Security headers that earn their place.

A practical way to improve response policies while preserving login, checkout and the integrations your site actually needs.

Begin with the behaviour you want to constrain

A security header is a browser instruction, not a decoration for a report. Before adding one, identify the behaviour it should change. Do you want to require future HTTPS connections, restrict scripts, stop unwanted embedding or reduce referrer disclosure? The answer determines which policy is relevant and what needs testing.

A missing policy can be worth fixing without being proof of a currently exploitable flaw. An image CDN and a banking dashboard have different requirements. Applying one copied configuration to every response can create compatibility problems while leaving application-specific risks untouched.

Use the HTTP header inspector to establish what the current public response contains. Record the path and final status. A login page, an error page and a static resource can travel through different middleware and receive different headers.

Treat HSTS as a deployment commitment

Strict-Transport-Security tells supporting browsers to use HTTPS for the host during the declared lifetime after a valid secure response. A positive max-age is meaningful; a header with no effective lifetime is not the same policy. Ordinary insecure HTTP responses cannot reliably establish HSTS.

Adding includeSubDomains extends the commitment. Check older services, delegated subdomains and third-party-hosted applications before applying it. A subdomain you forgot about can become unavailable to affected browsers if it does not support HTTPS properly. Preload enrolment is a separate decision with potentially slow reversal, so it should be planned rather than copied from a checklist.

Give CSP an inventory and a rollout

Content Security Policy is often the most application-sensitive part of a header review. Start by identifying legitimate script, image, style, connection and framing requirements. Remove accidental dependencies when possible instead of granting a wildcard because the first test breaks.

On a complex site, report-only deployment can reveal violations before enforcement. That mode observes; it does not block. Reports also need a configured collector and careful handling because URLs and contextual data may be sensitive. Test actual flows rather than assuming a quiet homepage proves checkout works.

The CSP auditor helps identify duplicate directives, permissive script sources and missing controls that do not inherit default-src. Its findings are a review aid. They do not replace runtime tests for nonce handling, dynamically inserted content or the trustworthiness of allowed hosts.

Keep related controls distinct

Framing restrictions can use CSP frame-ancestors, with X-Frame-Options relevant to some compatibility requirements. X-Content-Type-Options normally uses nosniff. Referrer-Policy controls information sent in the Referer header. Cookie Secure, HttpOnly and SameSite attributes protect different aspects of session handling and belong in the same deployment conversation, even though they are not interchangeable with CSP.

ControlTest before rollout
HSTS includeSubDomainsHTTPS support across affected subdomains
CSP script restrictionsLogin, checkout, widgets and dynamic content
Frame restrictionsIntentional embedding and partner integrations
SameSite changesCross-site sign-in and payment return flows

Verify the delivered response and the user workflow

Configuration can pass through an application, reverse proxy, cache and content-delivery network before reaching a browser. Inspect the final response after deployment. A correct setting in a source file is not proof that every edge delivers it, and cached responses can briefly preserve earlier policy.

Then exercise the site. Check successful and failed login, password reset, payment return, form submission, downloads and important embedded content. If a policy causes a failure, investigate the exact blocked behaviour before weakening the entire policy. Narrow fixes preserve the reason the control was added.

Save the result and the tested application version. That record makes a later regression easier to locate. The goal is a maintained policy that constrains unnecessary behaviour, not a one-time report with the highest possible collection of present headers.

The OWASP header guidance and MDN CSP documentation are useful references when deciding which browser behaviour a configuration actually changes.

Build a response matrix with application owners

Choose representative paths before editing middleware: homepage, authenticated dashboard, failed login, password reset, API error, static asset and intentional redirect. Include a partner-embedded page if one exists. For each, write the status, content type, cache layer and browser behaviour you want to constrain.

Compare headers at the public edge with the origin when you are authorised to inspect both. A CDN may inject a policy, remove a header or serve an older cached response. Document which layer owns each policy so future changes do not create duplicates or contradictory assumptions.

