Implementation guide
HTTP security headers: a practical guide
Security headers tell browsers how to handle transport, resources, framing, referrer data, and powerful features. They are small configuration changes with useful defensive value, but the safest policy is one that matches how your application actually works.
Which security headers should you prioritize?
Start with controls that address clear browser risks and are widely supported. Validate each change in a test environment, because strict values can block legitimate scripts, frames, assets, or integrations.
| Header | Primary purpose | Practical starting point |
|---|---|---|
Strict-Transport-Security | Keep future browser requests on HTTPS. | max-age=31536000 after HTTPS is stable. |
Content-Security-Policy | Restrict where executable and embedded resources may load from. | Build a site-specific policy; observe it in report-only mode first. |
frame-ancestors or X-Frame-Options | Reduce clickjacking by controlling who may frame the page. | frame-ancestors 'none' when framing is never required. |
X-Content-Type-Options | Tell browsers not to reinterpret declared content types. | nosniff. |
Referrer-Policy | Limit URL information sent in the Referer header. | strict-origin-when-cross-origin. |
Permissions-Policy | Limit access to browser features such as camera and geolocation. | Disable features the application does not use. |
1. Enforce HTTPS with HSTS
HTTP Strict Transport Security tells a browser that has already reached your site over HTTPS to use HTTPS for future requests. It helps prevent protocol downgrade and accidental HTTP navigation, but it does not replace a server-side HTTP-to-HTTPS redirect.
Strict-Transport-Security: max-age=31536000 includeSubDomains only when every current and future subdomain is available over HTTPS. Submit
to the preload list only after understanding the long-lived operational commitment and meeting its rules.2. Build a Content Security Policy around the application
CSP can reduce the impact of cross-site scripting and unwanted resource loading. It is also the header most likely to break a site when copied blindly. Inventory required scripts, styles, images, fonts, frames, and API connections before enforcing a policy.
Content-Security-Policy-Report-Only: default-src 'self'; object-src 'none'; base-uri 'self'; frame-ancestors 'none' A report-only policy produces violation reports without blocking resources. Use those observations to add only
the origins or nonces the application needs, then move to an enforced Content-Security-Policy.
Avoid treating broad sources or 'unsafe-inline' as a permanent shortcut where a nonce- or
hash-based policy is feasible.
3. Control framing and MIME sniffing
CSP's frame-ancestors directive is the modern way to control which sites may embed a page. An X-Frame-Options: DENY or SAMEORIGIN header can provide a legacy fallback. Choose values
that preserve intentional embeds, payment flows, and authentication integrations.
Content-Security-Policy: frame-ancestors 'none'
X-Frame-Options: DENY
X-Content-Type-Options: nosniff nosniff works best when assets also have accurate Content-Type response headers. Fix
incorrect MIME types rather than removing the protection when a browser blocks a resource.
4. Limit referrer data and browser features
Referrer-Policy controls how much of the current URL is sent on navigation. A balanced baseline is strict-origin-when-cross-origin: same-origin requests can receive the full URL, while cross-origin
HTTPS requests receive only the origin.
Referrer-Policy: strict-origin-when-cross-origin
Permissions-Policy: camera=(), microphone=(), geolocation=() Permissions Policy should reflect real product requirements. Disable unused features, and explicitly allow only the origins that need a capability when a first-party or embedded workflow depends on it.
5. Treat cross-origin isolation as an advanced control
Headers such as Cross-Origin-Opener-Policy, Cross-Origin-Resource-Policy, and Cross-Origin-Embedder-Policy can isolate browsing contexts and resources. They can also break OAuth
popups, third-party assets, embeds, and documents intended for cross-site use. Deploy them only after mapping
those flows and testing supported browsers.
Server configuration examples
These examples show syntax, not a universal production policy. Adapt and test the values for your site.
Nginx
add_header Strict-Transport-Security "max-age=31536000" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always; Apache
Header always set Strict-Transport-Security "max-age=31536000"
Header always set X-Content-Type-Options "nosniff"
Header always set Referrer-Policy "strict-origin-when-cross-origin" Application frameworks, CDNs, edge workers, and hosting platforms can also set headers. Prefer one documented source of truth so multiple layers do not emit conflicting values.
Validation checklist
- Test the final public HTTPS URL, including redirects and representative page types.
- Confirm the headers appear on HTML and relevant error responses, not only the homepage.
- Check the browser console for blocked resources, CSP violations, and broken workflows.
- Exercise sign-in, checkout, embeds, downloads, third-party widgets, and cross-origin API calls.
- Use a report-only CSP before enforcement when the application has multiple integrations.
- Document the owner, rationale, and rollback path for strict policies.
- Rescan after deployment and after major infrastructure or frontend changes.
What a security header scan cannot prove
A scan can observe whether selected controls are present and assess recognizable configuration patterns. It cannot prove that an application is free from injection, authorization, authentication, dependency, business logic, cloud, or infrastructure vulnerabilities. A strong header score is useful evidence of browser hardening, not a security certification.