HTTP security headers are a practical control layer between a website and the browser. This checklist explains which headers to use, how to inspect them, how to roll out Content Security Policy safely, and how to monitor changes without unexpectedly breaking scripts, embeds, forms, or navigation.
Overview
Security headers are response headers that tell a browser how to handle resources and browser capabilities. They do not replace secure application code, access control, dependency review, or server hardening. They do, however, reduce the consequences of common mistakes and make browser behavior more explicit.
The right configuration depends on the site. A static documentation site, a single-page application, an authenticated dashboard, and a site containing advertising or third-party embeds will not share exactly the same policy. Treat the examples below as a starting point to test, not as a drop-in configuration for every deployment.
A useful workflow has five stages:
- Inspect the headers currently returned by every important entry point.
- Record the assets, APIs, frames, forms, and external services the site actually needs.
- Deploy restrictive policies in a reporting or non-enforcing mode where supported.
- Test browser behavior, authenticated flows, and non-HTML responses.
- Monitor the configuration after each release, dependency change, and infrastructure migration.
Use browser developer tools for runtime evidence, command-line requests for repeatable checks, and a security-header scanner as a supplementary review. A scanner can identify omissions and suspicious settings, but it cannot know whether a blocked payment frame or analytics endpoint is intentional for your application.
What to track
Core HTTP security headers
| Header | Purpose | Practical starting point |
|---|---|---|
| Content-Security-Policy | Restricts where scripts, styles, images, frames, connections, and other resources may load from. | Begin with a policy based on observed dependencies; test with report-only before enforcement. |
| Strict-Transport-Security | Instructs a browser to use HTTPS for future requests to the host. | Enable only after HTTPS works consistently, including required subdomains if using the subdomain option. |
| Permissions-Policy | Controls access to selected browser features such as camera, microphone, and geolocation. | Disable features the site does not need and explicitly limit features used by embeds. |
| Referrer-Policy | Controls how much referrer information is sent with outgoing requests. | Choose a setting that avoids unnecessary URL disclosure while preserving required analytics or navigation behavior. |
| X-Content-Type-Options | Prevents browsers from treating a response as a different content type when MIME sniffing might otherwise occur. | Set to nosniff and serve correct Content-Type values. |
| Frame-ancestors | Within CSP, controls which sites may embed the page in a frame. | Use 'none' when framing is not required, or specify the small set of trusted origins. |
Build a dependency inventory before writing CSP
Content Security Policy is often the header that causes deployment friction because it describes the site’s actual dependency graph. Inventory the following for each major page type:
- JavaScript files, inline scripts, modules, workers, and dynamically created scripts.
- Stylesheets, inline styles, fonts, images, video, and data URLs.
- API and WebSocket destinations used by
fetch, XHR, or client libraries. - Payment, video, support, authentication, analytics, or consent-management frames.
- Form submission destinations and navigation targets.
- Object, plugin, and worker usage, even if those features are expected to be absent.
Prefer precise origins over broad wildcards. Avoid adding a third-party origin merely because a browser report mentions it; first identify which page, feature, and request generated the report. A policy that allows every HTTPS origin may appear convenient while providing little meaningful restriction.
A CSP rollout template
The following is an intentionally conservative example for a site that serves its own scripts and styles, loads images and fonts from approved locations, and calls an API on a separate origin. Replace every placeholder after testing:
Content-Security-Policy-Report-Only: default-src 'self'; script-src 'self'; style-src 'self'; img-src 'self' https://images.example; font-src 'self'; connect-src 'self' https://api.example; object-src 'none'; base-uri 'self'; frame-ancestors 'none'; form-action 'self'; report-to csp-endpoint
Do not copy this policy unchanged. If the application needs inline code, third-party frames, workers, or a content delivery network, those requirements must be handled deliberately. For inline scripts, nonces or hashes are generally more controlled than broadly allowing inline execution. A nonce must be unpredictable, generated for the response, and applied consistently to the intended script elements. Keep CSP changes in version control and review them alongside application changes.
Inspect the response, not only the source code
Headers can be added or replaced by a reverse proxy, CDN, application server, framework middleware, or hosting platform. Check the final network response:
curl -I https://www.example.test/
curl -sS -D - -o /dev/null https://www.example.test/login
Repeat the check for redirects, authenticated pages, static assets, API responses, error pages, and alternate hostnames. A header on the homepage does not prove that the login flow or an API response has the intended configuration. Also check whether a proxy has accidentally emitted duplicate CSP or HSTS headers; conflicting policies can produce behavior that is difficult to diagnose.
Cadence and checkpoints
Make security-header review part of the development workflow rather than a one-time launch task. A practical cadence is monthly or quarterly for stable sites, with an additional review whenever infrastructure, browser-facing features, or third-party dependencies change.
At each scheduled review
- Request representative URLs with a command-line tool and save the relevant response headers.
- Open the site in a supported browser and inspect Console and Network warnings.
- Test anonymous and authenticated journeys, including login, logout, forms, uploads, payments, embeds, and downloads where applicable.
- Review CSP violation reports and group them by blocked URL, directive, page, and release.
- Run a header scanner, then manually verify each finding against the application’s requirements.
- Compare the result with the previous review so additions, removals, and policy relaxations are visible.
Use change-based checkpoints
Run the same checks after moving from one CDN or hosting provider to another, changing TLS termination, introducing a new frontend framework, adding a tag manager, changing authentication, or embedding a new external service. Dependency updates can also introduce a new asset host or connection endpoint. Record the reason for every policy change so a future maintainer can distinguish an intentional allowance from an unexplained exception.
Keep a small header test in continuous integration where possible. It can assert that required headers exist, that HSTS is not emitted on an unintended hostname, that CSP has not silently changed from enforcement to report-only, and that critical directives such as object-src or base-uri have not disappeared. Use end-to-end tests for behavior that a static header assertion cannot verify.
How to interpret changes
A new scanner warning is not automatically a vulnerability, and a clean scanner result is not proof that the application is safe. Interpret each result in context.
CSP violations
First identify whether the blocked request is required. A blocked obsolete script, unexpected frame, or unfamiliar connection may indicate unwanted injection or a stale dependency. A blocked legitimate request usually means the policy inventory is incomplete. Avoid solving every report by adding a wildcard. Narrow the source, remove the dependency, or redesign the integration when appropriate.
Watch for recurring reports caused by browser extensions, local development tools, or malformed pages. Group reports by your own host, page path, directive, and release before acting. Reports that appear only in development should not automatically weaken a production policy.
HSTS issues
HSTS can make an HTTP mistake harder to recover from for users whose browsers have stored the directive. Confirm that HTTPS is valid and that every required subdomain is prepared before increasing the scope of the policy. Treat any option that extends the policy to subdomains as an architectural decision, not a routine checkbox. Do not use HSTS to hide mixed-content or certificate problems; fix the underlying references and deployment configuration.
Permissions Policy and framing
If an embedded service stops working, check whether the top-level page or an iframe policy has restricted the required feature. Grant only the feature and origins needed for that integration. Similarly, distinguish a page that must be framed by a trusted partner from one that should never be framed. Test both directions: your pages embedding external content and external sites attempting to embed your pages.
Referrer and MIME behavior
Unexpected referrer changes can affect analytics, attribution, or application flows, but sending full paths and query strings may expose sensitive information. Review URLs for tokens, identifiers, and personal data before selecting a permissive policy. For nosniff failures, correct the response MIME type and asset handling rather than removing the header.
When to revisit
Revisit this checklist at least on a monthly or quarterly schedule, depending on how frequently the site changes and how sensitive its data is. Return immediately after a security incident, a major browser behavior change, a hosting or CDN migration, a new third-party script, a framework migration, or a change to authentication, payments, uploads, or embedded media.
Keep the article’s working checklist with the project and record the date, tested URLs, browser coverage, scanner output, policy version, and unresolved exceptions. Standards and browser implementations evolve, and scanner rules can change; validate any recommendation against current browser documentation and your own test results before applying it broadly.
Practical next step: choose one production URL, capture its current headers, list every external dependency visible in the Network panel, and create a report-only CSP from that inventory. Test the most important user journeys, fix or explain each report, then promote the policy only after a documented review. Repeat the same process after the next meaningful release instead of assuming the header configuration will remain correct.
For adjacent workflow checks, pair this review with an ongoing web performance budget, a browser-based accessibility audit, and API contract validation. These checks cover different failure modes, but together they provide a more reliable release review than any single online developer tool or security scanner.