From 463aa3445675dec39cb16cfab9fdc56bb0508aa5 Mon Sep 17 00:00:00 2001 From: xjm Date: Wed, 20 May 2020 03:22:16 -0500 Subject: [PATCH 1/2] SA-CORE-2020-002 by mcdruid, dungahk, justafish, cilefen, xjm, larowlan, effulgentsia, bnjmnm, lauriii, zrpnr, samuel.mortenson --- .../jquery/jquery-htmlprefilter-3.5.0.js | 104 ++++++++++++++++++ core/core.libraries.yml | 6 +- core/modules/system/system.post_update.php | 7 ++ 3 files changed, 115 insertions(+), 2 deletions(-) create mode 100644 core/assets/vendor/jquery/jquery-htmlprefilter-3.5.0.js diff --git a/core/assets/vendor/jquery/jquery-htmlprefilter-3.5.0.js b/core/assets/vendor/jquery/jquery-htmlprefilter-3.5.0.js new file mode 100644 index 00000000000..cf26ecca9c1 --- /dev/null +++ b/core/assets/vendor/jquery/jquery-htmlprefilter-3.5.0.js @@ -0,0 +1,104 @@ +/** + * For jQuery versions less than 3.5.0, this replaces the jQuery.htmlPrefilter() + * function with one that fixes these security vulnerabilities while also + * retaining the pre-3.5.0 behavior where it's safe to do so. + * - https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2020-11022 + * - https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2020-11023 + */ + +(function (jQuery) { + + // No backport is needed if we're already on jQuery 3.5 or higher. + var versionParts = jQuery.fn.jquery.split('.'); + var majorVersion = parseInt(versionParts[0]); + var minorVersion = parseInt(versionParts[1]); + if ( (majorVersion > 3) || (majorVersion === 3 && minorVersion >= 5) ) { + return; + } + + // Prior to jQuery 3.5, jQuery converted XHTML-style self-closing tags to + // their XML equivalent: e.g., "
" to "
". This is + // problematic for several reasons, including that it's vulnerable to XSS + // attacks. However, since this was jQuery's behavior for many years, many + // Drupal modules and jQuery plugins may be relying on it. Therefore, we + // preserve that behavior, but for a limited set of tags only, that we believe + // to not be vulnerable. This is the set of HTML tags that satisfy all of the + // following conditions: + // - In DOMPurify's list of HTML tags. If an HTML tag isn't safe enough to + // appear in that list, then we don't want to mess with it here either. + // @see https://github.com/cure53/DOMPurify/blob/2.0.11/dist/purify.js#L128 + // - A normal element (not a void, template, text, or foreign element). + // @see https://html.spec.whatwg.org/multipage/syntax.html#elements-2 + // - An element that is still defined by the current HTML specification + // (not a deprecated element), because we do not want to rely on how + // browsers parse deprecated elements. + // @see https://developer.mozilla.org/en-US/docs/Web/HTML/Element + // - Not 'html', 'head', or 'body', because this pseudo-XHTML expansion is + // designed for fragments, not entire documents. + // - Not 'colgroup', because due to an idiosyncrasy of jQuery's original + // regular expression, it didn't match on colgroup, and we don't want to + // introduce a behavior change for that. + var selfClosingTagsToReplace = [ + 'a', 'abbr', 'address', 'article', 'aside', 'audio', 'b', 'bdi', 'bdo', + 'blockquote', 'button', 'canvas', 'caption', 'cite', 'code', 'data', + 'datalist', 'dd', 'del', 'details', 'dfn', 'div', 'dl', 'dt', 'em', + 'fieldset', 'figcaption', 'figure', 'footer', 'form', 'h1', 'h2', 'h3', + 'h4', 'h5', 'h6', 'header', 'hgroup', 'i', 'ins', 'kbd', 'label', 'legend', + 'li', 'main', 'map', 'mark', 'menu', 'meter', 'nav', 'ol', 'optgroup', + 'option', 'output', 'p', 'picture', 'pre', 'progress', 'q', 'rp', 'rt', + 'ruby', 's', 'samp', 'section', 'select', 'small', 'source', 'span', + 'strong', 'sub', 'summary', 'sup', 'table', 'tbody', 'td', 'tfoot', 'th', + 'thead', 'time', 'tr', 'u', 'ul', 'var', 'video' + ]; + + // Define regular expressions for and . Doing this as + // two expressions makes it easier to target without also targeting + // every tag that starts with "a". + var xhtmlRegExpGroup = '(' + selfClosingTagsToReplace.join('|') + ')'; + var whitespace = '[\\x20\\t\\r\\n\\f]'; + var rxhtmlTagWithoutSpaceOrAttributes = new RegExp('<' + xhtmlRegExpGroup + '\\/>', 'gi'); + var rxhtmlTagWithSpaceAndMaybeAttributes = new RegExp('<' + xhtmlRegExpGroup + '(' + whitespace + '[^>]*)\\/>', 'gi'); + + // jQuery 3.5 also fixed a vulnerability for when appears within + // an , but it did that in local code that we can't + // backport directly. Instead, we filter such cases out. To do so, we need to + // determine when jQuery would otherwise invoke the vulnerable code, which it + // uses this regular expression to determine. The regular expression changed + // for version 3.4.0. + // @see https://github.com/jquery/jquery/blob/3.2.1/dist/jquery.js#L4695 + // @see https://github.com/jquery/jquery/blob/3.4.0/dist/jquery.js#L4712 + var rtagName; + if (minorVersion < 4) { + rtagName = /<([a-z][^\/\0>\x20\t\r\n\f]+)/i; + } + else { + rtagName = /<([a-z][^\/\0>\x20\t\r\n\f]*)/i; + } + + jQuery.extend({ + htmlPrefilter: function (html) { + // This is how jQuery determines the first tag in the HTML. + // @see https://github.com/jquery/jquery/blob/3.2.1/dist/jquery.js#L4794 + var tag = ( rtagName.exec( html ) || [ "", "" ] )[ 1 ].toLowerCase(); + + // It is not valid HTML for to have