From ca884808394fbe4a590297c47d87baee5cb8615d Mon Sep 17 00:00:00 2001 From: Martin Probst Date: Thu, 20 Oct 2016 19:56:48 -0700 Subject: [PATCH] fix(security): do not auto-bootstrap when loaded from an extension. Extension URIs (`resource://...`) bypass Content-Security-Policy in Chrome and Firefox and can always be loaded. Now if a site already has a XSS bug, and uses CSP to protect itself, but the user has an extension installed that uses Angular, an attacked can load Angular from the extension, and Angular's auto-bootstrapping can be used to bypass the victim site's CSP protection. Notes: - `isAutoBootstrapAllowed` must be initialized on load, so that `currentScript` is set correctly. - The tests are a bit indirect as reproducing the actual scenario is too complicated to reproduce (requires signing an extension etc). I have confirmed this to be working manually. --- src/Angular.js | 28 ++++++++++++++++++++++++++++ test/.eslintrc.json | 2 ++ test/AngularSpec.js | 21 +++++++++++++++++++++ 3 files changed, 51 insertions(+) diff --git a/src/Angular.js b/src/Angular.js index dced06cc28b2..7a605cfc49be 100644 --- a/src/Angular.js +++ b/src/Angular.js @@ -97,6 +97,9 @@ NODE_TYPE_DOCUMENT, NODE_TYPE_DOCUMENT_FRAGMENT */ +/* global + console +*/ //////////////////////////////////// @@ -1444,6 +1447,26 @@ function getNgAttribute(element, ngAttr) { return null; } +function allowAutoBootstrap(document) { + if (!document.currentScript) { + return true; + } + var src = document.currentScript.getAttribute('src'); + var link = document.createElement('a'); + link.href = src; + var scriptProtocol = link.protocol; + var docLoadProtocol = document.location.protocol; + if ((scriptProtocol === 'resource:' || + scriptProtocol === 'chrome-extension:') && + docLoadProtocol !== scriptProtocol) { + return false; + } + return true; +} + +// Cached as it has to run during loading so that document.currentScript is available. +var isAutoBootstrapAllowed = allowAutoBootstrap(window.document); + /** * @ngdoc directive * @name ngApp @@ -1602,6 +1625,11 @@ function angularInit(element, bootstrap) { } }); if (appElement) { + if (!isAutoBootstrapAllowed) { + console.error('Angular: disabling automatic bootstrap.