A versioned third-party script is the practical case: your page should use the reviewed file, and a different response should fail visibly. SRI checks the file against the digest you supplied. You still need to decide whether the reviewed code itself is appropriate.
Generate the digest from the file you reviewed
Save the exact reviewed script as widget.js. With Node.js installed, run this in the folder containing it:
node -e "const fs=require('node:fs'),c=require('node:crypto');console.log('sha384-'+c.createHash('sha384').update(fs.readFileSync('widget.js')).digest('base64'))"
The result begins with sha384-. Copy the complete output into the attribute below, replacing the bracketed placeholder:
<script
src="https://cdn.example.com/widget/1.2.3/widget.js"
integrity="[COMPLETE sha384- OUTPUT]"
crossorigin="anonymous"></script>
The address is an illustrative CDN URL, not a working library recommendation. Use the real pinned URL whose returned bytes you reviewed. The placeholder is deliberately not a valid integrity value; replace it before testing.
Hash the file bytes, including their line endings. Formatting or rebuilding the file can change its digest without changing its apparent behavior. A local prettified copy may therefore differ from the CDN response. MDN SRI reference
Make a match and mismatch visible locally
For a controlled rehearsal, create this exact widget.js through Node so its newline is explicit:
node -e "require('node:fs').writeFileSync('widget.js','globalThis.widgetReady = true;\n')"
Compute its digest with the earlier command. On an HTTP development server, use a page containing:
<!doctype html>
<html lang="en">
<meta charset="utf-8">
<title>SRI rehearsal</title>
<p id="status">Waiting for script</p>
<script src="./widget.js"
integrity="[COMPLETE sha384- OUTPUT]"></script>
<script>
document.querySelector('#status').textContent =
globalThis.widgetReady === true ? 'Reviewed script ran' : 'Script did not run';
</script>
</html>
With the matching digest, the expected line is Reviewed script ran. Next append a comment to widget.js while keeping the old digest in HTML. On a fresh reload, the expected line is Script did not run, and the console should identify an integrity mismatch. This same-origin rehearsal isolates the digest check; it does not test CDN CORS settings.
Restore the reviewed file before continuing. If you intentionally approve a changed file, review it and regenerate the digest as part of that update. Replacing the digest merely to silence a surprise mismatch defeats the review boundary.
Diagnose the failed check before removing it
For a cross-origin script, inspect the actual response and its CORS headers. crossorigin="anonymous" does not make the CDN grant access; its server must approve the request. Also check for redirects, an HTML error page, a changed version, or transformed bytes.
Keep the failure visible. A fallback that inserts the same URL without integrity would run the unverified response. Plan a useful unavailable state for the page instead, and inspect the reason in DevTools.
If the script is missing because of a path or response-type problem, the JavaScript loading checklist covers those earlier checks. For a module-based page, HTML module scripts explains the entry file and dependencies; do not assume one classic script's digest verifies every file an application later requests.
Keep the pinned URL, reviewed file, digest, and match/mismatch result together. That gives the next maintainer a concrete basis for approving the next version.