Audit Missing Security Headers
Scan responses for missing HSTS, CSP, X-Content-Type-Options, and frame protections, then fix them with a middleware.
Task
Check production responses for required security headers and apply a consistent middleware.
When to use this
Security review flags absent headers that browsers rely on to mitigate sniffing and framing attacks.
Prerequisites
- curl for header inspection
- Access to the web server or framework
- A list of required headers
Steps
1. Scan the key responses for required headers.
for url in / /login /api/health; do
echo "== $url"
curl -sI https://app.example.com$url | grep -iE 'strict-transport|content-security|x-content-type|x-frame|referrer'
doneExpected output: Missing headers are visible per URL, exposing inconsistent coverage.
2. Set them centrally in middleware.
app.use((req, res, next) => {
res.set('Strict-Transport-Security', 'max-age=31536000; includeSubDomains; preload');
res.set('X-Content-Type-Options', 'nosniff');
res.set('X-Frame-Options', 'DENY');
res.set('Referrer-Policy', 'strict-origin-when-cross-origin');
next();
});Expected output: Every response carries the headers consistently instead of only some routes.
Troubleshooting
Problem
CSP breaks inline scripts
Solution
Introduce CSP in report-only mode, collect violations, then enforce with nonces.
Problem
Header duplicated
Solution
Set headers in one layer; the proxy and the app can both add them.
Limitations
- Headers alone do not fix injection flaws.
- HSTS preload is hard to undo.
- CSP requires ongoing maintenance.
What this recipe does
Check production responses for required security headers and apply a consistent middleware.
Security review flags absent headers that browsers rely on to mitigate sniffing and framing attacks.
Prerequisites
- curl for header inspection
- Access to the web server or framework
- A list of required headers
Procedure
- Scan the key responses for required headers.
for url in / /login /api/health; do
echo "== $url"
curl -sI https://app.example.com$url | grep -iE 'strict-transport|content-security|x-content-type|x-frame|referrer'
done
Expected result: Missing headers are visible per URL, exposing inconsistent coverage.
- Set them centrally in middleware.
app.use((req, res, next) => {
res.set('Strict-Transport-Security', 'max-age=31536000; includeSubDomains; preload');
res.set('X-Content-Type-Options', 'nosniff');
res.set('X-Frame-Options', 'DENY');
res.set('Referrer-Policy', 'strict-origin-when-cross-origin');
next();
});
Expected result: Every response carries the headers consistently instead of only some routes.
How to confirm it worked
Run the commands above and confirm every expected result in order. If a step does not produce the stated output, use the troubleshooting notes before continuing. A passing run shows every key response includes the required headers and enforcing CSP no longer produces new violations.
Troubleshooting
CSP breaks inline scripts — Introduce CSP in report-only mode, collect violations, then enforce with nonces.
Header duplicated — Set headers in one layer; the proxy and the app can both add them.
Limitations
- Headers alone do not fix injection flaws.
- HSTS preload is hard to undo.
- CSP requires ongoing maintenance.