Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

LaraBABA's avatar

Secure files vs non secure files - Best way to go about

Hello,

I have a question regarding 2 types of PDF I need to upload to a website.

PDF type 1 can be public PDF type 2 should be very secure and only accessible via the admin interface.

ie:If you go from the web and try to access the file, you cannot and must not!

I will install Laravel below the public_html, add the public folder in the public_html and then symlink the storage below root to the public above the root.

My question is..... How to protect the secured PDFs from the public PDF folder?

Both will be uploaded from the admin interface but obviously into 2 separate folders /pdf/Secure /pdf/public . I would like to know more about people who had to do something similar please, which security implementation or method did you use to have 2 uploads completely independent from each other when it comes to security.

Thank you.

0 likes
17 replies
LaraBABA's avatar

Thanks for the reply. I see so you would still symlink as:: ln -s/home/account/laravel/storage/app/public/ /home/account/public_html/api/storage

But upload the private files to: ln -s/home/account/laravel/storage/app/private/

Am I correct?

Thank you

Sinnbeck's avatar

Correct. Simply make a disk that isnt symlinked.

Take a look at the filesystems.php file in the config directory. Here is an example.

'admin' => [
            'driver' => 'local',
            'root' => storage_path('app/public'),
        ],

Get it using

Storage::disk('admin')->path($filename);
1 like
LaraBABA's avatar

Beautiful, thank you so much! Super helpful.

dan3460's avatar

I had a customer some time ago that wanted the private pdf displayed on the browser. I solved the problem by copying the file to the public folder and deleting the file just a few seconds after was uploaded to the browser with a dedicated queue.

LaraBABA's avatar

But don't you think the way Sinnbeck explained it is perfect without a queue? Think about it.

A middleware with Auth that detects your role. The private file stays below the public_html (therefore absolutely not public). You create a storage location there and only pass the private file to a user with the right role. Using this superb solution, you can safely view your files without a single issue. I really love the solution!

dan3460's avatar

Yes the solution is good. I just was pointing out the special request. The customer did not wanted the file being downloaded and then opened. He wanted for the users to see the file in the browser. It was middleware so only authorized users could view the files. In any case this was a few years back it may be another solution now.

LaraBABA's avatar

But it is my understanding that if you read something in the browser, it is already downloaded in the cache of the browser.

LaraBABA's avatar

Thanks, are you sure that the point 2 of the first link you gave me is right? I have always heard of never uploading sensitive data to a public folder, no matter how long the files names are.

jlrdw's avatar

I myself would use a service for secure client files. Something like dropbox, or another. I was just sharing a past link that discussed the subject.

1 like
LaraBABA's avatar

Oh I see, thanks for your reply. But do you agree that sharing anything in a public folder(even with difficult file names) is a bad idea right? I just checked this...wow, the number of ways there is to see the ocntent of public folder, it is scary: https://owasp.org/www-community/vulnerabilities/Unrestricted_File_Upload

I have also found a tool called DirBurster that brute force/search for directory names on websites and try to discover the file names. It is amazing how many clever ways there are to discover the content of a folder.

jlrdw's avatar

But do you agree that sharing anything in a public folder(even with difficult file names) is a bad idea right?

Yes, double yes. Some clients may have sensitive documents they have stored.

Storing to folders that is not available to the web, and only serving if passed authorization can also work, but it has a learning curve and a little more work (coding) involved.

A file like:

 <?php
$basedir = path to base directory (above webroot)
$imagedir = $_GET['dir'];  // path to users  images
$image = $_GET['img'];
$file = $basedir.'/'.$imagedir.'/'.$image;

header('Content-Type: image/jpeg');
ob_clean();

readfile($file);
exit(0);

?> 

Could be used to serve images, used in a img src tag. I have never tried it with files.

Just a simplified example, as there are more header options to take into account.

The only very secure way I know of is a service and using their api, like mentioned in my other answer.

I don't think (not 100 percent sure) , there is anything built into laravel, or any framework that 100 percent protects users files. I have never tried to encrypt a pdf or word document, but you could see how encrypting works with various file types. It may be the answer.

1 like
LaraBABA's avatar

Thanks, great to know. Yes your example is in pure PHP without Laravel. But I think the answer of Sinnbeck in the thread above would be enough to secure the file, Laravel will then take care of the rest.

dan3460's avatar

I don't know a way to display something on a browser that it is not in a public location. In my case the sensitive file was live on the public location for about 2 seconds. We also deployed software that checked for any malware that may be monitoring the public folder. Again this was a specific request by this specific client, the file will be many times more secured if it did not touched the public folder for even a microsecond.

patrickcm's avatar

Just keep in mind

$basedir = path to base directory (above webroot)
$imagedir = $_GET['dir'];  // path to users  images
$image = $_GET['img'];
$file = $basedir.'/'.$imagedir.'/'.$image;

header('Content-Type: image/jpeg');
ob_clean();

readfile($file);
exit(0);

?>

is a massive security hole. I'm sure you are aware @jlrdw but just making sure OP knows that the input needs to be heavily sanitized.

Please or to participate in this conversation.