diff --git a/changelog.md b/changelog.md index bdec60fd6..284f9759a 100644 --- a/changelog.md +++ b/changelog.md @@ -6,6 +6,9 @@ #### Drops support for Python 3.5 Opal now supports Python 3.6 - Python 3.8. +#### Adds the ng-sanitize +Opal now ships with the filter `$sanitize` that escapes dangerous tokens in html. + ### 0.20.0 (Major Release) diff --git a/opal/core/application.py b/opal/core/application.py index 5a3653b28..2bd4fdea2 100644 --- a/opal/core/application.py +++ b/opal/core/application.py @@ -21,7 +21,7 @@ class OpalApplication(object): "js/lib/bower_components/angular-route/angular-route.js", "js/lib/bower_components/angular-resource/angular-resource.js", "js/lib/bower_components/angular-cookies/angular-cookies.js", - + "js/lib/angular-sanitize.js", "js/lib/angular-ui-utils-0.1.0/ui-utils.js", "js/lib/ui-bootstrap-tpls-0.14.3.js", diff --git a/opal/static/js/lib/angular-sanitize.js b/opal/static/js/lib/angular-sanitize.js new file mode 100644 index 000000000..a283e43bd --- /dev/null +++ b/opal/static/js/lib/angular-sanitize.js @@ -0,0 +1,738 @@ +/** + * @license AngularJS v1.5.8 + * (c) 2010-2016 Google, Inc. http://angularjs.org + * License: MIT + */ +(function(window, angular) {'use strict'; + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Any commits to this file should be reviewed with security in mind. * + * Changes to this file can potentially create security vulnerabilities. * + * An approval from 2 Core members with history of modifying * + * this file is required. * + * * + * Does the change somehow allow for arbitrary javascript to be executed? * + * Or allows for someone to change the prototype of built-in objects? * + * Or gives undesired access to variables likes document or window? * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +var $sanitizeMinErr = angular.$$minErr('$sanitize'); +var bind; +var extend; +var forEach; +var isDefined; +var lowercase; +var noop; +var htmlParser; +var htmlSanitizeWriter; + +/** + * @ngdoc module + * @name ngSanitize + * @description + * + * # ngSanitize + * + * The `ngSanitize` module provides functionality to sanitize HTML. + * + * + *
+ * + * See {@link ngSanitize.$sanitize `$sanitize`} for usage. + */ + +/** + * @ngdoc service + * @name $sanitize + * @kind function + * + * @description + * Sanitizes an html string by stripping all potentially dangerous tokens. + * + * The input is sanitized by parsing the HTML into tokens. All safe tokens (from a whitelist) are + * then serialized back to properly escaped html string. This means that no unsafe input can make + * it into the returned string. + * + * The whitelist for URL sanitization of attribute values is configured using the functions + * `aHrefSanitizationWhitelist` and `imgSrcSanitizationWhitelist` of {@link ng.$compileProvider + * `$compileProvider`}. + * + * The input may also contain SVG markup if this is enabled via {@link $sanitizeProvider}. + * + * @param {string} html HTML input. + * @returns {string} Sanitized HTML. + * + * @example +Directive | +How | +Source | +Rendered | +
ng-bind-html | +Automatically uses $sanitize | +<div ng-bind-html="snippet"> |
+ + |
ng-bind-html | +Bypass $sanitize by explicitly trusting the dangerous value | +
+ <div ng-bind-html="deliberatelyTrustDangerousSnippet()"> +</div>+ |
+ + |
ng-bind | +Automatically escapes | +<div ng-bind="snippet"> |
+ + |
an html\nclick here\nsnippet
'); + }); + + it('should inline raw snippet if bound to a trusted value', function() { + expect(element(by.css('#bind-html-with-trust div')).getInnerHtml()). + toBe("an html\n" + + "click here\n" + + "snippet
"); + }); + + it('should escape snippet without any filter', function() { + expect(element(by.css('#bind-default div')).getInnerHtml()). + toBe("<p style=\"color:blue\">an html\n" + + "<em onmouseover=\"this.textContent='PWN3D!'\">click here</em>\n" + + "snippet</p>"); + }); + + it('should update', function() { + element(by.model('snippet')).clear(); + element(by.model('snippet')).sendKeys('new text'); + expect(element(by.css('#bind-html-with-sanitize div')).getInnerHtml()). + toBe('new text'); + expect(element(by.css('#bind-html-with-trust div')).getInnerHtml()).toBe( + 'new text'); + expect(element(by.css('#bind-default div')).getInnerHtml()).toBe( + "new <b onclick=\"alert(1)\">text</b>"); + }); +By enabling this setting without taking other precautions, you might expose your + * application to click-hijacking attacks. In these attacks, sanitized svg elements could be positioned + * outside of the containing element and be rendered over other elements on the page (e.g. a login + * link). Such behavior can then result in phishing incidents.
+ * + *To protect against these, explicitly setup `overflow: hidden` css rule for all potential svg + * tags within the sanitized content:
+ * + *
+ * .rootOfTheIncludedContent svg {
+ * overflow: hidden !important;
+ * }
+ *
+ * Filter | +Source | +Rendered | +
---|---|---|
linky filter | +
+ <div ng-bind-html="snippet | linky">+ |
+ + + | +
linky target | +
+ <div ng-bind-html="snippetWithSingleURL | linky:'_blank'">+ |
+ + + | +
linky custom attributes | +
+ <div ng-bind-html="snippetWithSingleURL | linky:'_self':{rel: 'nofollow'}">+ |
+ + + | +
no filter | +<div ng-bind="snippet"> |
+ + |