CSP, CORS, and secure headers — Patterns & Anti‑Patterns — Practical Guide (Jul 12, 2026)
CSP, CORS, and secure headers — Patterns & Anti‑Patterns
Level: Intermediate
As of July 12, 2026
Prerequisites
This article assumes you have a solid understanding of HTTP(s) protocols, browser security concepts, and web application architecture. Familiarity with web server configuration, HTTP headers, and concepts like the Same-Origin Policy is essential. Experience with modern frontend frameworks (React, Vue, Angular) and backend languages will help contextualise the hands-on instructions.
The guidance applies to mainstream browsers as of mid-2026, notably Chrome ≥ v115, Firefox ≥ v115, Edge ≥ v115, and Safari ≥ v17. Older browsers may lack full support for newer security header directives like Cross-Origin-Opener-Policy or enhanced CSP Level 3 features.
Introduction
Modern web security involves layered defence strategies. Content-Security-Policy (CSP), Cross-Origin Resource Sharing (CORS), and other secure HTTP headers protect applications from diverse threats, including cross-site scripting (XSS), data exfiltration, clickjacking, and cross-origin attacks. Knowing when and how to apply these headers effectively — and recognising common misconfigurations — is crucial for maintaining robust security without sacrificing usability.
Hands-on Steps
1. Content-Security-Policy (CSP)
CSP controls which resources browsers can load and execute for your site. It is an effective safeguard against XSS and injection attacks. Modern CSP supports multiple directives covering scripts, styles, images, frames, workers, fonts, and even form submissions.
Basic example to allow scripts only from same origin and trusted CDNs:
Content-Security-Policy: default-src 'self';
script-src 'self' https://cdn.example.com;
style-src 'self' 'unsafe-inline';
img-src 'self' data:;
default-src 'self'restricts all resource fetches by default to your own origin.script-srcfurther allows scripts from your domain and a trusted CDN.style-srcallows inline styles (sometimes necessary) but best avoided if possible.img-src 'self' data:permits images from your origin and base64-encoded inline images.
Best practice patterns:
- Use CSP Level 3 directives
strict-dynamicin trusted environments to trust dynamically loaded scripts instead of whitelisting many CDNs. - Continue avoiding
'unsafe-inline'and'unsafe-eval'in production unless you have precise mitigation. - Enforce
object-src 'none'to disable Flash or other plugins. - Consider the
report-uriorreport-todirective to receive violation reports during rollout.
2. Cross-Origin Resource Sharing (CORS)
CORS is a browser-enforced mechanism to relax the same-origin policy for certain cross-origin HTTP requests. CORS is fundamental when your frontend and backend are served from different origins or when using third-party APIs.
Simple permissive example allowing a single trusted origin:
Access-Control-Allow-Origin: https://app.example.com
Access-Control-Allow-Methods: GET, POST, OPTIONS
Access-Control-Allow-Headers: Content-Type, Authorization
Access-Control-Allow-Credentials: true
Access-Control-Allow-Originmust specify the exact origin or*. Wildcard*does not work with credentials.Access-Control-Allow-Credentials: trueallows cookies or HTTP authentication credentials to be sent with cross-origin requests.- Preflight requests (OPTIONS) are used for some methods/headers; servers must handle those correctly.
When to use CORS vs JSONP/WebSockets: CORS is standard and secure for RESTful APIs. JSONP is considered legacy and insecure for modern applications. WebSockets manage cross-origin connections differently and have their own security models.
3. Other Secure Headers
Complement CSP and CORS with these headers for enhanced security:
- Strict-Transport-Security (HSTS): Enforces HTTPS connections. Use
max-ageof at least 6 months withincludeSubDomains. E.g.
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
- Referrer-Policy: Controls the amount of referrer information sent cross-origin.
- Permissions-Policy: (formerly Feature-Policy) restricts APIs like camera, microphone, fullscreen.
- X-Frame-Options: Prevents framing to avoid clickjacking. Modern CSP frame-ancestors directive is preferred.
- Cross-Origin-Opener-Policy (COOP) and Cross-Origin-Embedder-Policy (COEP): Help enable strict isolation for powerful features such as SharedArrayBuffer.
Common Pitfalls
CSP Misconfiguration
- Overusing
'unsafe-inline'ornonce/hashesinconsistently weakens protection. - Forgetting to block
object-srcorframe-srcleaves injection vectors. - No reporting endpoint means silent failures.
- Ignoring browser support variance (some legacy browsers ignore parts of CSP).
CORS Misconfiguration
- Using
Access-Control-Allow-Origin: *withAllow-Credentials: true— browsers reject this. - Allowing all origins without validation exposes APIs to abuse.
- Ignoring preflight OPTIONS requests causing client failures.
- Not limiting allowed HTTP methods increases attack surface.
Other Header Pitfalls
- Missing HSTS on HTTPS sites invites downgrade attacks.
- Setting conflicting headers like both
X-Frame-Optionsandframe-ancestorswith contradictory values. - Not testing in different browsers, especially Safari, which has quirks.
Validation
Use automated tools and manual testing to validate your headers:
- Browser Developer Tools: Inspect response headers and network requests.
- Security scanners: Tools like Mozilla Observatory, securityheaders.com, and SSL Labs test your headers comprehensively.
- Online CSP Evaluators: Google’s CSP Evaluator helps critique your policies.
- Manual penetration testing: Simulate XSS and cross-origin attacks in controlled environments.
- CSP violation reports: Collect and analyse violation data to iteratively improve policies.
Checklist / TL;DR
- CSP: Start with restrictive
default-src 'self', avoid'unsafe-inline', use nonce or hash directives for inline scripts if needed, blockobject-src. - CORS: Specify explicit origins, validate origin server-side, handle preflight requests, restrict allowed methods and headers.
- HSTS: Enforce HTTPS with a long max-age and include subdomains.
- Frame protection: Prefer CSP
frame-ancestorsoverX-Frame-Options. - Permissions: Minimise access to powerful browser APIs via Permissions-Policy.
- COOP/COEP: Employ for advanced security isolation if using SharedArrayBuffer or cross-origin isolation.
- Monitoring: Set up reporting endpoints and regularly review violation reports.