Security Misconfiguration
Fix permissive CORS, verbose errors, missing security headers, and insecure defaults in API deployments.
URL: trusteed.io/academy/api-security/security-misconfiguration
Security Misconfiguration is the broadest category in the OWASP API Security Top 10 — covering permissive CORS policies, verbose error messages that leak internal details, missing security headers, unnecessary HTTP methods left enabled, default credentials or sample data left in place, and any gap between an environment's actual configuration and its intended, hardened state. It's rarely a single dramatic flaw and almost always an accumulation of small, individually-reasonable-looking defaults.
What Is Security Misconfiguration?
This category covers configuration decisions rather than logic bugs: a CORS policy that reflects any origin while also allowing credentials, turning a same-origin protection into no protection at all; stack traces or internal error details returned to clients in production, which hand an attacker a roadmap of your stack, file paths, and query structure; missing security headers (Strict-Transport-Security, X-Content-Type-Options, Content-Security-Policy) that would otherwise mitigate a range of client-side attacks; debug/admin interfaces left enabled or reachable in production; and default accounts, sample data, or example endpoints from a framework's scaffolding never removed before deployment.
Why AI Coding Assistants Get This Wrong
Development-friendly defaults are, by design, permissive — cors({ origin: '*' }), verbose error logging to the response body, debug mode enabled — because they make local development faster and less frustrating. These defaults are also exactly what most quick-start tutorials and boilerplate generators demonstrate, since a working local demo is the point. The gap appears when that same permissive configuration ships to production unchanged, which happens easily when environment-specific configuration isn't treated as a first-class, explicitly reviewed step.
Vulnerable Pattern
// Wildcard CORS combined with credentials — effectively no origin protection
app.use(cors({ origin: '*', credentials: true }));
// Generic error handler that leaks stack traces to the client
app.use((err, req, res, next) => {
res.status(500).json({ error: err.message, stack: err.stack }); // leaks internals
});
// Debug route left reachable without any guard
app.get('/debug/env', (req, res) => res.json(process.env)); // leaks secrets directly
Secure Pattern
const helmet = require('helmet');
// Explicit allow-list, never wildcard combined with credentials
const ALLOWED_ORIGINS = ['https://app.example.com', 'https://admin.example.com'];
app.use(cors({
origin: (origin, callback) => {
if (!origin || ALLOWED_ORIGINS.includes(origin)) return callback(null, true);
callback(new Error('Not allowed by CORS'));
},
credentials: true,
}));
app.use(helmet()); // sets HSTS, X-Content-Type-Options, and other security headers by default
// Environment-aware error handling — details only in development
app.use((err, req, res, next) => {
console.error(err); // full detail logged server-side, not returned to client
const isDev = process.env.NODE_ENV === 'development';
res.status(err.statusCode || 500).json({
error: isDev ? err.message : 'Internal server error',
...(isDev && { stack: err.stack }),
});
});
// No debug routes in the deployed application at all — gated entirely out of production builds
if (process.env.NODE_ENV === 'development') {
app.get('/debug/env', authenticate, requireAdmin, (req, res) => {
res.json({ nodeVersion: process.version }); // never dump raw env vars, even in dev
});
}
Copy-Paste Rules for Cursor, Claude Code, and Codex
---
description: Security misconfiguration prevention — CORS, error handling, headers, environment defaults
alwaysApply: true
---
# Security Misconfiguration Rules
- Never configure CORS with `origin: '*'` when `credentials: true` is also
set — this combination effectively disables origin protection entirely.
Use an explicit allow-list of permitted origins.
- Never return stack traces, internal file paths, database error details,
or raw exception messages to the client in a production build. Log full
detail server-side; return a generic error message to the client, gated
by an explicit environment check.
- Apply a security headers middleware (e.g., Helmet for Express, or
framework-equivalent) to every application by default — do not treat
security headers as optional or add them only when asked.
- Never leave debug, admin, or diagnostic endpoints reachable in a production
build without authentication and authorization — and prefer excluding them
from production builds entirely rather than gating them by environment
variable alone.
- Never dump raw environment variables, configuration objects, or credential
stores in any API response, in any environment.
- Explicitly disable HTTP methods that a given route doesn't need to support
(e.g., disallow `TRACE`, `OPTIONS` where not required, on routes that
don't need them).
- When generating configuration for CORS, error handling, or headers, always
produce environment-aware logic (development vs. production) rather than
a single, permissive default intended to be "hardened later."
- Remove or explicitly guard any sample data, default accounts, or
boilerplate scaffolding endpoints before code is considered complete for
a production-bound feature.
Verification Checklist
- CORS configuration uses an explicit origin allow-list; wildcard is never combined with credentials
- Error responses in production never include stack traces or internal implementation details
- Security headers middleware is applied to all routes
- No debug/diagnostic endpoints are reachable in production without authentication
- No environment variables, secrets, or configuration objects are exposed via any endpoint
- Unnecessary HTTP methods are disabled per route
- Configuration is reviewed per environment (dev/staging/production) as an explicit deployment step
- Continuous configuration scanning validates production settings match intended hardened state — see Trusteed's cloud security and compliance platform and WAAP for ongoing misconfiguration detection
Frequently asked questions
Isn't returning detailed error messages helpful for debugging?
It's helpful for the developer during local development, which is exactly why it should be gated by an explicit environment check — detailed errors in production help attackers far more than they help legitimate users, who never need to see a stack trace.
Do security headers actually stop attacks, or are they just best practice?
Security headers like Content-Security-Policy and X-Content-Type-Options actively mitigate specific attack classes (XSS execution, MIME-sniffing-based attacks) at the browser level — they're a meaningful, low-cost defensive layer, not merely a compliance checkbox.
How does Security Misconfiguration relate to Improper Inventory Management (API9)?
They're closely related but distinct: Security Misconfiguration is about a known, deployed endpoint or environment having an insecure configuration. Improper Inventory Management (API9) is about not knowing an endpoint or environment exists at all — an old API version or forgotten staging deployment that's misconfigured *and* unmonitored.