# SRI vs CSP hash, two hashes that do different jobs (/en/blog/sri-vs-csp-hash)



A Subresource Integrity (SRI) hash and a Content Security Policy (CSP) hash both start with `sha256-` or `sha384-`, so they read as the same thing. They are not. An SRI hash verifies the bytes of an external file you load by URL. A CSP hash allowlists the text of an inline script your page runs. Different inputs, different jobs, and you often use both on the same page.

The short version: if you wrote `integrity="sha384-..."` on a `<script src=...>` tag, that is SRI, and it checks that the file the server sent back matches your hash. If you wrote `'sha256-...'` inside `script-src`, that is a CSP hash source, and it checks that an inline `<script>` block's content matches your hash. One guards a file's contents, the other decides which inline code may run.

## The one-sentence difference [#the-one-sentence-difference]

SRI hashes a **response body**. A CSP hash hashes **inline source text**.

That is the whole distinction, and everything else follows from it. SRI asks "is this file the one I pinned?" before running an external resource. A CSP hash asks "is this inline block one I explicitly allowed?" before running inline code. Neither replaces the other, because they act at different points and on different inputs.

## SRI verifies an external file [#sri-verifies-an-external-file]

SRI is the [`integrity`](https://developer.mozilla.org/en-US/docs/Web/Security/Subresource_Integrity) attribute you put on a tag that loads code from another host. The browser fetches the file, hashes the bytes it received, and compares them to your value. A match runs the file. A mismatch is treated as a network error, so nothing runs.

```html
<script
  src="https://cdn.example.com/library.js"
  integrity="sha384-oqVuAfXRKap7fdgcCY5uykM6+R9GqQ8K/uxy9rx7HNQlGYl1kPzQho1wx4JwY8wC"
  crossorigin="anonymous"></script>
```

The hash covers the exact response body at that URL. If the CDN is compromised and serves altered code, the bytes no longer match the hash and the browser drops the file. The `crossorigin` attribute is mandatory for a cross-origin file, because the browser cannot read the bytes of an opaque response. [Subresource Integrity (SRI) explained](/en/blog/subresource-integrity-sri) covers that requirement in full.

## A CSP hash allowlists inline code [#a-csp-hash-allowlists-inline-code]

A CSP hash source is a digest you write into `script-src` (or `style-src`). A Content Security Policy blocks inline scripts by default. A hash source re-allows one specific inline block by its content, without re-enabling all inline script.

```http
Content-Security-Policy: script-src 'self' 'sha256-q1V8...='
```

When the browser meets an inline `<script>`, it hashes the text between the tags and checks it against the hashes in the directive. The hash is over the exact inline content, not a file, not the tag, not the attributes. [How to generate a CSP hash (sha256)](/en/blog/csp-hash-sha256) walks through computing one and the whitespace traps that break it, and the [CSP hashes and nonce](/en/docs/web-security/policies/content-security-policy/values/csp-hashes-nonce) reference documents the keyword.

## Side by side [#side-by-side]

The prefixes are identical, the inputs are not. Put the same string in the wrong place and it does nothing useful.

|                 | SRI hash                               | CSP hash source                          |
| --------------- | -------------------------------------- | ---------------------------------------- |
| Where it lives  | `integrity` attribute on a tag         | `script-src` / `style-src` in the policy |
| What it hashes  | The response bytes of an external file | The inline text of a `<script>` block    |
| What it answers | Is this fetched file untampered?       | May this inline block run?               |
| Prefix          | `sha256-` / `sha384-` / `sha512-`      | `sha256-` / `sha384-` / `sha512-`        |
| Updates when    | The external file changes              | The inline code changes                  |

A practical tell: a CSP hash sits between quotes inside a header, an SRI hash sits in an HTML attribute and carries no quotes around the algorithm prefix.

## They complement each other [#they-complement-each-other]

These are orthogonal controls, and a hardened page uses both. CSP decides which scripts may run at all, by origin, by nonce, or by hash. SRI then guarantees that an allowed external file has not been altered since you pinned it.

A script can pass CSP and still be tampered with. Say your policy allows `https://cdn.example.com` as a host source. CSP is satisfied the moment the script comes from that origin, it does not inspect the contents. If the CDN serves modified code, only SRI catches it, because only SRI hashes the response. Run them together: CSP for which code is allowed, SRI for whether the allowed file is intact. The [`script-src`](/en/docs/web-security/policies/content-security-policy/directives/script-src) directive is where you wire the CSP half.

## What about require-sri-for? [#what-about-require-sri-for]

There used to be a CSP directive meant to bridge the two: [`require-sri-for`](/en/docs/web-security/policies/content-security-policy/directives/require-sri-for), which would have forced an `integrity` attribute on every script or style. It is worth knowing about only so you do not reach for it.

`require-sri-for` was removed from the CSP specification. It never shipped to a stable browser, Chrome never implemented it, and Firefox removed its flagged implementation. It is not interoperable and you cannot rely on it today.

The modern way to require integrity site-wide is a separate header, [`Integrity-Policy`](/en/docs/web-security/policies/integrity-policy). Instead of a CSP directive, it tells the browser to block any in-scope subresource that loads without integrity metadata, and to report it as an [`integrity-violation`](/en/docs/web-security/reporting-api/reports/integrity-violation).

```http
Integrity-Policy: blocked-destinations=(script)
```

The `script` destination is now enforced across current Chrome, Firefox, and Safari. A report-only variant, `Integrity-Policy-Report-Only`, surfaces the gaps without blocking, so you can measure coverage before enforcing.

## Which one do I want? [#which-one-do-i-want]

* Loading a third-party file by URL and want to pin its contents? That is **SRI**, on the tag. Generate the value with the [SRI generator](/tools/sri-hash).
* Allowing one specific inline `<script>` block under a strict policy? That is a **CSP hash**, in `script-src`.
* Want to require integrity across the whole document? Use the `Integrity-Policy` header, not `require-sri-for`.

If you are auditing an existing policy and cannot tell which hashes are doing what, the [CSP evaluator](/tools/csp-evaluator) breaks a policy down directive by directive and flags the weak spots.

Knowing which scripts you load is the work that comes before either hash. CentralCSP builds a script inventory of every script running on your pages from CSP hash reports, so you can see new or changed third-party code before it turns into an incident. [Start free](/register) to map your client-side dependencies.

## Sources [#sources]

* [W3C, Subresource Integrity](https://www.w3.org/TR/SRI/)
* [W3C, Content Security Policy Level 3](https://www.w3.org/TR/CSP3/)
* [MDN, Subresource Integrity](https://developer.mozilla.org/en-US/docs/Web/Security/Subresource_Integrity)
* [MDN, script-src directive](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Content-Security-Policy/script-src)

## Related [#related]

* [Subresource Integrity (SRI) explained](/en/blog/subresource-integrity-sri)
* [How to generate a CSP hash (sha256)](/en/blog/csp-hash-sha256)
* [Subresource Integrity (SRI) reference](/en/docs/web-security/other/subresource-integrity)
