6 Security Misconfigurations That Automated Scanners Actually Find in the Wild (And How to Fix Them)
Some links in this article may be affiliate links. We may earn a commission if you purchase through them, at no extra cost to you.
OWASP A05 (Security Misconfiguration) is the broadest category in the Top 10. It covers everything from default credentials to missing security headers to exposed debug endpoints. But when you point an automated scanner at a real target, which misconfigurations actually show up? We built SecurityClaw's security-misconfiguration-checker to detect the 6 most common ones. This article covers what each misconfiguration looks like in the wild, why it's dangerous, and exactly how to fix it.
Why A05 Is the Most Common Finding Category
Security misconfiguration isn't a single vulnerability — it's a class of mistakes that happen when software ships with insecure defaults and nobody changes them. Every web server, every framework, every CMS has default settings that prioritize ease of setup over security. When those defaults make it to production, they become attack surface.
The reason A05 is so common is that it's not a coding bug. You can write perfect application code and still be vulnerable if your web server has directory listing enabled, or your deployment script left a .env file in the web root, or your error handler shows stack traces to users.
These are configuration problems, not code problems. And they're the easiest class of vulnerability for automated scanners to detect — because the scanner just needs to request a known path and check the response. No injection, no authentication bypass, no complex logic. Just: "Is this file accessible? It shouldn't be."
1. Directory Listing Enabled
What It Looks Like
Request any directory path on the server. If you see an HTML page titled "Index of /uploads/" with a list of files, directory listing is enabled.
GET /uploads/ HTTP/1.1
Host: example.com
HTTP/1.1 200 OK
Content-Type: text/html
<html>
<head><title>Index of /uploads/</title></head>
<body>
<h1>Index of /uploads/</h1>
<pre>
<a href="invoice-2026-03.pdf">invoice-2026-03.pdf</a> 2026-03-15 14:22 1.2M
<a href="customer-export.csv">customer-export.csv</a> 2026-03-20 09:11 4.8M
<a href="backup.sql.gz">backup.sql.gz</a> 2026-03-22 02:00 89M
</pre>
</body>
</html>
Why It Matters
Directory listing turns your web server into a file browser. Every file in that directory — including ones you didn't intend to be public — is now discoverable. Attackers don't need to guess filenames; the server lists them.
Common finds in directory listings: database backups, configuration files, customer data exports, internal documentation, deployment scripts, and source code archives. One directory listing can expose more sensitive data than a SQL injection.
How to Fix It
Apache: Add to .htaccess or httpd.conf:
Options -Indexes
Nginx: Ensure autoindex is off (it's off by default, but check):
location / {
autoindex off;
}
Express.js: Don't use serveIndex middleware in production. If you're using express.static(), it doesn't enable directory listing by default — but check for any serve-index middleware in your stack.
Detection
The scanner requests /, /images/, /uploads/, /assets/, and /static/. If any response contains "Index of" in the body, it's flagged. Simple, reliable, zero false positives.
2. .env File Exposure
What It Looks Like
GET /.env HTTP/1.1
Host: example.com
HTTP/1.1 200 OK
Content-Type: text/plain
APP_NAME=MyApp
APP_ENV=production
APP_KEY=base64:xK9m2...
DB_CONNECTION=mysql
DB_HOST=rds-prod.abc123.us-east-1.rds.amazonaws.com
DB_DATABASE=myapp_prod
DB_USERNAME=admin
DB_PASSWORD=Pr0d_P@ssw0rd!2026
MAIL_PASSWORD=smtp_secret_key
AWS_ACCESS_KEY_ID=AKIA...
AWS_SECRET_ACCESS_KEY=wJalr...
Why It Matters
The .env file is the single most dangerous file that can be exposed on a web server. It typically contains every secret the application needs: database credentials, API keys, encryption keys, SMTP passwords, cloud provider credentials. One exposed .env file can give an attacker full access to the application's database, email system, and cloud infrastructure.
This happens because frameworks like Laravel, Rails, and Node.js use .env files for configuration, and deployment processes sometimes copy the entire project directory — including .env — into the web root.
How to Fix It
Immediate: Block access to dotfiles at the web server level:
Nginx:
location ~ /\. {
deny all;
return 404;
}
Apache:
<FilesMatch "^\.">
Require all denied
</FilesMatch>
Long-term: Don't put .env files in the web root at all. Use environment variables injected by your deployment system (AWS Parameter Store, Kubernetes secrets, Docker env vars). The .env file should exist only in development.
Detection
The scanner requests /.env and checks for common environment variable patterns: APP_KEY=, DB_PASSWORD=, AWS_SECRET_ACCESS_KEY=, SECRET_KEY=. If any pattern matches, it's flagged as HIGH severity. The check is passive — it only reads the response, never modifies anything.
3. .git Directory Exposure
What It Looks Like
GET /.git/HEAD HTTP/1.1
Host: example.com
HTTP/1.1 200 OK
Content-Type: text/plain
ref: refs/heads/main
Why It Matters
If /.git/HEAD is accessible, the entire Git repository is likely accessible. An attacker can reconstruct the full source code, commit history, and — critically — any secrets that were ever committed and later removed. "Removed" from Git doesn't mean gone; it means it's in the history.
Tools like git-dumper can reconstruct a full repository from an exposed .git directory. This gives the attacker:
- Complete source code (including server-side logic)
- Commit history (including "oops, remove API key" commits where the key is still in the diff)
- Branch names (revealing feature development and internal naming)
- Author emails (useful for social engineering)
How to Fix It
Same as .env — block all dotfiles at the web server level. The Nginx and Apache rules above cover this.
Additionally: Don't deploy by running git clone into the web root. Use a build step that copies only the built artifacts, not the .git directory. If you're using CI/CD, your deployment pipeline should never include .git in the deployed artifact.
Detection
The scanner requests /.git/HEAD and checks if the response starts with ref: refs/heads/. This is a definitive indicator — no other file would contain this string. Zero false positive risk.
4. Default Admin Panels Accessible
What It Looks Like
The scanner checks common admin paths and looks for login pages or admin interfaces:
/admin/— generic admin panel/phpmyadmin/— phpMyAdmin database management/wp-admin/— WordPress admin/manager/html— Apache Tomcat Manager
If any of these return a 200 status with a login form or admin interface, the path is accessible.
Why It Matters
Accessible admin panels are the starting point for brute-force attacks. phpMyAdmin with default credentials gives direct database access. Tomcat Manager with default credentials (tomcat/tomcat) gives remote code execution via WAR file deployment. WordPress admin with a weak password gives full site control.
The misconfiguration isn't that the admin panel exists — it's that it's accessible from the public internet without IP restrictions or additional authentication layers.
How to Fix It
IP restriction: Limit admin panel access to known IP ranges:
Nginx:
location /admin/ {
allow 10.0.0.0/8;
allow 192.168.1.0/24;
deny all;
}
VPN/Zero Trust: Put admin panels behind a VPN or zero-trust network access (ZTNA) solution. The admin panel should never be directly accessible from the public internet.
Remove defaults: If you're not using phpMyAdmin, remove it. If Tomcat Manager isn't needed, disable it. Every admin panel you don't need is attack surface you don't need.
Detection
The scanner requests each admin path and checks for 200 responses containing login form indicators (<form, password, login). A 200 response alone isn't enough — the content must indicate an actual admin interface. 403 and 404 responses are correctly ignored.
5. Verbose Error Pages
What It Looks Like
GET /nonexistent-page HTTP/1.1
Host: example.com
HTTP/1.1 500 Internal Server Error
Traceback (most recent call last):
File "/app/views.py", line 42, in get_page
page = Page.objects.get(slug=slug)
File "/usr/lib/python3.11/site-packages/django/db/models/manager.py", line 87
...
django.core.exceptions.ObjectDoesNotExist: Page matching query does not exist.
Environment:
SERVER_SOFTWARE: gunicorn/21.2.0
DJANGO_SETTINGS_MODULE: myapp.settings.production
DATABASE_URL: postgres://admin:password@db.internal:5432/myapp
Why It Matters
Verbose error pages leak internal information: framework version, file paths, database connection strings, environment variables, and sometimes credentials. This information helps attackers understand the technology stack and find specific vulnerabilities to exploit.
Django's debug mode, Rails' development error pages, and PHP's display_errors are the most common culprits. They're invaluable during development and catastrophic in production.
How to Fix It
Django: Set DEBUG = False in production settings. Configure a custom 500 error template.
Rails: Ensure config.consider_all_requests_local = false in production.rb.
PHP: Set display_errors = Off and log_errors = On in php.ini.
Node.js/Express: Don't pass error details to res.send() in production. Use a generic error handler:
app.use((err, req, res, next) => {
console.error(err.stack); // Log internally
res.status(500).send('Something went wrong'); // Generic response
});
Detection
The scanner triggers error responses (404, 500) and checks for stack trace patterns: Traceback, at line, Exception in, framework-specific error signatures, and server version strings. The check distinguishes between custom error pages (safe) and framework debug pages (vulnerable).
6. Backup File Exposure
What It Looks Like
GET /index.php.bak HTTP/1.1
Host: example.com
HTTP/1.1 200 OK
Content-Type: application/octet-stream
<?php
// Database configuration
$db_host = 'rds-prod.abc123.us-east-1.rds.amazonaws.com';
$db_user = 'admin';
$db_pass = 'Pr0d_P@ssw0rd!2026';
...
Why It Matters
Backup files are created by text editors (file.php~, file.php.swp), manual backups (file.php.bak, file.php.old), and deployment processes (web.config.old, .htaccess.bak). Unlike the original files, backup files are often served as plain text — meaning the web server sends the raw source code instead of executing it.
A .php file is executed by the PHP interpreter and only the output is sent to the client. A .php.bak file is served as-is — including all the source code, database credentials, and business logic.
How to Fix It
Block common backup extensions:
Nginx:
location ~* \.(bak|old|orig|save|swp|swo|tmp|temp|backup|dist|copy)$ {
deny all;
return 404;
}
Prevention: Configure your text editor to store swap/backup files outside the project directory. In Vim: set backupdir=~/.vim/backup//. In VS Code: this isn't an issue (no swap files in the project directory).
CI/CD: Add a deployment step that removes backup files from the build artifact. A simple find . -name "*.bak" -delete in your build script prevents this class of exposure entirely.
Detection
The scanner checks for common backup file patterns: index.php.bak, web.config.old, .htaccess.bak, config.php.orig, and similar. If any return a 200 response with content that looks like source code or configuration, it's flagged.
How to Scan for All 6
SecurityClaw's security-misconfiguration-checker skill checks all 6 misconfiguration types in a single scan. It's a passive skill — no injection, no state modification, no approval required. You can run it in CI/CD without worrying about breaking anything.
The skill makes approximately 20 HTTP requests per target (checking various paths and file patterns). Total scan time is typically under 5 seconds. Every finding includes the specific path, the evidence found, and the severity level.
For teams that want to check these manually, here's a quick checklist:
| Check | Request | Vulnerable If |
|---|---|---|
| Directory listing | GET /uploads/ | Response contains "Index of" |
| .env exposure | GET /.env | Response contains APP_KEY= or DB_PASSWORD= |
| .git exposure | GET /.git/HEAD | Response starts with ref: refs/heads/ |
| Admin panels | GET /admin/ | 200 response with login form |
| Verbose errors | GET /nonexistent | Response contains stack trace |
| Backup files | GET /index.php.bak | 200 response with source code |
If any of these checks return a positive result on your production server, fix it today. These are the lowest-hanging fruit in web security — easy to find, easy to exploit, and easy to fix.
The Bottom Line
Security misconfiguration (A05) is the most common vulnerability category because it doesn't require a coding mistake — just a deployment oversight. The 6 misconfigurations covered here are found on real production servers every day. They're all detectable with simple HTTP requests and fixable with a few lines of web server configuration.
The fix pattern is the same for all 6: block access to files and paths that should never be public. A few Nginx or Apache rules, applied once, prevent the entire class of vulnerability. The hard part isn't the fix — it's knowing to check in the first place.
That's what automated scanners are for.