Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.

Commit bdeb339

Browse files
Rob--Wpetebacondarwin
authored andcommitted
feat(security): do not bootstrap from unknown schemes with a different origin
1 parent 7f45b5f commit bdeb339

File tree

2 files changed

+40
-4
lines changed

2 files changed

+40
-4
lines changed

src/Angular.js

+6-4
Original file line numberDiff line numberDiff line change
@@ -1452,12 +1452,14 @@ function allowAutoBootstrap(document) {
14521452
var src = document.currentScript.getAttribute('src');
14531453
var link = document.createElement('a');
14541454
link.href = src;
1455-
var scriptProtocol = link.protocol;
1456-
var docLoadProtocol = document.location.protocol;
1457-
if (docLoadProtocol === scriptProtocol) {
1455+
if (document.location.origin === link.origin) {
1456+
// Same-origin resources are always allowed, even for non-whitelisted schemes.
14581457
return true;
14591458
}
1460-
switch (scriptProtocol) {
1459+
// Disabled bootstrapping unless angular.js was loaded from a known scheme used on the web.
1460+
// This is to prevent angular.js bundled with browser extensions from being used to bypass the
1461+
// content security policy in web pages and other browser extensions.
1462+
switch (link.protocol) {
14611463
case 'http:':
14621464
case 'https:':
14631465
case 'ftp:':

test/AngularSpec.js

+34
Original file line numberDiff line numberDiff line change
@@ -1697,7 +1697,41 @@ describe('angular', function() {
16971697
dealoc(appElement);
16981698
});
16991699

1700+
it('should bootstrap from an extension into an extension document for same-origin documents only', function() {
1701+
if (msie) return; // IE does not support document.currentScript (nor extensions with protocol), so skip test.
1702+
1703+
// Extension URLs are browser-specific, so we must choose a scheme that is supported by the browser to make
1704+
// sure that the URL is properly parsed.
1705+
var extensionScheme;
1706+
var userAgent = window.navigator.userAgent;
1707+
if (/Firefox\//.test(userAgent)) {
1708+
extensionScheme = 'moz-extension';
1709+
} else if (/Edge\//.test(userAgent)) {
1710+
extensionScheme = 'ms-browser-extension';
1711+
} else if (/Chrome\//.test(userAgent)) {
1712+
extensionScheme = 'chrome-extension';
1713+
} else if (/Safari\//.test(userAgent)) {
1714+
extensionScheme = 'safari-extension';
1715+
} else {
1716+
extensionScheme = 'browserext'; // Upcoming standard scheme.
1717+
}
1718+
1719+
var src = extensionScheme + '://something';
1720+
// Fake a minimal document object (the actual document.currentScript is readonly).
1721+
var fakeDoc = {
1722+
currentScript: { getAttribute: function() { return src; } },
1723+
location: {protocol: extensionScheme + ':', origin: extensionScheme + '://something'},
1724+
createElement: document.createElement.bind(document)
1725+
};
1726+
expect(allowAutoBootstrap(fakeDoc)).toBe(true);
1727+
1728+
src = extensionScheme + '://something-else';
1729+
expect(allowAutoBootstrap(fakeDoc)).toBe(false);
1730+
});
1731+
17001732
it('should not bootstrap from an extension into a non-extension document', function() {
1733+
if (msie) return; // IE does not support document.currentScript (nor extensions with protocol), so skip test.
1734+
17011735
var src = 'resource://something';
17021736
// Fake a minimal document object (the actual document.currentScript is readonly).
17031737
var fakeDoc = {

0 commit comments

Comments
 (0)