Fixing Security Misconfiguration: Headers, Defaults and Errors
Many breaches don't need a clever exploit, just a setting left at the wrong value. Security misconfiguration is consistently near the top of the OWASP list.
1. Send security headers
Strict-Transport-Security: max-age=31536000; includeSubDomains
Content-Security-Policy: default-src 'self'; frame-ancestors 'none'; object-src 'none'
X-Content-Type-Options: nosniff
Referrer-Policy: strict-origin-when-cross-origin
Permissions-Policy: camera=(), microphone=(), geolocation=()
In Express, helmet() sets sensible defaults in one line. Check your site with a header scanner after deploying.
2. No debug mode in production
- Framework debug pages (Django
DEBUG=True, LaravelAPP_DEBUG=true) reveal source code, settings and sometimes secrets. - Disable or protect API explorers, GraphQL introspection and admin consoles on public deployments.
- Remove sample apps, test endpoints and default pages.
3. Generic error messages
app.use((err, req, res, next) => {
logger.error({ err, reqId: req.id });
res.status(500).json({ error: 'Something went wrong', requestId: req.id }); // no stack traces
});
4. Lock down cloud resources
- Storage buckets private by default, with account-level "block public access" settings on.
- Databases not reachable from the internet; use private networks.
- Least-privilege IAM roles instead of wildcard permissions.
- Scan infrastructure code with tools like Checkov or Trivy in CI.
5. Credentials and CORS
- Change or disable default accounts on every product you install.
- Never reflect any
Originback withAccess-Control-Allow-Credentials: true; list allowed origins explicitly.
6. Make it repeatable
Misconfiguration creeps in through manual changes. Keep server, container and cloud configuration in code, review it, and use the same hardened baseline for every environment.
Was this article helpful?
Comments
No comments yet. Have a question or a tip? Be the first to share it.