-
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1683,7 +1683,41 @@ describe('angular', function() { | |
dealoc(appElement); | ||
}); | ||
|
||
it('should bootstrap from an extension into an extension document for same-origin documents only', function() { | ||
if (msie) return; // IE does not support document.currentScript (nor extensions with protocol), so skip test. | ||
|
||
// Extension URLs are browser-specific, so we must choose a scheme that is supported by the browser to make | ||
// sure that the URL is properly parsed. | ||
var extensionScheme; | ||
var userAgent = window.navigator.userAgent; | ||
if (/Firefox\//.test(userAgent)) { | ||
extensionScheme = 'moz-extension'; | ||
} else if (/Edge\//.test(userAgent)) { | ||
extensionScheme = 'ms-browser-extension'; | ||
} else if (/Chrome\//.test(userAgent)) { | ||
extensionScheme = 'chrome-extension'; | ||
} else if (/Safari\//.test(userAgent)) { | ||
extensionScheme = 'safari-extension'; | ||
} else { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we need all those Especially that in real world on IE There was a problem hiding this comment. Choose a reason for hiding this commentThe 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):
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 if (msie) return true; at the beginning of the test you added? |
||
extensionScheme = 'browserext'; // Upcoming standard scheme. | ||
} | ||
|
||
var src = extensionScheme + '://something'; | ||
// Fake a minimal document object (the actual document.currentScript is readonly). | ||
var fakeDoc = { | ||
currentScript: { getAttribute: function() { return src; } }, | ||
location: {protocol: extensionScheme + ':', origin: extensionScheme + '://something'}, | ||
createElement: document.createElement.bind(document) | ||
}; | ||
expect(allowAutoBootstrap(fakeDoc)).toBe(true); | ||
|
||
src = extensionScheme + '://something-else'; | ||
expect(allowAutoBootstrap(fakeDoc)).toBe(false); | ||
}); | ||
|
||
it('should not bootstrap from an extension into a non-extension document', function() { | ||
if (msie) return; // IE does not support document.currentScript (nor extensions with protocol), so skip test. | ||
|
||
var src = 'resource://something'; | ||
// Fake a minimal document object (the actual document.currentScript is readonly). | ||
var fakeDoc = { | ||
|
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.
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.
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.
Also a nit: can you move the
var scriptProtocol
and inline it into the switch below? We no longer need the separate variable here.