A02:2025 Security Misconfiguration
is insecure configuration in an application, framework, server, container, cloud service, database, or security header. The OWASP A02:2025 page notes that this category moved upward in the 2025 release as modern applications rely increasingly on configuration.
This risk matters because today’s web applications are not only application code. Reverse proxies, API gateways, object storage, container runtimes, Kubernetes manifests, framework settings, secret management, HTTP security headers, and cloud IAM policies all form the security surface. Even if the code is safe, production debug mode, unchanged default accounts, or public cloud buckets can become direct attacker entry points.
Root Cause
Security misconfiguration often comes from missing secure defaults rather than a code bug. Examples include:
- Debug mode left enabled in production
- Default admin accounts or default passwords
- Unnecessary services, ports, endpoints, or sample applications
- Directory listing enabled
- Missing or unsafe security headers
- Public cloud storage buckets
- XML parsers configured in a way that permits XXE
- Error messages exposing stack traces, paths, or secrets
HTTP Header Example
Unsafe response:
HTTP/1.1 200 OK
Server: Apache/2.4.49
X-Powered-By: Express
Content-Type: text/htmlSafer response:
HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
Strict-Transport-Security: max-age=31536000; includeSubDomains
X-Content-Type-Options: nosniff
Content-Security-Policy: default-src 'self'
Referrer-Policy: no-referrer
Permissions-Policy: geolocation=()These headers do not make the application secure by themselves, but they reduce browser-side risk and create safer defaults.
Debug Mode Scenario
Vulnerable behavior:
GET /api/profile?debug=true HTTP/1.1
Host: vulnerable-app.example
HTTP/1.1 500 Internal Server Error
Traceback (most recent call last):
File "/srv/app/profile.py", line 42, in get_profile
DatabaseError: relation "users_private" does not exist
DB_HOST=10.0.2.15
DB_USER=app_readonlyThis response gives the attacker information about the technology stack, internal IPs, file paths, and data structure. That information can make later injection or access control testing easier.
Secure Configuration Approach
Configuration security should not depend only on a manual checklist. In modern applications, configuration should be managed as follows:
- Infrastructure as Code files go through review
- Production and staging use the same security baseline
- Secrets are not stored in repositories or images
- Container images include only minimal packages
- Default accounts and sample applications are removed
- Security headers are applied centrally at the reverse proxy or application layer
- Configuration drift is checked automatically
Testing Approach
Security misconfiguration testing should cover:
- HTTP response headers
- Directory listing and backup file exposure
- Default credential attempts
- Cloud object storage permissions
- Verb tampering and unnecessary methods
- Error handling and debug output
- TLS protocol and cipher configuration
- Admin panels, actuator endpoints, metrics, and health endpoints
Defensive Controls
- Create a repeatable hardening process for every environment.
- Remove unnecessary features, services, packages, and sample files.
- Apply and verify a secure baseline through automation.
- Disable production debug output.
- Use centralized error handling.
- Use a platform secret manager or vault for secrets.
- Restrict cloud IAM and bucket policies with least privilege.
Security misconfiguration may look like a small setting, but it often becomes the first step in an attacker’s discovery and privilege expansion chain.