WICG/import-maps

Integrity proposal

guybedford opened this issue ยท 15 comments

I'd like to move forward with an integrity proposal in SystemJS and ES Module Shims as an extension of this specification.

Would this repo be the right place to suggest that?

I've added an integrity proposal to the import maps extensions repo, which currently is an aim to try and capture the spill-over on discussions not currently happening here - https://github.com/guybedford/import-maps-extensions#integrity.

Right the web platform already has SRI and the capability to add them to imports, this would solve the cache invalidation turtles all the way down that @mozfreddyb and @fmarier will be very familiar with.
This likely relates to: #76 and other abilities to modify the import.

Although I still believe this would be best in a general fetch map, not a JS import-specific one, the proposal at https://github.com/guybedford/import-maps-extensions#integrity is simple enough, and we've seen such bad progress on fetch maps, that I'd be willing to pursue this in a hypothetical future where we got more engineers to work on import maps in Chromium. (See #235 (comment) for more background.) As such, any thumbs-up votes on the OP here would be helpful for such future prioritization.

Whilst decoupling this idea from import maps seems worthwhile to improve traction. My hunch is the engineering effort to implement this would be pretty significant and not too dissimilar to import maps alone.

This has the ability to resolve many problems:

  • Solving CSS not having the ability to specify SRI
  • Cache invalidation of modules when SRI is required
  • Re-bundling an entire tree of files because a single dependency changed

Although I still believe this would be best in a general fetch map

Can the design can account for this without implementing other imports types?

Moving over some discussion from #174 โ€” @guybedford listed a few options:

  1. Have a link preload for not actually preloading. See eg https://lists.w3.org/Archives/Public/public-webappsec/2021Mar/0002.html.

  2. Include integrity in the import map itself. See eg https://github.com/guybedford/import-maps-extensions#integrity

  3. Rely on bundlers that perform dynamic import wrapping, although this will tie cache digests to sources unless that technique can in turn use a bundle manifest, say eg a <script type="bundle-manifest"> that the bundler can read.

With the caveat that I'm relatively unfamiliar with import maps, one thought is that options 1 and 2 aren't mutually exclusive.

As someone who's publishing a library that's intended to be included via a <script> tag (rather than buying into a specific package ecosystem), it would be nice to publish a import map containing the hashes for all the files that my library might load, and to distribute that import map via the same mechanism that the library code is distributed by โ€” this will ensure that the hashes in the import map don't get out of date with the library code. (obviously there's a ways to go before this is viable, since it relies on both external maps and potentially multiple maps on the same page, but it should eventually be supported)

As mentioned above, this doesn't enable SRI for CSS (and other content types) โ€” I don't think it's unreasonable to have some form of link tag that specifies a SRI hash for arbitrary content without preloading, while also allowing people to specify SRI hashes for their javascript via import maps.

