# How to improve your security headers grade (/en/blog/improve-security-headers-grade)



A scanner gave you a low security headers grade, and now you need to know which headers to set and how. The grade is a checklist score: a tool reads your response headers and marks each recommended one present or missing, then weighs how well the ones present are configured. To raise the grade you send the right set of headers with the right values. This is that set, what each header does, and the value to ship, with the deeper fixes linked from each step.

Different scanners weight things differently. [securityheaders.com](https://securityheaders.com/) checks for a fixed list of headers and downgrades you for missing ones. [Mozilla Observatory](https://developer.mozilla.org/en-US/observatory) (the MDN Observatory) scores the CSP more strictly and rewards a policy without `'unsafe-inline'`. Rating agencies layer their own naming on the same checks. The headers below cover all of them.

## The headers a scanner grades [#the-headers-a-scanner-grades]

Six headers carry almost all of the grade. Set these and configure them well, and an A is reachable.

### Content Security Policy, the heaviest single factor [#content-security-policy-the-heaviest-single-factor]

A Content Security Policy (CSP) tells the browser which scripts, styles, and other resources a page may load. It is the one header most scanners weight highest, and a strict CSP with no `'unsafe-inline'` is what earns the top marks on a CSP-aware scanner like Mozilla Observatory.

```http
Content-Security-Policy:
    default-src 'self';
    script-src 'nonce-{RANDOM}' 'strict-dynamic';
    object-src 'none';
    base-uri 'none';
    frame-ancestors 'none'
```

A CSP is also the header most likely to break the page if you guess at it, so deploy it in report-only first, collect what real traffic blocks, then enforce. The full method is in [how to build a strong CSP, step by step](/en/blog/how-to-build-a-strong-csp), and the keyword to remove first is covered in [why you should never use unsafe-inline in CSP](/en/blog/unsafe-inline-csp).

### Strict-Transport-Security (HSTS), enforce HTTPS [#strict-transport-security-hsts-enforce-https]

`Strict-Transport-Security` tells the browser to only ever reach your site over HTTPS, which closes the gap where a first request goes out in plaintext. Send a long `max-age` and include subdomains. Add `preload` only when you are ready to commit the domain to the browser preload list, since it is hard to undo.

```http
Strict-Transport-Security: max-age=63072000; includeSubDomains
```

### X-Content-Type-Options, stop MIME sniffing [#x-content-type-options-stop-mime-sniffing]

`X-Content-Type-Options: nosniff` stops the browser from second-guessing a response's declared content type, which is how some uploads turn into executable scripts. It has one value and no modern replacement, so set it everywhere.

```http
X-Content-Type-Options: nosniff
```

### Frame control, prefer frame-ancestors [#frame-control-prefer-frame-ancestors]

Clickjacking protection decides who may embed your page in a frame. The modern control is the CSP [`frame-ancestors`](/en/docs/web-security/policies/content-security-policy/directives/frame-ancestors) directive, which supports multiple origins and `'none'`. The old `X-Frame-Options` header still satisfies some scanner checks and works as a fallback for very old browsers, but `frame-ancestors` is the one doing the work today. Why the older header is on its way out is covered in [legacy security headers you can retire](/en/blog/legacy-security-headers-to-retire).

```http
Content-Security-Policy: frame-ancestors 'none'
```

### Referrer-Policy, limit what you leak [#referrer-policy-limit-what-you-leak]

`Referrer-Policy` controls how much of the current URL is sent in the `Referer` header when a user navigates away or a page loads a resource. A sensible default keeps the origin on cross-origin requests and the full path same-origin.

```http
Referrer-Policy: strict-origin-when-cross-origin
```

### Permissions-Policy, switch off features you do not use [#permissions-policy-switch-off-features-you-do-not-use]

`Permissions-Policy` controls access to browser features like the camera, microphone, and geolocation. Disabling the ones your site does not use shrinks what an injected script can reach. It is the standardized successor to the deprecated `Feature-Policy`, explained in [Permissions-Policy explained](/en/blog/permissions-policy-explained).

```http
Permissions-Policy: geolocation=(), camera=(), microphone=()
```

## The order to fix them in [#the-order-to-fix-them-in]

Set the low-risk headers first, because they cannot break the page: `X-Content-Type-Options`, `Referrer-Policy`, `Strict-Transport-Security`, and `Permissions-Policy` are single-line additions you can ship today. They will move the grade immediately.

Save the CSP for last, because it is the one that needs the report-only, collect, enforce cycle to avoid breaking real traffic. It is also the heaviest factor, so it is worth the extra care.

```mermaid
flowchart LR
  A["Quick wins<br/>nosniff, Referrer-Policy,<br/>HSTS, Permissions-Policy"] --> B["CSP via<br/>Report-Only"]
  B --> C["Collect"]
  C --> D["Enforce"]
```

## If your low grade comes from a rating agency [#if-your-low-grade-comes-from-a-rating-agency]

Security rating agencies grade the same headers but publish their own finding names, and the fix is the same set of headers configured well. If your finding came from one of them, the per-agency walkthroughs map each finding to a header change:

* [How to fix SecurityScorecard CSP findings](/en/blog/fix-securityscorecard-csp-findings)
* [How to fix BitSight Content Security Policy findings](/en/blog/fix-bitsight-csp-findings)

## Head-to-head comparisons [#head-to-head-comparisons]

Several of these headers have a close cousin they get confused with. When you are deciding between two, these break down the trade-off:

* [X-Frame-Options vs frame-ancestors](/en/blog/x-frame-options-vs-frame-ancestors) for framing control.
* [HSTS vs upgrade-insecure-requests](/en/blog/hsts-vs-upgrade-insecure-requests) for forcing HTTPS.
* [no-cache vs no-store](/en/blog/no-cache-vs-no-store) for keeping sensitive responses out of shared caches.
* [SameSite vs CSRF tokens](/en/blog/samesite-vs-csrf-tokens) for cross-site request defense.

For the full reference on each header, see the [security headers documentation](/en/docs/web-security/security-headers).

## See your current state first [#see-your-current-state-first]

Before you change anything, scan what the live site sends. A scan lists which headers are present, which are missing, and which carry weak values, so you fix in one informed pass instead of guessing. The [security headers scanner](/tools/security-headers) gives you that list, the [CSP scanner](/tools/csp-scanner) reports on the policy specifically, and the [CSP evaluator](/tools/csp-evaluator) grades a draft policy before you ship it. Once the headers are in place, the [CSP suite](/platform/csp-builder) collects the violation reports and tracks the policy over time so the grade does not quietly slip after the next deploy.

## Where this leaves you [#where-this-leaves-you]

A security headers grade is a checklist, so raising it is a checklist too: send `X-Content-Type-Options`, `Referrer-Policy`, `Strict-Transport-Security`, and `Permissions-Policy` now, then build and enforce a strict CSP with `frame-ancestors` for the heaviest part of the score. Scan first so you know your starting point, and keep scanning so a new third-party script does not undo the work.

To collect violation reports, track your policy over time, and watch the headers across your estate, [start free with CentralCSP](/register).

## Sources [#sources]

* [MDN, security headers and the Observatory](https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/CSP)
* [securityheaders.com](https://securityheaders.com/)

## Related [#related]

* [How to fix SecurityScorecard CSP findings](/en/blog/fix-securityscorecard-csp-findings)
* [How to fix BitSight Content Security Policy findings](/en/blog/fix-bitsight-csp-findings)
* [Legacy security headers you can retire](/en/blog/legacy-security-headers-to-retire)
* [Permissions-Policy explained](/en/blog/permissions-policy-explained)
