# Enforce SRI across every script with Integrity-Policy (/en/blog/integrity-policy-explained)





Subresource Integrity (SRI) protects one element at a time. You hash a file, paste the digest into that tag's `integrity` attribute, and the browser checks it. The next script someone adds without a hash is unprotected, and nothing tells you. The `Integrity-Policy` response header fixes the scope problem: it requires SRI on every script with one header, and reports the ones that are missing it.

The short version: send `Integrity-Policy: blocked-destinations=(script)` and the browser blocks any script that loads without valid integrity metadata. Add an `endpoints=()` directive plus a `Reporting-Endpoints` header and it reports each blocked script as an [`integrity-violation`](/en/docs/web-security/reporting-api/reports/integrity-violation) report. A report-only variant lets you measure the gap before you enforce. This post covers the syntax, the reporting wiring, and how it turns SRI from a per-tag opt-in into a site-wide rule.

<Callout type="warn" title="Recent availability">
  Integrity-Policy enforcement for the `script` destination recently became available across current Chrome, Firefox, and Safari, and Firefox has gained endpoint delivery. It is still recent and not yet Baseline, so confirm coverage for the browsers you care about and treat it as an enforcement layer plus a reporting signal.
</Callout>

## What Integrity-Policy does [#what-integrity-policy-does]

[SRI](/en/docs/web-security/other/subresource-integrity) is opt-in per element. Nothing stops a developer from adding a new `<script src>` without an `integrity` attribute, and that one unhashed tag is the gap an attacker needs. Integrity-Policy closes it by stating the requirement once, at the response-header level, instead of on every tag.

You name the resource destinations that must be integrity-protected, and the browser then requires a valid `integrity` value on every load of that type. A script without one is blocked (or, in report-only mode, reported). The full reference is the [Integrity-Policy policy page](/en/docs/web-security/policies/integrity-policy).

## How to configure it [#how-to-configure-it]

The minimal header names the destination to protect:

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

`blocked-destinations` is the required directive. Today the practical value is `script`; the `style` destination has narrower support. With that header alone, any script that loads without a correct `integrity` attribute is blocked, with no report.

To get reports, add an `endpoints=()` directive and declare that endpoint name in a [`Reporting-Endpoints`](/en/docs/web-security/reporting-api/headers/reporting-endpoints) header. The two headers go in separate blocks:

```http
Reporting-Endpoints: integrity-endpoint="https://<Endpoint-ID>.report.centralcsp.com"
```

```http
Integrity-Policy: blocked-destinations=(script), endpoints=(integrity-endpoint)
```

One wiring detail trips people up: Integrity-Policy selects its reporting endpoint with the `endpoints=()` directive, not the `report-to=` parameter that COOP, COEP, and Permissions-Policy use. The name inside `endpoints=()` has to match a name declared in `Reporting-Endpoints`.

## Start in report-only mode [#start-in-report-only-mode]

Turning on blocking before you know which scripts carry SRI will break the page: every legitimate but un-hashed script gets blocked along with the bad ones. Run the report-only variant first. It reports each script that lacks valid integrity without blocking anything, so you see the full list before you enforce.

```http
Integrity-Policy-Report-Only: blocked-destinations=(script), endpoints=(integrity-endpoint)
```

Leave that running until the reports stop surfacing scripts you have not yet hashed. Then add the `integrity` attribute (or drop the dependency) for everything on the list, and switch the header to `Integrity-Policy` to enforce.

## What a violation report looks like [#what-a-violation-report-looks-like]

When a script loads without valid integrity, the browser emits an [`integrity-violation`](/en/docs/web-security/reporting-api/reports/integrity-violation) report to your endpoint. It names the page, the blocked script, and whether the policy was enforcing or only reporting.

```json
{
  "type": "integrity-violation",
  "age": 5,
  "url": "https://example.com/",
  "user_agent": "Mozilla/5.0 ...",
  "body": {
    "documentURL": "https://example.com/",
    "blockedURL": "https://example.com/example-framework.js",
    "destination": "script",
    "reportOnly": false
  }
}
```

The `reportOnly` field tells you which mode produced the report: `true` for the report-only header, `false` once you enforce. The `blockedURL` is the script that was missing valid SRI, which is the line you act on.

## The supply-chain case [#the-supply-chain-case]

This is where the header earns its place. Say you load an analytics script from a CDN with a correct `integrity` hash, and the CDN account is compromised so the file is swapped for a tampered version. SRI catches that one because the bytes no longer match the hash, and the script is blocked.

Now say a teammate adds a new third-party tag and forgets the `integrity` attribute. Per-element SRI cannot help, there is no hash to check against. Integrity-Policy does: the unhashed script violates the policy, so it is blocked and reported as an `integrity-violation`. The same report fires when a resource is requested in `no-cors` mode, where the browser cannot read the bytes to verify them at all. Both are the supply-chain gaps you want to know about before they run.

Integrity-Policy is the enforcement half. Knowing what is actually running on your pages is the other half. CentralCSP builds a [script inventory](/platform/supply-chain) from CSP hash reports, so you can see every script (and which ones lack integrity) before you flip the header to enforce. [Start free](/register) to map your client-side scripts and collect integrity-violation reports in one place.

<img alt="Scripts missing integrity, each CDN URL listed with the document origin that loaded it and its disposition" src="__img0" width="1359" height="388" />

## Sources [#sources]

* [MDN, Integrity-Policy](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Integrity-Policy)
* [W3C, Subresource Integrity, Integrity-Policy section](https://w3c.github.io/webappsec-subresource-integrity/#integrity-policy-section)

## Related [#related]

* [Integrity-Policy reference](/en/docs/web-security/policies/integrity-policy)
* [integrity-violation report](/en/docs/web-security/reporting-api/reports/integrity-violation)
* [Subresource Integrity (SRI) reference](/en/docs/web-security/other/subresource-integrity)
* [Subresource Integrity (SRI) explained](/en/blog/subresource-integrity-sri)
* [Reporting-Endpoints header](/en/docs/web-security/reporting-api/headers/reporting-endpoints)
