From 9f24c2d458b32e8d632740a100e1b428aaf534ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Go=C5=82e=CC=A8biowski-Owczarek?= Date: Tue, 19 May 2020 14:25:02 +0200 Subject: [PATCH] fix(jqLite): prevent possible XSS due to regex-based HTML replacement --- src/.eslintrc.json | 1 + src/Angular.js | 17 +++++++++++ src/AngularPublic.js | 1 + src/jqLite.js | 27 +++++++++++++---- test/jqLiteSpec.js | 69 ++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 110 insertions(+), 5 deletions(-) diff --git a/src/.eslintrc.json b/src/.eslintrc.json index dca5e4b006ef..36b653a76649 100644 --- a/src/.eslintrc.json +++ b/src/.eslintrc.json @@ -100,6 +100,7 @@ "VALIDITY_STATE_PROPERTY": false, "reloadWithDebugInfo": false, "stringify": false, + "UNSAFE_restoreLegacyJqLiteXHTMLReplacement": false, "NODE_TYPE_ELEMENT": false, "NODE_TYPE_ATTRIBUTE": false, diff --git a/src/Angular.js b/src/Angular.js index 8ce4f46347d3..e98c05cce352 100644 --- a/src/Angular.js +++ b/src/Angular.js @@ -93,6 +93,7 @@ hasOwnProperty, createMap, stringify, + UNSAFE_restoreLegacyJqLiteXHTMLReplacement, NODE_TYPE_ELEMENT, NODE_TYPE_ATTRIBUTE, @@ -1949,6 +1950,22 @@ function bindJQuery() { bindJQueryFired = true; } +/** + * @ngdoc function + * @name angular.UNSAFE_restoreLegacyJqLiteXHTMLReplacement + * @module ng + * @kind function + * + * @description + * Restores the pre-1.8 behavior of jqLite that turns XHTML-like strings like + * `
` to `
` instead of `
`. + * The new behavior is a security fix so if you use this method, please try to adjust + * to the change & remove the call as soon as possible. + */ +function UNSAFE_restoreLegacyJqLiteXHTMLReplacement() { + JQLite.legacyXHTMLReplacement = true; +} + /** * throw error if the argument is falsy. */ diff --git a/src/AngularPublic.js b/src/AngularPublic.js index 760fa835bd48..7f89362fed9b 100644 --- a/src/AngularPublic.js +++ b/src/AngularPublic.js @@ -156,6 +156,7 @@ function publishExternalAPI(angular) { 'callbacks': {$$counter: 0}, 'getTestability': getTestability, 'reloadWithDebugInfo': reloadWithDebugInfo, + 'UNSAFE_restoreLegacyJqLiteXHTMLReplacement': UNSAFE_restoreLegacyJqLiteXHTMLReplacement, '$$minErr': minErr, '$$csp': csp, '$$encodeUriSegment': encodeUriSegment, diff --git a/src/jqLite.js b/src/jqLite.js index 9884730d5e13..91b0b3dd9999 100644 --- a/src/jqLite.js +++ b/src/jqLite.js @@ -90,6 +90,16 @@ * - [`val()`](http://api.jquery.com/val/) * - [`wrap()`](http://api.jquery.com/wrap/) * + * jqLite also provides a method restoring pre-1.8 insecure treatment of XHTML-like tags + * that makes input like `
` turned to `
` instead of + * `
` like version 1.8 & newer do: + * ```js + * angular.UNSAFE_restoreLegacyJqLiteXHTMLReplacement(); + * ``` + * Note that this only patches jqLite. If you use jQuery 3.5.0 or newer, please read + * [jQuery 3.5 upgrade guide](https://jquery.com/upgrade-guide/3.5/) for more details + * about the workarounds. + * * ## jQuery/jqLite Extras * AngularJS also provides the following additional methods and events to both jQuery and jqLite: * @@ -170,8 +180,6 @@ var TAG_NAME_REGEXP = /<([\w:-]+)/; var XHTML_TAG_REGEXP = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:-]+)[^>]*)\/>/gi; var wrapMap = { - 'option': [1, ''], - 'thead': [1, '', '
'], 'col': [2, '', '
'], 'tr': [2, '', '
'], @@ -179,10 +187,16 @@ var wrapMap = { '_default': [0, '', ''] }; -wrapMap.optgroup = wrapMap.option; wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; wrapMap.th = wrapMap.td; +// Support: IE <=9 only +// IE <=9 replaces