HTTP security headers: what HSTS, CSP, and X-Content-Type-Options reveal about a site's technical maturity

A guide to the HTTP response headers OWASP recommends as baseline protection, what each one actually prevents, and why their absence is a configuration gap, not proof of a breach.

Cover image for the article: HTTP security headers: what HSTS, CSP, and X-Content-Type-Options reveal about a site's technical maturity

Executive brief

Key takeaways

  • Strict-Transport-Security (HSTS) instructs the browser to never attempt HTTP again on that domain, even if a link or typed address points to the insecure version.
  • Content-Security-Policy (CSP) declares where the browser is allowed to load scripts, styles, and other resources, reducing the effect of a content injection even when one occurs.
  • OWASP recommends a core set of response headers as baseline protection, not as a complete application security certification.
  • A missing header is a publicly observable configuration gap; it does not equal a confirmed exploitable vulnerability, nor does it replace a penetration test.

A site can hold a valid HTTPS certificate, show a green padlock in the browser, and still respond without a single one of the security headers OWASP recommends as baseline protection. The padlock confirms the connection is encrypted. It doesn't confirm the browser was instructed to refuse a future insecure connection attempt, nor that there's a declared policy for where scripts are allowed to load from.

These HTTP response headers are server configuration, not application code. That makes them publicly verifiable without access to any account or the site's repository — and it's exactly why their absence is a common finding in an evidence-based audit.

What can be observed, and what it proves

The OWASP Secure Headers Project defines a core set of recommended response headers for any web application. Five of them are directly observable in the HTTP response of any public page:

HeaderWhat it declaresWhat it reduces
Strict-Transport-Security (HSTS)How long the browser must require HTTPS on this domainProtocol downgrade attacks and cookie hijacking on an initial HTTP attempt
Content-Security-Policy (CSP)Where scripts, styles, and other resources are allowed to load fromThe effect of a content injection, even when one occurs
X-Content-Type-OptionsThat the browser must not guess (sniff) a response's content typeExecuting a file as a different type than declared
Referrer-PolicyHow much origin-URL information is sent to the next siteLeakage of sensitive URL parameters to third parties
Permissions-PolicyWhich browser APIs (camera, microphone, geolocation) the page can useUnintended use of sensitive APIs by third-party scripts

OWASP recommends configuring HSTS with a max-age of two years (63072000 seconds), the includeSubDomains directive, and preload where applicable — a window long enough that the browser never "forgets" the HTTPS requirement between visits.

None of these headers alone proves an application is free of vulnerabilities. Each reduces a specific class of risk at the transport and content-loading layer; none audits business logic, access control, or application dependencies.

Method: from HTTP response to prioritization

1. Capture the HTTP response from the real page, not a cached version

The browser's Network inspector, or a direct request, shows headers exactly as the server sent them. CDNs and proxies sometimes strip or override headers configured at the origin — which is why verification should target the final public URL, not a development environment.

2. Check presence, not just the header name

A header present with a weak directive (for example, a CSP that broadly allows unsafe-inline) reduces the protection the header is meant to provide. Checking presence is the first filter; reading the directive is the next step, usually done by engineering during a dedicated review.

3. Cross-check against the HTML document's foundation

A declared doctype, a charset set early in <head>, and a viewport tag are prerequisites for predictable rendering — they aren't security headers, but they tend to be missing in the same projects that also skip response headers, because both are low-level configuration decisions left behind during rushed migrations.

4. Don't confuse a missing header with a confirmed vulnerability

The gap between "the header wasn't found" and "the site was breached" is the gap between a public configuration audit and a penetration test. Treat the absence as a point worth engineering's investigation, not as a confirmed security incident.

False positives and limitations

  • CDNs and reverse proxies can add or strip headers between the origin and the browser. Confirm the configuration both at the origin and at the final delivery point.
  • A present header can still be misconfigured. Presence doesn't equal a correct directive; an empty or overly permissive CSP still counts as "present" in a simple existence check.
  • None of these five headers cover authentication, access control, or outdated dependencies. They're a publicly observable slice of security posture, not a complete audit.

Action plan

  1. Verify the HTTP response of the main public page and confirm which of the five core headers are present. Suggested owner: Engineering.
  2. Prioritize HSTS and CSP first — the two with the largest reduction in protocol-downgrade and content-injection risk, respectively.
  3. Review the directives, not just presence, in a dedicated engineering session — especially CSP, whose wrong policy can be either too permissive or break legitimate functionality.
  4. Re-verify after any CDN, reverse proxy, or hosting provider change, since those components can silently override origin-configured headers.

Remountly checks the presence of these five headers in a page's public HTTP response as part of the Best Practices category, alongside HTTPS, mixed content, and deprecated API patterns like document.write. That check is observable configuration evidence — the same principle behind turning technical problems into financial impact: start from what can be observed publicly before assuming the cause.

Direct answers

Frequently asked questions

Does Remountly test whether a site can be hacked?

No. Remountly checks the public HTTP response for whether five OWASP-recommended security headers are present: Strict-Transport-Security, Content-Security-Policy, X-Content-Type-Options, Referrer-Policy, and Permissions-Policy. That's an observable configuration check, not a penetration test or an application vulnerability audit.

Why isn't HTTPS alone enough?

HTTPS protects data in transit between the browser and the server, but it doesn't stop a user from typing or clicking a link to the http:// version of the same domain before a redirect happens. HSTS closes that window by instructing the browser to never attempt the insecure version again, even on the first try, once it has seen the header within the max-age window.

Can a site have every recommended header and still be vulnerable?

Yes. These headers reduce specific classes of risk, but they don't cover business-logic flaws, broken access control, outdated dependencies, or authentication errors. They're a publicly observable layer of defense, not a complete application security audit.