-
Notifications
You must be signed in to change notification settings - Fork 27.4k
feat(security): do not bootstrap from unknown schemes with a different origin #15428
Conversation
@@ -1454,8 +1454,7 @@ function allowAutoBootstrap(document) { | |||
var link = document.createElement('a'); | |||
link.href = src; | |||
var scriptProtocol = link.protocol; | |||
var docLoadProtocol = document.location.protocol; | |||
if (docLoadProtocol === scriptProtocol) { | |||
if (document.location.origin === link.origin) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not so sure about this - are we certain that we won't have extension protocols in which origin is different between e.g. different parts of the extension, but the scheme/protocol would be the same?
I think it's a good idea to be conservative in areas where we know it's a security issue, but do we have any idea about an attack vector at all for this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1, this looks too risky and doesn't seem to add that much value. Let's deal with this once we have a concrete example where the original change is not sufficient.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
are we certain that we won't have extension protocols in which origin is different between e.g. different parts of the extension, but the scheme/protocol would be the same?
Yes I am. All URLS that reference parts of one extension have a single origin (at least in Chrome, Firefox, Safari, Opera; I haven't looked at others but I assume the same holds too).
I can't think of a legitimate use case for loading Angular.js from another extension.
I think it's a good idea to be conservative in areas where we know it's a security issue, but do we have any idea about an attack vector at all for this?
Bootstrapping Angular.js from an extension in a normal web page was disabled in #15427. There is no reason to believe that extension pages are less affected by the potential issues that are faced by normal web pages.
Extension URLs can be loaded regardless of CSP (https://w3c.github.io/webappsec-csp/#extensions). So if extension A publishes a URL to an unsafe version of Angular.js, and extension B has a XSS vulnerability, then an attacker can misuse the unsafe Angular.js from extension A to bypass CSP in extension B, unless Angular.js blocks cross-origin extension resources (as I propose here).
These conditions are not too farfetched: I have reviewed hundreds of add-ons and XSS is not uncommon. And as you know, Angular.js has had its share in CSP-bypassing exploits. Together, there is some risk in allowing Angular.js to be loaded in a different extension.
If you want a concrete example of a CSP bypass with an extension resource, see: Synzvato/decentraleyes#130 (the CSP bypass was shown in a normal web page, but it would work equally well in an extension page).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah I get it, you're talking about extensions protecting themselves using CSP. That's a fair point, this code wasn't intended to cover this but we might as well.
- can you add a comment explaining that this covers two cases, loading Angular from an extension into a website, and across extensions?
- can you add a test that demonstrates this, so we don't break it in the future?
Also a nit: can you move the var scriptProtocol
and inline it into the switch below? We no longer need the separate variable here.
b20e3ab
to
db6d4a9
Compare
@mprobst Done. PTAL. I hope to have this patch included in 1.5.9 before Angular.js submissions are allowed in AMO. |
LGTM, thanks for the patch. |
I'll merge this tomorrow morning unless @IgorMinar and @matsko do so as part of their syncing today. |
@Rob--W this is failing a unit test on Travis. Can you take a look? |
@Rob--W We've already released Angular 1.5.9 with a previous version of the patch so this will only be a part of 1.5.10. |
@Rob--W For reference, this is what we released in 1.5.9: https://github.com/angular/angular.js/blob/v1.5.9/src/Angular.js#L1448-L1471. |
The tests are failing because those browsers have different ideas about what a non-standard origin means. Chrome (and I guess Safari as well) view "resource://something"'s origin as "resource://" (as if it was a file:-URL). I'll fix the tests.
I don't have the authority to say anything about that. I'm a volunteer editor at the Add-on review team, which is also how I learned about this bug. My feedback to the original PR and this PR here are actions independent of Mozilla. Old-style Firefox add-ons don't have a CSP by default, so whether the patch is in 1.5.9 or not does not affect the security of those add-ons (if these add-ons have a XSS issue, then they're already hosed). So I think that the patch does not need to block the whitelisting of 1.5.9. |
This shouldn't block the release. This is really just fixing a corner case of a corner case a bit more. To exploit the potential issue, you need an extension that has an XSS, and uses CSP in a way that's effective to block the problem, and need a user to have another extension installed that uses AngularJS, and then predict what extension that is. That's certainly a possibility, but really not a release blocker. |
extensionScheme = 'safari-extension'; | ||
} else if (/Trident/.test(userAgent)) { | ||
return; // IE does not support extensions with a standard protocol, so skip the test. | ||
} else { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we need all those if
s? We're not using real extension URLs here anyway but we're mocking the document so I think resource:
would be enough as it was before.
Especially that in real world on IE allowAutoBootstrap
will always return true as there is no document.currentScript
there.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The initial version of my patch used resource:-URLs, and that caused failures in IE (9, 10, 11), Safari and Chrome: https://travis-ci.org/angular/angular.js/jobs/179590522
An excerpt of what I said half an hour ago at #15428 (comment):
The tests are failing because those browsers have different ideas about what a non-standard origin means. Chrome (and I guess Safari as well) view "resource://something"'s origin as "resource://" (as if it was a file:-URL). I'll fix the tests.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see. In that case this test shouldn't be run in IE at all as it will return true
immediately in the very first document.currentScript
check as it doesn't support this API. Maybe add:
if (msie) return true;
at the beginning of the test you added?
As I said, we've already released 1.5.9 so we can't add anything to it. This will have to wait for 1.5.10. |
@Rob--W The tests were previously failing because in the document mock you defined |
Ok,1.5.10 it is. |
The very first version of my patch, with tests (and also the CI results I linked above) were using origin. Only after observing the test failure I switched to location.protocol/host to see whether it would change part of the test results, because I saw a comment on MDN about the invalidity of location.origin in early IE11 releases in Windows 10 - https://developer.mozilla.org/en-US/docs/Web/API/Window/location#Browser_compatibility The currently running tests in CI are using |
@Rob--W I see, thanks for the background. Normally we couldn't use |
@mgol Done. Hopefully "msie" never becomes true when Edge is added to the tests (or did I misinterpret the test results? Edge seems not among the browsers of the unit tests, even though there is test code that branches based on the presence of Edge). |
We haven't added Edge testing yet, see #14401. |
I'm thinking if there's another platform that doesn't support @Rob--W If we had to care about IE inside the |
LGTM but since the logic changed I'd like @mprobst to have one final look before we land it. |
Given that we are mocking out the document in order to setup the One last PTAL for you @mprobst. |
@petebacondarwin Yes. URL parsing differs, see #15428 (comment) |
@Rob--W - OK thanks for the clarification. LGTM |
LGTM |
I'll merge tonight or tomorrow |
Follow-up to #15427. There is no reason for allowing cross-origin automatic bootstrapping at URLs with an unknown scheme.
@mprobst @petebacondarwin