How can I prevent Drupal’s public file system from exposing private configuration files accidentally?
0 reputation · 17 Jun 2020, 18:34 UTC
0 reputation · 17 Jun 2020, 18:34 UTC
I want to ensure that files placed in Drupal’s public file system are not unintentionally served to visitors when they contain sensitive information such as configuration exports or logs.
The site uses the default public file path defined in admin/config/media/file-system, and I am unsure whether additional server‑level restrictions are required to block access to files with extensions like .yml, .yaml, .inc, or .log.
What core settings should be reviewed to guarantee that only intended assets are served from the public file system? Are there recommended .htaccess rules or server‑level directives to block access to files with certain extensions? How can I verify that no private files are leaked after applying these changes?
26525 reputation · 18 Jun 2020, 01:34 UTC
Drupal’s public file system lives inside the web‑root (e.g., sites/default/files). Any file that ends up there is reachable by a direct URL unless the web server is explicitly told otherwise. If a developer or an automated process uploads a configuration export, log, or any other non‑public file to that folder, visitors can download it.
admin/config/media/file-system and confirm the Public file path is what you expect (usually sites/default/files).settings.php the private path should point outside the document root, e.g.:
$settings['file_private_path'] = '/var/www/example.com/private';
This directory must be writable by the web‑server user but not directly accessible via HTTP.0755 and files 0644; the private folder should be 0750 and files 0640. Verify the owner matches the web‑server user (often www-data, apache, or nginx).php_flag engine off in the default files/.htaccess, but double‑check if you have overridden it.# Prevent access to sensitive file types in the public files directory.
Require all denied
# Deny PHP execution in the public files folder.
Require all denied
# Keep the default Drupal behaviour for assets.
location ~* ^/sites/default/files/.*\.(yml|yaml|inc|install|log|txt|conf|ini|env)$ {
deny all;
return 404;
}
location ~* ^/sites/default/files/.*\.(php|php5?)$ {
deny all;
return 404;
}
# Allow normal assets.
location ~* ^/sites/default/files/.*\.(css|js|png|jpg|jpeg|gif|svg|webp)$ {
try_files $uri =404;
}
Replace /sites/default/files with the actual public path if you use a different site directory.
curl -I https://example.com/sites/default/files/someconfig.yml and confirm a 403 or 404 status.admin/reports/status and verify the private path is listed as outside the docroot.403 entries on legitimate assets.drush core-status or drush php-eval "echo file_exists('/var/www/example.com/private/test.txt');" to ensure the private filesystem is functional.Do you currently host Drupal behind Apache, Nginx, or another web server? The exact directive syntax differs slightly between them, so confirming the server type will help tailor the rules precisely.
Use comments to ask for clarification. Post a solution as an answer.
26,525 reputation · 18 Jun 2020, 03:00 UTC
Drupal’s public files live under sites/*/files. If any sensitive file slips there, it’s reachable by URL. The first thing to confirm is that the file_private_path in settings.php points to a directory outside the web root and that the public path is a dedicated folder that never contains config.
Require all denied
location ~* ^/sites/.*/files/.*\.(yml|yaml|inc|log|env|ini|conf|install|txt)$ {
deny all;
return 404;
}test.yml in the public directory.curl -I http://example.com/sites/default/files/test.yml – you should see 403 Forbidden or 404 Not Found.drush status to confirm the private path is not the same as the public one.When these checks pass, you can be confident that accidental uploads of configuration files won’t be exposed to visitors.