21

Given code like this:

import { el, mount } from 'https://unpkg.com/redom@3.2.1/dist/redom.es.js';

is there some way to enable subresource integrity verification to ensure that the CDN asset returns the expected content?

loganfsmyth
  • 135,356
  • 25
  • 296
  • 231
jens1o
  • 358
  • 3
  • 13
  • What can I do to improve my question? What's the problem? I don't know what I did wrong, and why I have that downvote.... :/ – jens1o Aug 21 '17 at 20:53
  • 3
    I don't have an actual answer, though I suspect the answer is no because this stuff is so new and the spec isn't really done yet. I also edited your question to drop some unneeded details and make the question clearer. – loganfsmyth Aug 21 '17 at 21:20
  • Have you tried setting the `integrity` attribute on a ` – Noah Freitas Aug 21 '17 at 21:26
  • That's working, but it doesn't solve my problem in general, because I only can require from each script inside my module. And in my main module, I need to load the dependency. – jens1o Aug 21 '17 at 22:23
  • 1
    @jens1o, it looks like there's some discussion of having this be based on a `` with an integrity attribute: https://github.com/w3c/webappsec-subresource-integrity/issues/26 and https://github.com/w3c/webappsec-subresource-integrity/issues/70 – Noah Freitas Aug 21 '17 at 23:08
  • 1
    It seems like the type of thing where you'd expect a query parameter or something, but I don't know that there's any discussion of that yet. – loganfsmyth Aug 22 '17 at 00:28

4 Answers4

3

You have to also define the module via

<script type="module" integrity="..." src="https://unpkg.com/redom@3.2.1/dist/redom.es.js">

What you're asking specifically requires changes to ECMAScript itself and currently there's not even a proposal for it, so I don't expect it to appear anytime soon.


However in the case of UNPKG, if you trust UNPKG and Cloudflare not to mess with the content, you're fine. Neither npm nor the package author can modify the file as long as you specify the version.

fregante
  • 23,010
  • 11
  • 97
  • 127
  • 1
    In addition to trusting the servers, you must also trust the network connection to them. In oppressive regimes national ISPs could collude with certificate authorities by law. – fuzzyTew Apr 09 '20 at 09:23
  • Kinda, but if they can change content served via HTTPS, nothing can save you; they already changed the HTML page you loaded, including the dropping any `integrity` attributes. – fregante Apr 09 '20 at 15:50
  • Maybe. I'm working with blockchains where the primary content is far more reliable. Same might be more true for things like electron and cordova apps, or if your primary host simply had a better certificate system than unpkg. Cloudflare protects so much of the internet it would be a far more highly valued door than a small host. More checks always help integrity. But nor do they prove it. – fuzzyTew Apr 10 '20 at 16:14
  • Beware that this won't work in Safari today. As of Safari 14.0.1 (which is the current latest version), if you put in a ` – Dan Fabulich Dec 01 '20 at 05:23
2

From an HTML document, you can use the <link rel="modulepreload"> element to perform that integrity check, which is unfortunately currently supported only in Blink browsers.

// default script
import( "https://unpkg.com/redom@3.2.1/dist/redom.es.js" )
  .then( module => console.log( 'from default script:', typeof module.List ) )
  .catch( console.error );
<link rel="modulepreload" 
  href="https://unpkg.com/redom@3.2.1/dist/redom.es.js"
  integrity="sha384-notthecorrectsha">
<script type="module">
  import { List } from "https://unpkg.com/redom@3.2.1/dist/redom.es.js";
  console.log( 'from module script:', typeof List );
</script>

The same snippet without the integrity check:

// default script
import( "https://unpkg.com/redom@3.2.1/dist/redom.es.js" )
  .then( module => console.log( 'from default script:', typeof module.List ) )
  .catch( console.error );
<link rel="modulepreload" 
  href="https://unpkg.com/redom@3.2.1/dist/redom.es.js">
<script type="module">
  import { List } from "https://unpkg.com/redom@3.2.1/dist/redom.es.js";
  console.log( 'from module script:', typeof List );
</script>

Note that this check would also apply to "sub-modules", but not to Workers.

Kaiido
  • 87,051
  • 7
  • 143
  • 194
1

With Deno supporting such imports for its dependencies (and having no out-of-the-box package manager) and Node leaving open the chance for importing non-file URLS in the future, this issue becomes even more important.

While what @fregante mentions about there not being yet a proposal remains accurate, https://github.com/WICG/import-maps/issues/174 includes discussion, including via a referenced slide presentation, of some of the questions raised in modifying the syntax (e.g., transitive dependency cache invalidation) to support SRI as well as other possible alternatives.

Brett Zamir
  • 12,481
  • 5
  • 45
  • 68
0

You can use RequireJS, and transpile your code to AMD or UMD to achieve this. RequireJS has a hook onNodeCreated, which gives you access to the script tag before it is added to document. You can add the sri attribute onto the script tag:

onNodeCreated: function(node, config, module, path) { node.setAttribute('integrity', integrityForModule); node.setAttribute('crossorigin', 'anonymous'); }

credit: https://stackoverflow.com/a/37065379

I use Webpack (with a target of UMD) and RequireJS. With the relevant modules put in the external section of the webpack configuration file, so the modules are not compiled into the transpiled code.