TrustedTypes: Worker()/SharedWorker() constructors#42073
Conversation
|
Preview URLs Flaws (2)URL:
URL:
External URLs (3)URL:
(comment last updated: 2026-01-21 20:20:57) |
| - : Thrown if `url` cannot be parsed. | ||
| - `TypeError` | ||
| - : Thrown if the `url` parameter is set with a string when [Trusted Types](/en-US/docs/Web/API/Trusted_Types_API) are [enforced by a CSP](/en-US/docs/Web/API/Trusted_Types_API#using_a_csp_to_enforce_trusted_types) and no default policy is defined. | ||
| <!-- This is also thrown if the fetched URL cannot be successfully parsed as its indicated type. --> |
There was a problem hiding this comment.
This was true in other case I copied the error from. Not sure yet if true here.
|
This pull request has merge conflicts that must be resolved before it can be merged. |
c05fc4d to
d3c8a56
Compare
96230ce to
6089e76
Compare
f4ca572 to
5fa24e4
Compare
|
|
||
| Classic workers are fetched in `no-cors` mode, executed as scripts, and import other scripts using {{domxref("WorkerGlobalScope.importScripts()")}} (not `import` statements). | ||
| Because they are fetched in `no-cors` mode, cross-origin requests are not blocked by CORS, and the response does not have to include the `Access-Control-Allow-Origin` header. | ||
| Unlike for modules, the document [Content Security Policy (CSP)](/en-US/docs/Web/HTTP/Guides/CSP) is not affected by the `worker-src` directive, but it is still affected by sources listed in the `script-src` directive. |
There was a problem hiding this comment.
My testing shows that
- module workers respect
worker-src. So if you set aCSP: worker-src 'self'you can load a module (which is always same origin), then it canimportfurther same origin modules, but NOT cross-origin modules. - classic/script* workers do not respect
worker-src. So if you set aCSP: worker-src 'self', a wokrer script can import a cross origin script usingimportScript. - classic/script* workers do respect
script-src, So if you set aCSP: script-src 'self'this will block a worker script loading a cross origin script.
There was a problem hiding this comment.
It sounds like you're saying that worker-src controls the scripts that a worker can load? Not the source of the worker itself? In that case isn't the example here wrong: https://w3c.github.io/webappsec-csp/#directive-worker-src ?
There was a problem hiding this comment.
@wbamberg I have updated my note above to state more clearly what testing shows.
But to summarize, I'm saying that
worker-srcaffects the scripts that can be imported into a module worker, but not the scripts that can be imported into a classic worker.worker-srcseems to be pointless, since if I specifyContent-Security-Policy: worker-src https://example.com/neither a module or classic script at that address will load. ONLY same-origin modules ever load.
Clearly the intent is that the worker-src allows control over where module scripts can be loaded from, and "perhaps" also where they may load. But that's not what my testing is showing. Of course my testing might be wrong.
There was a problem hiding this comment.
Hoping to get some clarity from Jake in https://github.com/mdn/content/pull/42073/files#r2666249206
There was a problem hiding this comment.
As in me? Which part? I think GitHub is being unhelpful and hiding something
There was a problem hiding this comment.
Hamish is out for the next two weeks but I promised to try to get this PR merged if I could :).
The question we have is, when a page loads a worker script, does the worker have to be same origin with the loading document? The page for the Worker() constructor says:
This script must obey the same-origin policy.
...which seems to me a curious thing to say (I mean, everything has to obey the SOP, it's a browser policy, so what is the substantive force of this statement?). We weren't sure whether this means "the script must be same origin with the loading document". Hamish's tests indicate that it does have to be same origin.
But that raises further questions, such as, what is the worker-src CSP directive for, then? The spec for worker-src even has an example of how you would use the directive to block workers from a different source, and why would you need that if the worker needs to be same origin?
So we thought we could ask you since you probably know.
There was a problem hiding this comment.
Yeah the root worker script needs to be same origin. However, scripts from other origins can be loaded via ES imports and importScripts. I guess that's what worker-src is for
There was a problem hiding this comment.
OK, thank you! Then it looks like Hamish's tests are all right.
I guess that's what worker-src is for
That is still odd, because it's not what the example from the spec is showing: https://w3c.github.io/webappsec-csp/#example-fd6c5849. But I'm going to let it go now :).
There was a problem hiding this comment.
Thanks @jakearchibald and @wbamberg . It is a relief to know that all the testing was not just "wrong". I'm OK to let this all go for now - as you say it is a bit odd but it is what I saw.
wbamberg
left a comment
There was a problem hiding this comment.
I haven't finished but I got so many questions about SOP that I thought I should give you them.
| - : A string specifying the type of worker to create. The value can be `classic` or `module`. If not specified, the default used is `classic`. | ||
| - : An object containing option properties that can be set when creating the object instance. | ||
| Available properties are as follows: | ||
| - `credentials` |
There was a problem hiding this comment.
I guess this has the same meaning (and constraints?) as https://developer.mozilla.org/en-US/docs/Web/API/RequestInit#credentials, where it is all described more fully (including saying what credentials are). Maybe link there and say this?
There was a problem hiding this comment.
Yes. Done in 1837809
This controls whether a module worker sends credentials when it imports a cross-origin module.
This is ignored for classic modules. They send credentials for same-origin imports. They generally won't send them for cross-origin imports - it isn't under the control of the interface. They might if the remote server allows it.
| All same-origin workers can load same-origin scripts by default. | ||
| However because module scripts are fetched using CORS, cross-origin scripts must be served with the {{httpheader("Access-Control-Allow-Origin")}} header. | ||
| In addition, the if the document has a [Content Security Policy (CSP)](/en-US/docs/Web/HTTP/Guides/CSP), it must allow the origins of imported worker scripts in `worker-src` (with fallback to `script-src` and `default-src` directives). | ||
|
|
||
| Classic workers are fetched in `no-cors` mode, executed as scripts, and import other scripts using {{domxref("WorkerGlobalScope.importScripts()")}} (not `import` statements). | ||
| Because they are fetched in `no-cors` mode, cross-origin requests are not blocked by CORS, and the response does not have to include the `Access-Control-Allow-Origin` header. | ||
| Unlike for modules, the document [Content Security Policy (CSP)](/en-US/docs/Web/HTTP/Guides/CSP) is not affected by the `worker-src` directive, but it is still affected by sources listed in the `script-src` directive. |
There was a problem hiding this comment.
Am I right to understand that these 2 paras are exclusively about scripts that the worker script itself loads? i.e. they're not about loading the worker script itself (since that's always same-origin)?
If so then I think you ought to have a heading like "Loading scripts from a worker" or something, to make this very clear.
| In addition, the if the document has a [Content Security Policy (CSP)](/en-US/docs/Web/HTTP/Guides/CSP), it must allow the origins of imported worker scripts in `worker-src` (with fallback to `script-src` and `default-src` directives). | ||
|
|
||
| Classic workers are fetched in `no-cors` mode, executed as scripts, and import other scripts using {{domxref("WorkerGlobalScope.importScripts()")}} (not `import` statements). | ||
| Because they are fetched in `no-cors` mode, cross-origin requests are not blocked by CORS, and the response does not have to include the `Access-Control-Allow-Origin` header. |
There was a problem hiding this comment.
I don't really understand this. It seems to be saying: because classic workers are fetched in no-cors, then they can make cross-origin requests without CORS headers (btw "not blocked by CORS" is not a good way to put it, CORS doesn't block anything, it only unblocks things).
But is that right? Why does the mode a script was fetched in affect the mode of the requests it makes? I don't think this is true. If a resource is fetched in no-cors then the fetching of it has certain attributes, but I don't think that "carries over" to the requests that it makes, does it?
There was a problem hiding this comment.
@wbamberg So yes, I am saying that classic workers are fetched in no-cors mode. My understanding was that this mean't that any requirements of CORS are ignored - the request will succeed as if CORS headers were not set.
I did not mean to make any statement about what mode a classic script would import its scripts using - I just tried to make clear that a classic script uses importScripts() to load further scripts, and not import.
You're right that we can't draw any assumptions about this. That said, that is what my tests showed. I'll try check again on Friday.
There was a problem hiding this comment.
@wbamberg So yes, I am saying that classic workers are fetched in no-cors mode. My understanding was that this mean't that any requirements of CORS are ignored - the request will succeed as if CORS headers were not set.
But that's only relevant for cross-origin fetches, right? So if fetching a worker has to be same-origin, it's irrelevant. Put another way, the doc says:
Because they are fetched in
no-corsmode, cross-origin requests are not blocked by CORS,
...what are these "cross-origin requests", if fetching a worker has to be same-origin?
There was a problem hiding this comment.
Cross origin import requests made by the worker.
There was a problem hiding this comment.
I have addressed in https://github.com/mdn/content/pull/42073/files#r2674625053
|
|
||
| Classic workers are fetched in `no-cors` mode, executed as scripts, and import other scripts using {{domxref("WorkerGlobalScope.importScripts()")}} (not `import` statements). | ||
| Because they are fetched in `no-cors` mode, cross-origin requests are not blocked by CORS, and the response does not have to include the `Access-Control-Allow-Origin` header. | ||
| Unlike for modules, the document [Content Security Policy (CSP)](/en-US/docs/Web/HTTP/Guides/CSP) is not affected by the `worker-src` directive, but it is still affected by sources listed in the `script-src` directive. |
There was a problem hiding this comment.
It sounds like you're saying that worker-src controls the scripts that a worker can load? Not the source of the worker itself? In that case isn't the example here wrong: https://w3c.github.io/webappsec-csp/#directive-worker-src ?
40c7414 to
01ce5b6
Compare
2add044 to
1837809
Compare
403d673 to
047a381
Compare
| - Dependencies are imported using the {{domxref("WorkerGlobalScope.importScripts()")}} method | ||
| - Fetched synchonously in `no-cors` mode |
There was a problem hiding this comment.
We would expand this with other differences if we knew them.
| In addition, if the document has a [Content Security Policy (CSP)](/en-US/docs/Web/HTTP/Guides/CSP), it must allow the origins of imported scripts or modules. | ||
| For modules the allowed sources are specified in `worker-src` (with fallback to `script-src` and `default-src` directives), while for classic scripts the sources are specified in `script-src` (with fallback to the `default-src` directives). |
There was a problem hiding this comment.
@wbamberg I think this is ready for another look.
Unfortunately I ate the commits while trying to create a version where it would be easy to be determine the changes.
Since last you looked I have addressed your comments, including adding this section on importing scripts and the credentials.
Essentially I think my testing provides a consistent story (or or less) - workers must be constructed with a same origin script/module. The credentials apply to the modules that are imported by a module worker (but not a script worker, over which you have no control via the API).
The remaining inconsitency is this section - why would you use worker-src if you can't import the main script cross-origin, and why is it ignored for scripts. However this is what my testing shows about CSP. If we question this too much, we could drop this line. Or just put it in, and hope to tidy later.
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
wbamberg
left a comment
There was a problem hiding this comment.
Thank you for all your work on this Hamish.
The
Worker()andSharedWorker()constructors takes aurlparameter that that can be aTrustedScriptURL. This attempts to follow the pattern of our other trusted types docs and add the header warning and security considerations section.SharedWorkerappears to be the same as Worker but of course constructs a different object. To reduce duplication I have mostly linked fromSharedWorker()rather than copy-pasting.Related project: #41507