/
githubmirror
/
angular.js
Обзор
Документация
Войти
/
githubmirror
/
angular.js
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
src/ng/directive/ngCsp.js
210 строк
8 KB
Martin Staffa
docs(*): add / correct `@`-tags; fix headlines; add info
11 окт 2017, 15:36
11 окт 2017, 15:36
2c8bfd8
Код
Авторство
О чём код?
'use strict'; /** * @ngdoc directive * @name ngCsp * * @restrict A * @element ANY * @description * * AngularJS has some features that can conflict with certain restrictions that are applied when using * [CSP (Content Security Policy)](https://developer.mozilla.org/en/Security/CSP) rules. * * If you intend to implement CSP with these rules then you must tell AngularJS not to use these * features. * * This is necessary when developing things like Google Chrome Extensions or Universal Windows Apps. * * * The following default rules in CSP affect AngularJS: * * * The use of `eval()`, `Function(string)` and similar functions to dynamically create and execute * code from strings is forbidden. AngularJS makes use of this in the {@link $parse} service to * provide a 30% increase in the speed of evaluating AngularJS expressions. (This CSP rule can be * disabled with the CSP keyword `unsafe-eval`, but it is generally not recommended as it would * weaken the protections offered by CSP.) * * * The use of inline resources, such as inline `<script>` and `<style>` elements, are forbidden. * This prevents apps from injecting custom styles directly into the document. AngularJS makes use of * this to include some CSS rules (e.g. {@link ngCloak} and {@link ngHide}). To make these * directives work when a CSP rule is blocking inline styles, you must link to the `angular-csp.css` * in your HTML manually. (This CSP rule can be disabled with the CSP keyword `unsafe-inline`, but * it is generally not recommended as it would weaken the protections offered by CSP.) * * If you do not provide `ngCsp` then AngularJS tries to autodetect if CSP is blocking dynamic code * creation from strings (e.g., `unsafe-eval` not specified in CSP header) and automatically * deactivates this feature in the {@link $parse} service. This autodetection, however, triggers a * CSP error to be logged in the console: * * ``` * Refused to evaluate a string as JavaScript because 'unsafe-eval' is not an allowed source of * script in the following Content Security Policy directive: "default-src 'self'". Note that * 'script-src' was not explicitly set, so 'default-src' is used as a fallback. * ``` * * This error is harmless but annoying. To prevent the error from showing up, put the `ngCsp` * directive on an element of the HTML document that appears before the `<script>` tag that loads * the `angular.js` file. * * *Note: This directive is only available in the `ng-csp` and `data-ng-csp` attribute form.* * * You can specify which of the CSP related AngularJS features should be deactivated by providing * a value for the `ng-csp` attribute. The options are as follows: * * * no-inline-style: this stops AngularJS from injecting CSS styles into the DOM * * * no-unsafe-eval: this stops AngularJS from optimizing $parse with unsafe eval of strings * * You can use these values in the following combinations: * * * * No declaration means that AngularJS will assume that you can do inline styles, but it will do * a runtime check for unsafe-eval. E.g. `<body>`. This is backwardly compatible with previous * versions of AngularJS. * * * A simple `ng-csp` (or `data-ng-csp`) attribute will tell AngularJS to deactivate both inline * styles and unsafe eval. E.g. `<body ng-csp>`. This is backwardly compatible with previous * versions of AngularJS. * * * Specifying only `no-unsafe-eval` tells AngularJS that we must not use eval, but that we can * inject inline styles. E.g. `<body ng-csp="no-unsafe-eval">`. * * * Specifying only `no-inline-style` tells AngularJS that we must not inject styles, but that we can * run eval - no automatic check for unsafe eval will occur. E.g. `<body ng-csp="no-inline-style">` * * * Specifying both `no-unsafe-eval` and `no-inline-style` tells AngularJS that we must not inject * styles nor use eval, which is the same as an empty: ng-csp. * E.g.`<body ng-csp="no-inline-style;no-unsafe-eval">` * * @example * * This example shows how to apply the `ngCsp` directive to the `html` tag. ```html <!doctype html> <html ng-app ng-csp> ... ... </html> ``` <!-- Note: the `.csp` suffix in the example name triggers CSP mode in our http server! --> <example name="example.csp" module="cspExample" ng-csp="true"> <file name="index.html"> <div ng-controller="MainController as ctrl"> <div> <button ng-click="ctrl.inc()" id="inc">Increment</button> <span id="counter"> {{ctrl.counter}} </span> </div> <div> <button ng-click="ctrl.evil()" id="evil">Evil</button> <span id="evilError"> {{ctrl.evilError}} </span> </div> </div> </file> <file name="script.js"> angular.module('cspExample', []) .controller('MainController', function MainController() { this.counter = 0; this.inc = function() { this.counter++; }; this.evil = function() { try { eval('1+2'); // eslint-disable-line no-eval } catch (e) { this.evilError = e.message; } }; }); </file> <file name="protractor.js" type="protractor"> var util, webdriver; var incBtn = element(by.id('inc')); var counter = element(by.id('counter')); var evilBtn = element(by.id('evil')); var evilError = element(by.id('evilError')); function getAndClearSevereErrors() { return browser.manage().logs().get('browser').then(function(browserLog) { return browserLog.filter(function(logEntry) { return logEntry.level.value > webdriver.logging.Level.WARNING.value; }); }); } function clearErrors() { getAndClearSevereErrors(); } function expectNoErrors() { getAndClearSevereErrors().then(function(filteredLog) { expect(filteredLog.length).toEqual(0); if (filteredLog.length) { console.log('browser console errors: ' + util.inspect(filteredLog)); } }); } function expectError(regex) { getAndClearSevereErrors().then(function(filteredLog) { var found = false; filteredLog.forEach(function(log) { if (log.message.match(regex)) { found = true; } }); if (!found) { throw new Error('expected an error that matches ' + regex); } }); } beforeEach(function() { util = require('util'); webdriver = require('selenium-webdriver'); }); // For now, we only test on Chrome, // as Safari does not load the page with Protractor's injected scripts, // and Firefox webdriver always disables content security policy (#6358) if (browser.params.browser !== 'chrome') { return; } it('should not report errors when the page is loaded', function() { // clear errors so we are not dependent on previous tests clearErrors(); // Need to reload the page as the page is already loaded when // we come here browser.driver.getCurrentUrl().then(function(url) { browser.get(url); }); expectNoErrors(); }); it('should evaluate expressions', function() { expect(counter.getText()).toEqual('0'); incBtn.click(); expect(counter.getText()).toEqual('1'); expectNoErrors(); }); it('should throw and report an error when using "eval"', function() { evilBtn.click(); expect(evilError.getText()).toMatch(/Content Security Policy/); expectError(/Content Security Policy/); }); </file> </example> */ // `ngCsp` is not implemented as a proper directive any more, because we need it be processed while // we bootstrap the app (before `$parse` is instantiated). For this reason, we just have the `csp()` // fn that looks for the `ng-csp` attribute anywhere in the current doc.