Open shhnjk opened 3 years ago
Can you sketch out import-src
in a little more detail? What behavior would it influence?
/cc @lweichselbaum @koto
There are mainly 2 reasons why we'd probably want to implement import-src
.
'strict-dynamic'
(see https://github.com/w3c/webappsec-csp/issues/243#issuecomment-346506773).I feel like we should probably separate mitigation for import mechanism out of script-src
(similar to worker-src
), so that more specific mitigations can be applied for import
s without affecting other script loading.
The suggestion I made about 'allow-static-imports'
is basically to solve the problem #1. For HTML Modules and co, I just have a feeling that it's little weird to have mitigation for HTML loading in script-src
.
Thanks! I still don't think I understand the distinction you're drawing between imports and plain ol' scripts. What's a policy you'd recommend that folks construct that would apply specific mitigations for import
without affecting other script loading? If we could jam keywords for static/dynamic imports into script-src
, would that satisfy the need, or is there something different about the way we want to recommend folks handle imports?
I don't have answers, only more questions :)
It kinda depends on two things:
A similar syntax is used for importing JS and non-JS modules, and it's probable these would behave and evolve in a similar way in EcmaScript. They already do - e.g. both can already be loaded dynamically, or statically. If we want to put guards on these specific behaviours, it might make sense to start afresh and put them together under a separate directive and a set of keywords instead of complicating the script-src
even more. That said, b/w compatibility would be an issue here.
If we don't plan to guard non-JS modules, and only focus on JS ones, script-src
is the closest match indeed, so the only problem is practical - would we be able to add more keywords without that house of cards falling down.
If import maps ship, the advantage of a separate directive is that we could separately guard on module specifiers and resulting URLs:
module-src foobar/*; script-src https://foo.bar/
If we think there's value in guarding module specifiers and not URLs, and expect import maps to ship, that directive is also a better fit for new keywords e.g. 'allow-dynamic-import'
.
Alternatively, we could:
script-src
, guarded by their URL, as it behaves nowdynamic-import-src
directive that can disable it completely ('none'
) or guard them by URL (now), or module specifiers (after import maps). dynamic-import-src 'self' https://my.cdn/* 'module-foo/*'
? In the most advanced configuration, the module loaded dynamically would have to satisfy both script-src
and dynamic-import-src
.Essentially, I think the problem boils down to dynamic import. The only way to guard it now is by CSP script-src
URL allowlists which we are discouraging. And since nonces / TT are not coming to dynamic imports anytime soon, there should be something to guard that sink, at the very least prohibiting it completely.
Thanks! I still don't think I understand the distinction you're drawing between imports and plain ol' scripts. What's a policy you'd recommend that folks construct that would apply specific mitigations for
import
without affecting other script loading? If we could jam keywords for static/dynamic imports intoscript-src
, would that satisfy the need, or is there something different about the way we want to recommend folks handle imports?
Plain scripts can be mitigated with nonce, but import
s can't be (which should require 'strict-dynamic'
but it isn't today).
To solve this problem today, Web apps are forced to add 'strict-dynamic'
or add an allow-list for import
s in script-src
, which either weakens CSP (e.g. 'nonce-R4nd0m' 'strict-dynamic'
or 'nonce-R4nd0m' https://import-src.app.example
) than nonce-only CSP, or make deployment of such policy much harder (i.e. supply 2 headers of CSP, one with nonce and another with allow-list of all endpoints they use in addition to scripts used for import
s).
While a keyword like 'allow-static-imports'
can be added to script-src
, providing additional directive makes deployment a lot easier, and has potential for extension (e.g. if we see dangerous practice from devs with HTML Modules). It's also important to note that all import
s can't be guarded with Trusted Types, so script-src
is the only mitigation place for those currently.
With that probably recommended (for now) CSP that demonstrates good use of import-src
are:
CSP: script-src 'nonce-R4nd0m'; import-src 'allow-static-imports';
(if a web app doesn't use dynamic import).CSP: script-src 'nonce-R4nd0m'; import-src https://my-static-endpoint.app.example/modules/;
(if a web app does use dynamic import).2. what happens with import maps that would allow module specifiers, now forbidden in the web.
Import maps requires script tags, therefore it can be mitigated by nonce. So, I'm not terribly concerned about that.
Essentially, I think the problem boils down to dynamic import. The only way to guard it now is by CSP
script-src
URL allowlists which we are discouraging. And since nonces / TT are not coming to dynamic imports anytime soon, there should be something to guard that sink, at the very least prohibiting it completely.
Agreed that the main problem we have right now is dynamic import.
JavaScript is capable of loading other scripts (e.g. static and dynamic import). But it can also load modules like JSON, CSS, and (in the future) HTML.
Issues 243 acknowledges that there is an issue with dynamic import, but we aren't making progress there.
We should probably start a discussion about
import-src
that fallback toscript-src
, where we can control those import behavior from JS (which I believe bypasses nonce-based CSP).In addition to allow-list based based blocking mechanism, it'll be interesting to consider keywords that only denies dynamic import (e.g.
import-src 'allow-static-import'
), or something that allows import with TrustedScriptURL (not sure if this is doable though).P.S. I intentionally haven't mentioned
importScripts
, because that's probably controlled byworker-src
.