To be fair, running a mismatched version of the JS could already break things if the changes are big enough, but for minor updates, the user often won't notice the difference. Now, these cases are hard failures. That's not necessarily a bad thing, but I wonder if there's a path here to tell the browser "you have an old version of the content; go get the new version."
CDNs and invalidations can be tricky, and it sounds like this could lead to things being broken more often if you're caught in the window where one piece updates before the other.
Maybe I should refrain from posting my gut reactions (or at least wait until I'm awake first). =)
Only if your page requires JavaScript to function and doesn't gracefully degrade. None of us would ever write that sort of page, would we?
For example the <noscript> tag works that way.
The way that this fixes the issue is by ensuring that the file being loaded on those thousands of websites is the correct one, and not the malicious attack script that was injected by the Chinese government or other such actors, otherwise it's not run at all.
Could the Chinese government rewrite the HTML of all these thousands of websites to also change the hash? Theoretically yes, but practically it makes it much more difficult.
Hashes means you have to specify an exact version, so there's not an easy way to add integrity to things like Google's CDN for jQuery that has latest minor version update links for the major API versions of jQuery.
Of course, that means also adding a signature to the payload response (maybe an "Integrity: <hash>-<sig>" header?). So it's understandable why signatures weren't in scope for the first release.
If a hypothetical attack breaks TLS or you don't use it, you can just change the public key served.
It also lets you use CloudFront as a CDN for your own JS without having to trust them to serve the content as you described it, if you calculate your hashes based on the scripts you sent them.
Subresource integrity is in some ways more important than "HTTPS Everywhere", because the MITM-as-a-service sites such as Cloudflare subvert HTTPS Everywhere. For security reasons, you might choose to serve your home page and a few security-critical pages from your own server, without using a CDN. But run everything else through the CDN, using subresource integrity to keep the CDN honest.
With subresource integrity, many items no longer need to be encrypted. This is good for security. Encryption interferes with caching, and HTTPS in front of caches means that the attack surface is larger, and includes the CDN.
(Yes, there's an argument that HTTPS conceals what the user was browsing. Not really. Checking document length will provide a good hint on what static asset was read. The pattern of document lengths requested tends to fingerprint the page being read.)
Frankly I'm relieved to see that browser vendors and leading tech firms are maintaining control of the situation and protecting users, even if driven by self-interest.
If you start seeing unexplained errors on pay-as-you-go phones, you'll know why; although if this facility gains popularity then I'm sure they'll be pressured to stop modifying content.
original: IIRC CSP already has hashes for resources, which also would handle this purpose.
As a side note, there's at least one CDN already hosting fake copy of bootstrap - I've seen a mlicious extension loading it in my report-uri.io logs.
This matters: If someone wants to hack my company, they're not going to do it by hacking Github's CDN. They're going to do it by targeting particular employees -- probably focusing on those who have the least security experience. To reduce risk, I need to give each team member the least authority they need to do their job. Github is making it really hard for me to do that; I tend to have to give "admin" rights to everyone. :(
Widespread adoption of Subresource Integrity could
have largely prevented the Great Cannon attack
earlier this year.
Sorry, it wouldn't have. From the CitizenLab report [1] on the Great Cannon attacks: In the attack on GitHub and GreatFire.org, the GC
intercepted traffic sent to Baidu infrastructure
servers that host commonly used analytics, social,
or advertising scripts. If the GC saw a request
for certain Javascript files on one of these servers,
it appeared to probabilistically take one of two
actions: it either passed the request onto Baidu’s
servers unmolested (roughly 98.25% of the time),
or it dropped the request before it reached Baidu
and instead sent a malicious script back to the
requesting user (roughly 1.75% of the time). In
this case, the requesting user is an individual
outside China browsing a website making use of a
Baidu infrastructure server (e.g., a website with
ads served by Baidu’s ad network). The malicious
script enlisted the requesting user as an unwitting
participant in the DDoS attack against GreatFire.org
and GitHub.
So the idea is someone runs a site with: <script src="http://baidu.com/ads.js">
When visitors request these scripts the request passes through the "Great Cannon" which 1.75% of the time serves a different script instead. That malicious script makes lots of requests to the victim sites, and they're overloaded.To prevent this sort of attack with SRI you would need to change your page to look like:
<script src="http://baidu.com/ads.js"
integrity="hash of the real ads.js">
The problem is, Baidu isn't going to be willing to commit to always serving the same ads js: they need to be able to make upgrades.SRI is useful in the case where the entity producing the html is referencing js that they've uploaded to a third party CDN or js where they choose what version to run, but not in the normal "include a snippet and we'll do stuff to your page" model.
(To block the Great Cannon there, what would have worked would be moving the js serving to HTTPS.)
IPFS comes to mind.
Bravo. :)