Application Security In progress
Intermediate 15 min read Application Security
Security Headers and CSP
Enlist the browser itself in your security team: HSTS, X-Content-Type-Options, Referrer-Policy, and a properly-shaped Content-Security-Policy.
CSPHSTSsecurity headersX-Content-Type-OptionsReferrer-PolicyCSP violations
Introduction
What is this?
Security headers are HTTP response options that turn browser-side protections on: transport policy, content restrictions, and leak-reduction defaults that cost nothing to add and a fortune to skip.
Motivation
Why do you need it?
- A good CSP turns a successful XSS from 'full compromise' into 'a browser error', capping the attack at the front door.
- Headers are a five-minute change with audit visibility — the highest-value-per-hour control an app has.
- Auditors check them; penetration-test reports routinely open with 'Missing security headers'.
Think about it
Mental model
Imagine
A visiting guest's house rules
Think of
A written door policy on the landlord's side
Instead of trusting every visitor to behave, the building enforces the rules itself.
Mechanics
How it works
- HSTS tells browsers: always use HTTPS for this domain, never downgrade — preventing protocol-downgrade and cookie-transit attacks.
- CSP is a allow-list for script/style/frame/image sources; browsers refuse anything not named, so injected <script> dies.
- X-Content-Type-Options: nosniff stops MIME-sniffing confusion; Referrer-Policy trims the URL leaked to third parties.
- Headers ship per-response; frameworks emit them centrally (middleware) so drift is visible in CI.
A response wearing its full header set
HSTS'always https' for the domain
CSPallow-list for scripts/styles
X-Contentno MIME sniffing
Referrerminimal referrer leakage
FrameX-Frame-Options / frame-ancestors
Real world
In production
- An e-commerce deployment added a strict CSP and their stored-XSS bounty submissions dropped to near zero.
- A bank enabled HSTS with includeSubDomains and saw report-only HSTS helps kill downgrade in the logs.
- A media site set Referrer-Policy to strict-origin-when-cross-origin, trimming analytics referrer noise by half.
Guidelines
Best practices
- Start CSP in report-only mode, collect violation reports for a week, then enforce the final policy.
- Set HSTS with preload intent only after confirming you can serve HTTPS forever — preload is irreversible.
- Centralize headers in middleware so every route inherits them, then assert their presence in CI.
- Keep third-party script domains in the CSP allow-list explicit; wildcards make the policy meaningless.
Watch out
Common mistakes
- Writing a CSP with 'script-src *' which is no CSP at all.
- Using 'unsafe-inline' for scripts, gracefully deleting the XSS defense in one attribute.
- Enforcing a strict CSP before testing, breaking analytics/injections in production.
- Setting HSTS preload without HTTPS-everywhere, then watch visitors and SEO both fail.
When things break
Debugging tips
- Read the CSP violation report from your report URI — it names the exact blocked source URL.
- Use your browser's console (CSP errors are loud) to debug in report-only first.
- If inline styles break, prefer hashes/allow-list nonces over 'unsafe-inline'.
Security
Security considerations
- Assert headers in your CI pipeline, not just at manual audit time; the suite should re-run them each release.
- Third-party scripts holding a CSP allow-list entry are a supply-chain trust decision; audit their ownership.
Interviews
Interview checkpoint
Practice
Hands-on lab
Ship Headers from a Local App and Watch the Browser Enforce Them
40 min · intermediate
Objectives
- Send HSTS, nosniff, frame, and Referrer-Policy headers from a small lab server.
- Add a strict CSP in report-only and collect a violation.
- Read your own violation report to write the enforcement policy.
Ship Headers from a Local App and Watch the Browser Enforce Them
40 min · intermediate
0/3 steps
0%
sandbox · Linux sandbox
$
Try these commands
Test yourself
Quick quiz
0/2
1
'script-src *' is considered...
2
HSTS is issued via which response header?
Go deeper