Inline ES Modules

Darien Valentine valentinium at
Wed Jun 20 01:50:24 UTC 2018

Aha! Thanks. I think I get what you mean now.

Let’s say I have this CSP:

content-security-policy: script-src 'nonce-foo'

And I have this in my document:

<script nonce=foo type=module>
  import 'data:text/javascript,console.log(`bar`)';

Then the browser could theoretically ignore the absence of 'data:' in the
CSP safely because the import statement here is part of a nonce-allowed
script. And the unsafety is adding `data:` to the CSP (which would then be
available for third party scripts I might also allow), not using `data:` in
my own trusted modules; and there is a minor bit of unsafety associated
with dynamic import, but it’s not in the same league as the unsafety
potentially implied by a blanket permission for all `data:` URI sources.

I was surprised that this nuance was considered. I figured it just blindly
asked "is this source permitted by the CSP" without taking into account
whether the trust from a parent resource could be implicitly extended. But
I see you’re totally right:

<!DOCTYPE html>
<meta http-equiv=content-security-policy content="script-src 'nonce-foo'">
<script nonce=foo type=module>
  import 'data:text/javascript,;document.writeln(`<p>static
import of data URI module worked</p>`)';
  document.writeln(`<p>nonce module worked</p>`);
  import('data:text/javascript,document.writeln(`<p>dynamic import of data
URI module worked</p>`)');


All three seem to work! Very cool.

Sorry for the diversion from the main topic. This was really interesting
and I appreciate the explanation.

On Tue, Jun 19, 2018 at 8:58 PM Mike Samuel <mikesamuel at> wrote:

> Sorry for the confusion.
> Nonces are just for elements with url attributes.
> I mentioned nonces to point out that strict CSP policies can allow some
> data: urls without having to explicitly whitelist or hash the entire
> content.
> Separately I wanted to say that there is no incompatibility between the
> goals of CSP and import statements that use a data: module specifier, since
> we already trust the compilation unit and there's no actual network message
> leaked.
> But there is a risk with the import operator since it's input is not part
> of an already trusted input.
> On Tue, Jun 19, 2018, 8:22 PM Darien Valentine <valentinium at>
> wrote:
>> Mike: Ah, cool, I didn’t realize that — I had thought that nonces were
>> just for whitelisting inline script elements. How does one specify a nonce
>> in association with a data URI? I’m having trouble turning up a description
>> / example of how it would work. Or possibly I’m misunderstanding this quite
>> a bit, hm ... I’m also confused by the relationship between import/import()
>> and XSS that you’ve described.
>> On Tue, Jun 19, 2018 at 8:06 PM Mike Samuel <mikesamuel at> wrote:
>>> CSP with data URIs is possible via nonce sources.  For data: module
>>> descriptors browsers could safely skip the CSP check since it doesn't allow
>>> XSS unless one can already specify an import statement which typically
>>> means one can specify arbitrary JS.  That argument doesn't extend to the
>>> import operator though so you'd have to tolerate assymetry there.
>>> On Tue, Jun 19, 2018, 7:57 PM Darien Valentine <valentinium at>
>>> wrote:
>>>> Andrea: That is a really interesting approach. I would point out that
>>>> using data URIs for js means the `data:` scheme has to be a permitted
>>>> source for script-src. This allowance has roughly the same security
>>>> implications as permitting `unsafe-eval`. I know most people aren’t using
>>>> CSPs yet, but personally I’d be wary of a solution that makes it harder to
>>>> adopt a strong CSP.
>>>> A super dorky/tangential aside that probably doesn’t matter at all but
>>>> ... I notice you used application/javascript for the media type. There’s a
>>>> contradiction between the IANA media type registry and the HTML 5 spec with
>>>> regard to the "correct" media type to use for JS. RFC 4329 says
>>>> application/javascript is the only value that should be used, while HTML
>>>> says text/javascript is the only value that should be used. I believe (not
>>>> sure though) that this is because it’s the most backwards-compatible value.
>>>> Given that the media types registry seems to be basically dead to web
>>>> standards (if we follow the registry we can’t serve or post a bunch of
>>>> media types acknowledged or defined by web standards at all, including
>>>> image/webp, application/csp-report, etc) and the code has to run in a
>>>> browser, I’d tend to think HTML is the better spec to follow ... though I
>>>> guess when two specs contradict each other it’s hard to make an objective
>>>> case for one being more authoritative. (I’d be curious if there’s a
>>>> specific reason you know of to prefer to RFC definition though. When
>>>> standards don’t align it breaks my tiny heart.)
>>>> On Tue, Jun 19, 2018 at 4:09 PM Andrea Giammarchi <
>>>> andrea.giammarchi at> wrote:
>>>>> sorry, I meant:
>>>>> JSON.stringify('data:text/javascript,' +
>>>>> moduleContentAfterTreeShaking);
>>>>> On Tue, Jun 19, 2018 at 10:09 PM, Andrea Giammarchi <
>>>>> andrea.giammarchi at> wrote:
>>>>>> I think these are all nice to have features, but I also think we have
>>>>>>> all the primitives we need to make it happen via pre-processing.
>>>>>> I meant even synchronously, with a pre-processor that replace the
>>>>>> imported module with
>>>>>> 'data:text/javascript,' +
>>>>>> JSON.stringify(moduleContentAfterTreeShaking);
>>>>> _______________________________________________
>>>> es-discuss mailing list
>>>> es-discuss at
>>> _______________________________________________
>> es-discuss mailing list
>> es-discuss at
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <>

More information about the es-discuss mailing list