This guide is for developers, system administrators, and technical managers responsible for web server security. Directory listing and sensitive file exposure are among the most common — and most preventable — web vulnerabilities. When a web server reveals its directory structure or accidentally exposes configuration files, backup archives, or environment variables, attackers gain a free map to your application's internals. Follow these steps to close those gaps immediately.
Understand What You're Protecting Against
Before applying fixes, it's important to understand exactly what these vulnerabilities look like in practice. Directory listing occurs when a web server displays the contents of a directory as a browsable HTML page because no index file (e.g. index.html) exists. Sensitive file exposure happens when files such as .env, config.php, database dumps, or .git folders are accessible via a direct URL. Both issues provide attackers with credentials, source code, internal paths, and other intelligence that accelerates further attacks.
- Search your live site for URLs ending in
/that return a directory listing page (look for "Index of /" in the page title). - Try accessing common sensitive paths directly:
/.env,/config.php,/wp-config.php,/.git/config,/backup.zip,/database.sql. - Check subdomains and staging environments — they are frequently overlooked and left misconfigured.
- Use Sensagraph's automated scans to detect exposed directories and sensitive files across your entire web presence.
Disable Directory Listing on Your Web Server
Every major web server has a straightforward way to turn off directory listing. Apply the configuration that matches your stack and verify the change is live before moving on.
- Apache: Add or confirm the following in your
httpd.conf, virtual host block, or.htaccessfile:Options -Indexes. This single directive removes the ability for Apache to generate directory listings. - Apache (.htaccess): If you cannot edit the main config, place a
.htaccessfile in every directory that should not be browsable containing:Options -Indexes. - Nginx: Inside the relevant
serverorlocationblock, ensureautoindexis disabled:autoindex off;. This is the default, but confirm it has not been turned on inadvertently. - IIS: In IIS Manager, select your site, open "Directory Browsing," and click "Disable" in the Actions panel. Alternatively set
<directoryBrowse enabled="false" />inweb.config. - Caddy: Do not include the
file_server browsedirective; usefile_serveralone, which serves files without listing directories. - After making changes, test by navigating to an empty directory in your browser — you should receive a 403 Forbidden or 404 Not Found, not a file list.
Block Access to Sensitive Files and Directories
Disabling directory listing is necessary but not sufficient. Attackers can still request sensitive files directly if they know — or can guess — the filename. You must explicitly deny access to known dangerous file types and directories.
- Apache (.htaccess or httpd.conf): Add rules to deny access to dangerous file extensions and dotfiles:
<FilesMatch "(\.env|\.git|\.htaccess|\.htpasswd|\.DS_Store|composer\.json|composer\.lock|package\.json|yarn\.lock|\.bak|\.sql|\.log|\.config)$">
Require all denied
</FilesMatch> - Nginx: Add location blocks to deny access to sensitive files:
location ~* /\.(?!well-known) { deny all; }
location ~* \.(env|git|bak|sql|log|config|json|lock)$ { deny all; } - Block the
.gitdirectory entirely — an exposed.gitfolder allows full source code reconstruction. - Block access to
composer.json,composer.lock,package.json, andyarn.lock— these reveal your dependency tree and known vulnerable versions. - Block common backup file extensions:
.bak,.old,.orig,.tmp,.swp,.~. - Block
.logfiles — application logs frequently contain stack traces, user data, and internal IP addresses. - Restrict the
/vendordirectory if it falls inside your web root (move it above the web root if possible).
Move Sensitive Files Outside the Web Root
The most robust protection for configuration and secret files is to remove them from any location the web server can serve. Files outside the web root are structurally inaccessible to HTTP requests, regardless of server configuration errors.
- Store
.envfiles, database configuration, and API keys in a directory one level above the web root (e.g. above/var/www/html/or/public_html/). - In your application code, use relative paths or environment variables to reference these files rather than hard-coded absolute paths.
- Move the Composer
vendor/directory above the web root and adjust your autoloader path accordingly. - Store uploaded user files in a directory outside the web root and serve them through a controller script that enforces authentication and file-type validation.
- Review your deployment pipeline to ensure build artifacts, test fixtures, and seed data files are never deployed to the public web root.
Audit File System Permissions
Even if web server rules block access, overly permissive file system permissions can expose files to other processes or users on the same server. Apply the principle of least privilege at the OS level.
- Web server processes (e.g.
www-data,nginx,apache) should have read-only access to application files — never write access unless explicitly required (e.g. an upload directory). - Set configuration files to mode
600(owner read/write only) or640(owner read/write, group read) so the web server process cannot write to them. - Set directories to mode
750or755as appropriate; never777. - Run
find /var/www -perm -o+w(or your web root path) to identify world-writable files and correct them immediately. - Ensure
.envand other secret files are owned by your deploy user and not readable by the web server process at all — use a secrets manager or environment injection instead of file-based secrets where possible. - On shared hosting environments, verify that other accounts cannot read your files through misconfigured
open_basedirorsuEXECsettings.
Remove Unnecessary Files from the Web Root
Developer convenience files, temporary test pages, and forgotten backups are a persistent source of sensitive file exposure. Establish a clean-up habit as part of every deployment.
- Remove all
phpinfo()pages, test scripts (e.g.test.php,info.php), and installation wizards after initial setup. - Delete database dump files (
*.sql,*.dump) from the web root immediately after use — store them securely off-server. - Remove CMS installation directories (e.g. WordPress's
/wp-admin/install.php, Joomla's/installation/) once setup is complete. - Add a pre-deployment checklist or CI/CD pipeline step that scans for and blocks deployment of common sensitive filenames.
- Audit your web root for editor swap files (
.swp,~filename) left by Vim, Emacs, or other editors during in-place editing on the server. - Add
.git/,*.env,*.bak,*.sql, and*.logto your.gitignoreto prevent accidental commits — but remember.gitignoredoes not protect files already in the repository.
Implement Custom Error Pages
Default server error pages for 403 Forbidden and 404 Not Found often reveal the web server name, version, and operating system. Replace them with custom pages that return the correct HTTP status code but no server details.
- Apache: Add
ErrorDocument 403 /errors/403.htmlandErrorDocument 404 /errors/404.htmlto your configuration. - Nginx: Use
error_page 403 /errors/403.html;anderror_page 404 /errors/404.html;in your server block. - Ensure your custom error pages themselves do not expose internal paths, stack traces, or application version numbers.
- Suppress the
ServerHTTP response header or replace it with a generic value: in Apache useServerTokens ProdandServerSignature Off; in Nginx useserver_tokens off;. - Disable
X-Powered-Byheaders: in PHP setexpose_php = Offinphp.ini; in Express.js callapp.disable('x-powered-by').
Continuously Monitor and Scan
One-time hardening is not enough. New deployments, CMS updates, and developer mistakes can re-introduce exposed files at any time. Build ongoing verification into your security workflow.
- Schedule regular automated scans of your web application to detect newly exposed directories, backup files, and configuration files — Sensagraph performs these checks continuously and alerts you when issues arise.
- Integrate a security scan step into your CI/CD pipeline so that sensitive file patterns are flagged before they reach production.
- Review web server access logs periodically for requests to sensitive paths (e.g.
/.env,/.git/config,/backup.zip) — repeated attempts signal active reconnaissance. - After every major deployment or infrastructure change, re-run your directory listing and sensitive file checks manually.
- Subscribe to security advisories for your CMS, framework, and server software — patches sometimes change default configurations.
- Include directory listing and sensitive file checks in your internal penetration testing or bug bounty scope.