Skip to content

Instantly share code, notes, and snippets.

@evilpie
Last active September 23, 2025 16:51
Show Gist options
  • Select an option

  • Save evilpie/ad8426ccc93fe63fbbf304c9bfa2fd3d to your computer and use it in GitHub Desktop.

Select an option

Save evilpie/ad8426ccc93fe63fbbf304c9bfa2fd3d to your computer and use it in GitHub Desktop.
Support for (script) integrity on the web
Description Example Can have integrity metadata 1 Content-Security-Policy support for hashes Integrity-Policy support 2
External script <script src=http://> Yes (integrity attribute) Yes Yes
Inline script <script>alert("hello world");</script> No 3 Yes No
Event handlers onclick=alert(1) No Yes (with 'unsafe-hashes') No
javascript: protocol javascript:alert(2) No Yes (with 'unsafe-hashes') No
Static import import foo from "/bar.js" Yes ("importmap") Yes Yes
Dynamic import import("/script.js") Yes ("importmap") Yes Yes
Eval eval("alert('boo');")
new Function() ...
No No 4 No
WebAssembly No No No
Worker new Worker("/worker.js") No No No
Worker scripts importScripts("/foo.js") No No No
Worklet audioWorklet.addModule() No No No
Service Worker navigator.serviceWorker.register() No No No

Footnotes

  1. https://w3c.github.io/webappsec-subresource-integrity/#integrity-metadata-description

  2. Everything that is not supported by the Integrity-Policy is allowed to execute by default.

  3. The Inline Integrity proposal currently only adds support for signatures.

  4. Hashes for eval() scripts are part of the script-src-v2 proposal.

@dveditz
Copy link

dveditz commented Aug 29, 2025

is it assumed Worker includes SharedWorker and ServiceWorker or should you call it out? If this is just tracking combinations for yourself it's fine as-is. If you think it might get shared around or re-used later you might want to spell that out. On the other hand, "Eval" covers more than just the literal eval() in your example so maybe people will get it.

Worker constructors (or the .register() method for ServiceWorkers) accept an options parameter. It would be easy to add an integrityproperty that works the way it does for fetch() if we wanted to enable integrity and CSP support. Your matrix is not wrong, but this seems easily fixable.

That approach won't work for importScripts() because there are already a variable number of arguments, all of them interpreted as paths. If we didn't have to worry about backwards compatibility we could change it so each argument could be a string OR an object, but that support would not be detectable so that a newer script can avoid passing objects to unsupporting browsers. Another approach would be to invent a new method importScript() (singular) that takes (path, options) like the Worker constructors, but only one script at a time (or a different variation could support multiple scripts, of course). Your matrix is not wrong, but this could be fixed once we get past a lot of bikeshedding.

CSP can block worker scripts and importScripts(), just not currently with hashes or nonces.

Workers are different from other scripts, and from CSP's POV they're a bit more like an iframe document than content "in" the current page. ServiceWorkers especially, which might already be running and able to communicate with a page and affect its resource loads without the page doing anything that could trigger a CSP or Integrity check. I guess that's OK if your page is just passively affected by a ServiceWorker registered by another page. But if your page does call .register() with a future integrity attribute, or even a CSP path mismatch, what do we do? If we load it we can enforce those things, but then that new serviceworker won't affect the current page until it is reloaded at the earliest, and even later if there are other open tabs keeping the old SW alive. On the other hand there's no way for a page to enforce integrity on a different document it's talking to with window.PostMessage() or BroadcastChannel. ServiceWorkers are kind of like that.

Workers support having their own CSP header; we could make them support the Integrity-policy header, too, if it was useful. They can also inherit CSP from the document that loaded them (I don't think that's true of SW). We could make Integrity-policy do the same

Integrity-policy doesn't cover inline script integrity as a separate item because that is part of the document, which could also have its integrity checked. Maybe not with Integrity-policy as it is right now, but in the manifest-based version that will be part of WAICT.

CSP treats WebAssembly as a kind of eval(). If script-src-v2 is adding hashes for regular eval it should be expanded to cover wasm-eval also.

@dveditz
Copy link

dveditz commented Aug 29, 2025

Worklets? The Worker stuff probably applies directly, except they use addModule() for additional scripts instead of importScripts()

@rich-hansen
Copy link

CSP treats WebAssembly as a kind of eval(). If script-src-v2 is adding hashes for regular eval it should be expanded to cover wasm-eval also.

I'd argue it's better to keep them separate given CSP treats them separately. "unsafe-eval" vs "wasm-unsafe-eval" directives as the example.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment