Custom Integrity Hashes
What are Custom Integrity Hashes?
CSP Integrity reports the SRI hash of every script the browser loaded. We match each hash against a global database of known files, so a well-known library shows up named and versioned rather than as an opaque string.
Your own first-party scripts are not in that database. Nobody else loads them, so nothing can identify them, and they arrive in your reports labelled unknown. On a site that bundles or fingerprints its own JavaScript, that can be most of what you see — which makes the genuinely unexpected script much harder to spot.
Custom Integrity Hashes fix that. You upload a list of hashes you already know about, each with a label of your choosing, and those hashes are labelled with your tag instead of "unknown" wherever they appear in your reports.
Custom Integrity Hashes are included with the Integrity Suite, so any plan with CSP Integrity has them. The feature is currently in open beta.
Account admins only
Uploading, replacing and deleting the hash list requires admin access on the account. Other members see the resulting tags in reports but cannot change the list.
Why bother?
The point is not decoration, it is signal. Once your own scripts are labelled, "unknown" goes back to meaning genuinely unrecognised — which is exactly the state worth investigating on a page handling payments or personal data.
It also gives you somewhere to record intent. A hash you tag as warning with an info note saying it is a deprecated bundle scheduled for removal is a message to whoever reads the report in three months, including you.
The file format
Upload a single JSON file. The structure is:
{
"defaultTag": "My Company",
"defaultStatus": "good",
"hashes": [
{"hash": "sha256-abc123..."},
{"hash": "sha256-xyz789...", "tag": "My Company (legacy)", "status": "warning", "info": "v1.4.2 — scheduled for removal"}
]
}
| Field | Required | Notes |
|---|---|---|
defaultTag |
Yes | Applied to any entry with no tag of its own. |
defaultStatus |
No | Applied to any entry with no status. Defaults to good. |
hashes |
Yes | The list of entries. |
hashes[].hash |
Yes | An SRI hash prefixed sha256-, sha384- or sha512-. |
hashes[].tag |
No | Overrides defaultTag for this entry. |
hashes[].status |
No | One of good, warning or error. |
hashes[].info |
No | Free text, shown as a tooltip in reports. |
Most people only need defaultTag and a list of hashes — the per-entry fields are there for when you want to single something out.
The file is limited to 500 KB.
Getting your hashes
The hashes are ordinary SRI hashes of the files as served, so anything that already produces SRI values will do. Two easy routes:
- From your build. Most bundlers can emit SRI hashes for their output, which is the most reliable source because it runs on exactly the files you deploy.
- From a file directly, on any machine with OpenSSL:
cat app.js | openssl dgst -sha384 -binary | openssl base64 -A
Prefix the result with the algorithm to get the value to put in the file, for example sha384-<output>.
You can also use our SRI Hash generator for a one-off.
Hash the bytes you actually serve
The hash covers the exact bytes the browser received. If a CDN minifies, recompresses or rewrites your file in transit, the hash the browser reports will not match the one you generated from your source file. When a hash you were sure about still shows as unknown, this is almost always why.
Uploading the list
Go to CSP Integrity → Custom Hashes in your account, choose your file, and upload.
Uploading replaces your entire existing list — it is not a merge. Keep the file in source control and re-upload the whole thing when it changes, so the list you can see is the list that is live.
After an upload you are told how many entries were accepted and how many were rejected. Entries are rejected individually for things like an unrecognised hash prefix or an invalid status, so a single bad line does not cost you the upload — but do read the count, because a large rejected number usually means a format mistake repeated throughout the file.
Downloading and deleting
Download returns the list currently stored, which is the quickest way to confirm what is actually live if you have lost track of which version you uploaded.
Delete removes the list permanently. Hashes that were previously tagged revert to showing as unknown in reports. Nothing else about CSP Integrity changes.
Keeping the list current
The hashes change every time the file changes, so a fingerprinted or frequently rebuilt bundle produces new hashes on every deploy. Two practical approaches:
- Regenerate and re-upload as part of your release process, so the list tracks what you actually ship.
- Tag by intent instead of by version. Rather than listing every build, list the hashes you expect to be in circulation — current release plus whatever is still cached at the edge — and let genuinely retired ones fall off.
A stale list is not harmful; its entries simply stop matching and those scripts show as unknown again. The failure mode is noise, not a broken policy.