Security misconfiguration: what it is, with real examples.
A security misconfiguration is a weakness in how software is set up rather than in its code: a default left switched on, a file left in the wrong place, a feature nobody turned off. Nothing has to be hacked — the server simply hands over what it was never meant to.
In the OWASP Top 10
OWASP ranks security misconfiguration A02:2025, second of the ten most critical web application risks — up from fifth (A05) in the 2021 edition. OWASP reports that every application in its data set showed some form of misconfiguration. The category maps 16 weaknesses, among them CWE-16 (Configuration) and CWE-611 (XML external entities, which many XML parsers allow by default).
Examples
| Misconfiguration | What it gives away | Checked? |
|---|---|---|
A .env file inside the web root | Database passwords, API keys, signing secrets | Yes — fix |
Backup and editor copies (.env.bak, wp-config.php.bak) | The same secrets, as plain text | Yes — fix |
PHP not handling .php files after an upgrade | The source of wp-config.php and every other script | Yes — fix |
A .git or .svn folder deployed with the site | Source code and its history | Yes — fix |
A leftover phpinfo() page | Server configuration, environment variables, cookies | Yes — fix |
| Logs in the web root | Queries, tokens, stack traces | Laravel’s only |
Cloud keys and OS files (.aws/credentials, .DS_Store) | AWS access; names of hidden files | Yes — fix |
| Debug mode or detailed errors in production | Configuration, paths and versions on error pages | No |
| Directory listing switched on | Every file in a folder, backups included | No |
| Default passwords, sample apps and admin tools left installed | A way in that needs no exploit | No |
Missing security headers (CSP, HSTS, X-Content-Type-Options) | Easier cross-site scripting, clickjacking and downgrade attacks | No |
| Cloud storage shared publicly | Whatever is in the bucket | No |
| Database or admin ports open to the internet | Login prompts for brute-forcing | No |
“Checked?” means DotenvScan tests for it. It covers the first group — files that should never be downloadable, including Laravel’s log but not WordPress’s debug.log — because those are the misconfigurations that leak secrets outright. The rest need other checks, below.
Why it happens
- Defaults are made for getting started. Debug output, sample pages and open permissions help on day one and are forgotten by day two.
- Servers drift. Settings made by hand on one server are missing on the next, or on the staging copy that went live.
- Upgrades and moves break things quietly. A PHP upgrade that leaves the handler unconfigured, or a move from Apache to nginx, which ignores
.htaccessand its protections. - Nobody looks from the outside. The site works, so nobody checks what else it serves.
How to prevent it
- Serve only what must be public. Point the document root at the app’s public folder, and block dotfiles and backup copies: tested rules for nginx, Apache and Caddy.
- Make hardening repeatable. Build servers and containers from code — configuration management, images, infrastructure as code — so every environment is set up the same way, differing only in its secrets.
- Keep the platform minimal. Remove sample apps, test pages, unused modules and default accounts.
- Turn off debug output in production (
APP_DEBUG=false,WP_DEBUG_DISPLAYfalse,display_errors = Off) and log errors somewhere private. - Send security headers, and turn off directory listing (
autoindex offin nginx,Options -Indexesin Apache). - Avoid long-lived secrets where you can: roles and short-lived credentials instead of keys in files.
- Check after every deploy and server change, automatically if possible. OWASP’s own advice is to verify configuration in every environment.
How to test for it
- Exposed files: run DotenvScan, or by hand
curl -sI https://example.com/.env— anything but 403 or 404 needs a look. - Security headers:
curl -sI https://example.com | grep -iE 'strict-transport|content-security|x-content-type'. - Directory listing: open a folder URL such as
/wp-content/uploads/; a list of files means it is on. - On the server: ServerSecretVault finds every
.env,wp-config.phpand backup copy across all sites, andnginx -Tprints the full nginx configuration to review. - Broader scanners such as ZAP and Nikto test far more, including code flaws, and send far more requests. Use them only on sites you are allowed to test.