Keep authentication state in the matrix. A public scanner cannot automatically see the same response as a signed-in browser. Use a test account and browser evidence for private flows, with credentials kept out of exported reports. The server-side checker is one perspective in the review.

Make one policy change traceable

Suppose the goal is to prevent unapproved framing of a dashboard. Identify legitimate embedding partners, choose the relevant frame-ancestor policy and test the dashboard in both an approved and an unapproved controlled parent. The expected difference is whether framing succeeds, not whether a generic score increased.

Keep script execution and outbound API connections separate from that framing change. If checkout breaks at the same time, inspect the actual response diff and browser error. Several unrelated header edits in one release can make it difficult to determine which change caused the regression.

For a CSP rollout, save the enforced policy and any report-only candidate as separate values. A report-only violation is evidence about the candidate, not proof of blocking. Verify an actual rejected resource in a controlled environment before describing the enforced protection.

Include cache and error handling in acceptance

An application can set headers only in its successful route handler while errors come from a proxy or framework default. Trigger a harmless known error and inspect the final response. The policy should be intentional for that content and context, rather than absent because the normal handler was bypassed.

Test cached and uncached responses where the deployment uses both. If a policy varies by origin or user context, review the cache key and Vary behaviour. A shared cache serving a response prepared for another context can create failures that do not appear in local development.

Keep rollback tied to a known configuration and understand stored browser state. Removing HSTS from a server response does not instantly remove a learned requirement from every client. A rollback plan should distinguish response-only controls from controls with a retained lifetime.

Maintain the policies alongside dependencies

Require a policy review when adding a third-party script, changing authentication providers or moving a service to a new subdomain. The dependency change may introduce a new frame, connection or cookie requirement. Review the smallest necessary allowance rather than adding broad wildcards by habit.

Keep a short record of each allowance's purpose and owner. When a service is removed, review whether its allowed origin can be removed too. A policy that only grows over time can retain trust in infrastructure the application no longer needs.

Use the response matrix as a release check after hosting changes. The application code may be identical while a new proxy changes headers, redirects or caching. Testing the delivered behaviour catches that infrastructure boundary.

Frequently asked questions

Does every missing header indicate an exploitable vulnerability?

No. The significance depends on the response type, application and threat being addressed. A missing control can still be a useful improvement, but the finding should explain the behaviour it leaves unconstrained. Avoid presenting header presence as a complete assessment of application security.

Can I copy one policy across every site?

Shared defaults can help, but application-sensitive directives need review. Scripts, frames, authentication and subdomain ownership differ. Start from a justified baseline, then test the real flows and keep exceptions explicit rather than assuming one copied string fits every product.

Why does the browser show two CSP headers?

Different layers may each emit a policy. Enforced policies apply together according to CSP rules, so a resource allowed by one can still be blocked by another. Inspect the complete public response and assign configuration ownership before changing only the application-level value.

Should I remove a policy when one widget breaks?

Identify the blocked feature and intended dependency first. A narrowly justified change can restore the widget while preserving the control's purpose. Removing the entire policy can hide the integration problem and discard unrelated protections without explaining the cause.

How should reports be handled?

Browser policy reports can contain URLs and contextual information. Validate them as untrusted input, restrict access and keep retention appropriate to the debugging purpose. Reproduce important findings before expanding allowlists based on reports that may originate from extensions or unusual clients.

Does a successful homepage test cover login?

No. Authentication can load different scripts, redirects, frames and cookies. Test successful and failed login, session expiry and recovery with a controlled account. These paths often use middleware and third-party services absent from the public homepage.

What should a deployment handoff include?

Keep the final headers, response matrix, tested application version, responsible configuration layer and rollback procedure. State any untested private or partner flow. This gives the next maintainer evidence of intended behaviour instead of a screenshot of a score.

How often should the configuration be reviewed?

Review it when dependencies, hosting, authentication or domain scope change, and at a cadence suited to the service. The important trigger is a change in the assumptions behind an allowance or restriction. A policy can become stale even when its syntax remains valid.

Sources and further reading

50 useful tools · ↑ ↓ to navigate · Enter to open · Esc to close