This path forward would:

  • Enable people to specify SRI hashes for arbitrary content types, without needing to wait for fetch maps (which I can't seem to find any spec/discussion for?)
  • Allow import maps to focus solely on javascript, knowing that SRI for other content types can be handled separately. (We don't need to worry then about what it means for CSS or an image to be scoped, for instance)
  • Allow people to get the benefits of specifying SRI hashes in their import maps (tooling integration, enabling libraries to ship SRI hashes alongside library code, etc)

Adding SRI to both <link> and import maps makes the implementation pretty simple for both of those things, and gives people the tools that they need to be able to use SRI both generically and ergonomically for javascript specifically.

Adding @dandclark and @BoCupp-Microsoft who might like to contribute to this discussion.

Maybe split integrity outside import map?

  1. Recently I tried deno. The import map can be small and human readable. But the lock.json might be very long and human not readable.
  2. Are there similar practice split them? I'm not sure, but proxy.golang.org and sum.golang.org seems the case.

Hi. I use import maps a lot and download all dependencies manually as I can't trust cdns or repo owners of external libraries are not compromise.

IMHO Integrity will make import maps production ready. Before that it should be flag as insecure for external resources/libraries as most JS library already include Integrity in their copy/paste snippets.

As impormaps are becoming popular it is urgent to have integrity before mass adoption. So there is no time to big changes in the spec.

The current proposal:

  • adds complexity and
  • adds extra size to the html, that might be considerable for big sites.
  • Will take time to implement

As the urls inside the impormaps are not user faced, I suggest to use the URL fragment to include the integrity.

  • Fragments are not sent over the weird
  • Don't have any defined use case for non user facing urls
  • minimal impact and change required
  • Progressive deployment as it is compatible with existing implementation
{
    "slider": "http://insecure.site/slider.js#sha384-oqVuAfXRKap7fdgcCY5uykM6+R9GqQ8K/uxy9rx7HNQlGYl1kPzQho1wx4JwY8wC
}

I personally dislike the use of url fragments, but given the urgency I believe it is important.

ije commented

Hi. I use import maps a lot and download all dependencies manually as I can't trust cdns or repo owners of external libraries are not compromise.

IMHO Integrity will make import maps production ready. Before that it should be flag as insecure for external resources/libraries as most JS library already include Integrity in their copy/paste snippets.

As impormaps are becoming popular it is urgent to have integrity before mass adoption. So there is no time to big changes in the spec.

The current proposal:

  • adds complexity and
  • adds extra size to the html, that might be considerable for big sites.
  • Will take time to implement

As the urls inside the impormaps are not user faced, I suggest to use the URL fragment to include the integrity.

  • Fragments are not sent over the weird
  • Don't have any defined use case for non user facing urls
  • minimal impact and change required
  • Progressive deployment as it is compatible with existing implementation
{
    "slider": "http://insecure.site/slider.js#sha384-oqVuAfXRKap7fdgcCY5uykM6+R9GqQ8K/uxy9rx7HNQlGYl1kPzQho1wx4JwY8wC
}

I personally dislike the use of url fragments, but given the urgency I believe it is important.

but how do you handle imports with tailing /

but how do you handle imports with tailing /

Can you provide an example?

ije commented

but how do you handle imports with tailing /

Can you provide an example?

{
"slider/": "http://insecure.site/slider/"
}

Can you provide an example?

{ "slider/": "http://insecure.site/slider/" }

 { "slider/": "http://insecure.site/slider/#sha384-oqVuAfXRKap7fdgcCY5uykM6+R9GqQ8K/uxy9rx7HNQlGYl1kPzQho1wx4JwY8wC" }

Note:It is not recommend that use case as some cache servers might consider:

http://insecure.site/slider/
http://insecure.site/slider

The same entry, while origin might map

http://insecure.site/slider/ to http://insecure.site/slider/index.js
http://insecure.site/slider to http://insecure.site/slider.js

Creating a cache mess.

Edit: I think now that your refer to map prefixes.
That way you will not be able to specify the integrity.

In the previous proposal, you will have an extra hash were you indeed list all the files. If you are going to list all the files with the integrity anyway, just list them in the importmap.

I like how the "hash" (as we used to refer to URL fragments back in the day) in #221 (comment) actually is a cryptographic hash.

I do feel a bit cautious about appropriating the entire fragment for this purpose; a well defined prefix, e.g., integrity:, might make this idea slightly more forward compatible.

Hello... we are using Single Spa with React. I am not a UI expert, know enough to be dangerous :)

I am confused by import-map json, is that a single-spa feature or a System.js feature?
Is there a solution? If so, is it an upgrade to Single Spa or System JS?

Currently, we moved our import map to a nginx server that serves out importmap.js files, we can update the import map json for any environment and serve it out. Updating importmap is manual.

We are experimenting with putting importmap in a db with an API in front of it to serve out the json. We can use our pipeline to increment version in the DB (that is the motivator) and cache bust after every post deploy event.

If adding a 'integrity' node in the importmap json does not work then how can we get integrity checks? Is the hash method preferred? Has his been proven to work?

we are also behind a CDN.

Anyone have any solutions to share?

@xpagesbeast Can you please move your question to https://github.com/single-spa/single-spa/discussions ? Thanks.