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

fix(security): do not auto-bootstrap when loaded from an extension. #15346

Closed
wants to merge 2 commits into from

Conversation

mprobst
Copy link
Contributor

@mprobst mprobst commented Nov 1, 2016

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.

@mprobst
Copy link
Contributor Author

mprobst commented Nov 1, 2016

/CC @rjamet @koto

@koto
Copy link
Contributor

koto commented Nov 1, 2016

LGTM

@@ -1602,6 +1622,11 @@ function angularInit(element, bootstrap) {
}
});
if (appElement) {
if (!isAutoBootstrapAllowed) {
console.error('Angular: disabling automatic bootstrap. <script> protocol indicates an ' +
'extension, document.href does not match.');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

document.location.href?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

@@ -1602,6 +1622,11 @@ function angularInit(element, bootstrap) {
}
});
if (appElement) {
if (!isAutoBootstrapAllowed) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This check could be moved at the top (unless we expect anyone to load angular via resource:/chrome-extension: in a non-extention page and bootstrap it manually.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't do this intentionally - otherwise you'll get an error message even if you intend to manually bootstrap by calling angular.bootstrap. Which I guess is a legit use case, if somebody does inject Angular in the page but also controls it to call angular.bootstrap (not a security issue because they can already execute JS in the page in that case).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I thought it might be intentional. I don't expect anyone to be loading angular over resource: on non-extension pages, but you never know 😃

Hm...so, if it is a supported usecase (loading angular.js over resource: on non-extension pages), isn't this chage breaking? In that case, we should have a breaking change notice.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Loading angular.js over resource: from a non-extension page is not supported, and not a use case (that's almost certainly a security exploit, which is why this change is blocking it). I don't think we need to document that.

However, for the rare case where a web page really actually wants to load via resource://, it still can, by embedding an appropriate angular.bootstrap call. If you can embed JS into the hosting page, you can do evil things anyway, so that's not a security boundary. This behaviour is easy to implement, doesn't do harm or lower security (it should, at least...), and overall seems fine.

A secondary effect is that the console spam only triggers if the user actually has an ng-app in their app, so it's more precise, which I think is a good thing.

So I don't think we need to document anything. Most users will never notice this.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So I don't think we need to document anything. Most users will never notice this.

This should be documented, assuming that most users won't notice it means that when someone does notice it, there is no help available on how to go about making it work.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mmccallum - feel free to send in a PR.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mmccallum FWIW, when auto bootstrap gets disabled, Angular prints out a pretty clear message in the console.

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.
@mprobst mprobst force-pushed the protocols-resources-bootstrap branch from b5e6da4 to ca88480 Compare November 1, 2016 20:49
@@ -97,6 +97,9 @@
NODE_TYPE_DOCUMENT,
NODE_TYPE_DOCUMENT_FRAGMENT
*/
/* global
console
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can avoid this by accessing console off window (not sure what is better).

@@ -1602,6 +1622,11 @@ function angularInit(element, bootstrap) {
}
});
if (appElement) {
if (!isAutoBootstrapAllowed) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I thought it might be intentional. I don't expect anyone to be loading angular over resource: on non-extension pages, but you never know 😃

Hm...so, if it is a supported usecase (loading angular.js over resource: on non-extension pages), isn't this chage breaking? In that case, we should have a breaking change notice.

var docLoadProtocol = document.location.protocol;
if ((scriptProtocol === 'resource:' ||
scriptProtocol === 'chrome-extension:') &&
docLoadProtocol !== scriptProtocol) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So we do allow auto bootstrap if the protocol of the document matches that of the script?
Why is that?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because that's the intended use case - an extension that has a page (within the extension) that loads angular, and contains ng-app. We could disable that, but if we support auto bootstrap, I think we should support it within extensions, shouldn't we?

@@ -1602,6 +1622,11 @@ function angularInit(element, bootstrap) {
}
});
if (appElement) {
if (!isAutoBootstrapAllowed) {
window.console.error('Angular: disabling automatic bootstrap. <script> protocol indicates ' +
'an extension, document.location.href does not match.');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel that this message could be clearer or that it should link to a webpage/issue that explains what is happening?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you have a suggestion? This should really only happen when somebody tries to exploit the security hole, so I'm not too worried about usability here. I don't think we need docs or a website.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But it shouldn't block merging this.

petebacondarwin pushed a commit that referenced this pull request Nov 2, 2016
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.

Closes #15346
petebacondarwin pushed a commit to petebacondarwin/angular.js that referenced this pull request Nov 21, 2016
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.

Closes angular#15346
petebacondarwin pushed a commit to petebacondarwin/angular.js that referenced this pull request Nov 21, 2016
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.

Closes angular#15346
ellimist pushed a commit to ellimist/angular.js that referenced this pull request Mar 15, 2017
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.

Closes angular#15346
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants