-
Notifications
You must be signed in to change notification settings - Fork 233
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Update to Drupal 7.70. For more information, see https://www.drupal.o…
- Loading branch information
1 parent
8f5b5c8
commit b3cede3
Showing
6 changed files
with
271 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,251 @@ | ||
/** | ||
* 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 | ||
* | ||
* Additionally, for jQuery versions that do not have a jQuery.htmlPrefilter() | ||
* function (1.x prior to 1.12 and 2.x prior to 2.2), this adds it, and | ||
* extends the functions that need to call it to do so. | ||
* | ||
* Drupal core's jQuery version is 1.4.4, but jQuery Update can provide a | ||
* different version, so this covers all versions between 1.4.4 and 3.4.1. | ||
* The GitHub links in the code comments below link to jQuery 1.5 code, because | ||
* 1.4.4 isn't on GitHub, but the referenced code didn't change from 1.4.4 to | ||
* 1.5. | ||
*/ | ||
|
||
(function (jQuery) { | ||
|
||
// Parts of this backport differ by jQuery version. | ||
var versionParts = jQuery.fn.jquery.split('.'); | ||
var majorVersion = parseInt(versionParts[0]); | ||
var minorVersion = parseInt(versionParts[1]); | ||
|
||
// No backport is needed if we're already on jQuery 3.5 or higher. | ||
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., "<div />" to "<div></div>". 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 <TAG/> and <TAG ATTRIBUTES/>. Doing this as | ||
// two expressions makes it easier to target <a/> 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 </select> appears within | ||
// an <option> or <optgroup>, 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.0.0 and changed again for 3.4.0. | ||
// @see https://github.com/jquery/jquery/blob/1.5/jquery.js#L4958 | ||
// @see https://github.com/jquery/jquery/blob/3.0.0/dist/jquery.js#L4584 | ||
// @see https://github.com/jquery/jquery/blob/3.4.0/dist/jquery.js#L4712 | ||
var rtagName; | ||
if (majorVersion < 3) { | ||
rtagName = /<([\w:]+)/; | ||
} | ||
else if (minorVersion < 4) { | ||
rtagName = /<([a-z][^\/\0>\x20\t\r\n\f]+)/i; | ||
} | ||
else { | ||
rtagName = /<([a-z][^\/\0>\x20\t\r\n\f]*)/i; | ||
} | ||
|
||
// The regular expression that jQuery uses to determine which self-closing | ||
// tags to expand to open and close tags. This is vulnerable, because it | ||
// matches all tag names except the few excluded ones. We only use this | ||
// expression for determining vulnerability. The expression changed for | ||
// version 3, but we only need to check for vulnerability in versions 1 and 2, | ||
// so we use the expression from those versions. | ||
// @see https://github.com/jquery/jquery/blob/1.5/jquery.js#L4957 | ||
var rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi; | ||
|
||
jQuery.extend({ | ||
htmlPrefilter: function (html) { | ||
// This is how jQuery determines the first tag in the HTML. | ||
// @see https://github.com/jquery/jquery/blob/1.5/jquery.js#L5521 | ||
var tag = ( rtagName.exec( html ) || [ "", "" ] )[ 1 ].toLowerCase(); | ||
|
||
// It is not valid HTML for <option> or <optgroup> to have <select> as | ||
// either a descendant or sibling, and attempts to inject one can cause | ||
// XSS on jQuery versions before 3.5. Since this is invalid HTML and a | ||
// possible XSS attack, reject the entire string. | ||
// @see https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2020-11023 | ||
if ((tag === 'option' || tag === 'optgroup') && html.match(/<\/?select/i)) { | ||
html = ''; | ||
} | ||
|
||
// Retain jQuery's prior to 3.5 conversion of pseudo-XHTML, but for only | ||
// the tags in the `selfClosingTagsToReplace` list defined above. | ||
// @see https://github.com/jquery/jquery/blob/1.5/jquery.js#L5518 | ||
// @see https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2020-11022 | ||
html = html.replace(rxhtmlTagWithoutSpaceOrAttributes, "<$1></$1>"); | ||
html = html.replace(rxhtmlTagWithSpaceAndMaybeAttributes, "<$1$2></$1>"); | ||
|
||
// Prior to jQuery 1.12 and 2.2, this function gets called (via code later | ||
// in this file) in addition to, rather than instead of, the unsafe | ||
// expansion of self-closing tags (including ones not in the list above). | ||
// We can't prevent that unsafe expansion from running, so instead we | ||
// check to make sure that it doesn't affect the DOM returned by the | ||
// browser's parsing logic. If it does affect it, then it's vulnerable to | ||
// XSS, so we reject the entire string. | ||
if ( (majorVersion === 1 && minorVersion < 12) || (majorVersion === 2 && minorVersion < 2) ) { | ||
var htmlRisky = html.replace(rxhtmlTag, "<$1></$2>"); | ||
if (htmlRisky !== html) { | ||
// Even though htmlRisky and html are different strings, they might | ||
// represent the same HTML structure once parsed, in which case, | ||
// htmlRisky is actually safe. We can ask the browser to parse both | ||
// to find out, but the browser can't parse table fragments (e.g., a | ||
// root-level "<td>"), so we need to wrap them. We just need this | ||
// technique to work on all supported browsers; we don't need to | ||
// copy from the specific jQuery version we're using. | ||
// @see https://github.com/jquery/jquery/blob/3.5.1/dist/jquery.js#L4939 | ||
var wrapMap = { | ||
thead: [ 1, "<table>", "</table>" ], | ||
col: [ 2, "<table><colgroup>", "</colgroup></table>" ], | ||
tr: [ 2, "<table><tbody>", "</tbody></table>" ], | ||
td: [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ], | ||
}; | ||
wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; | ||
wrapMap.th = wrapMap.td; | ||
|
||
// Function to wrap HTML into something that a browser can parse. | ||
// @see https://github.com/jquery/jquery/blob/3.5.1/dist/jquery.js#L5032 | ||
var getWrappedHtml = function (html) { | ||
var wrap = wrapMap[tag]; | ||
if (wrap) { | ||
html = wrap[1] + html + wrap[2]; | ||
} | ||
return html; | ||
}; | ||
|
||
// Function to return canonical HTML after parsing it. This parses | ||
// only; it doesn't execute scripts. | ||
// @see https://github.com/jquery/jquery-migrate/blob/3.3.0/src/jquery/manipulation.js#L5 | ||
var getParsedHtml = function (html) { | ||
var doc = window.document.implementation.createHTMLDocument( "" ); | ||
doc.body.innerHTML = html; | ||
return doc.body ? doc.body.innerHTML : ''; | ||
}; | ||
|
||
// If the browser couldn't parse either one successfully, or if | ||
// htmlRisky parses differently than html, then html is vulnerable, | ||
// so reject it. | ||
var htmlParsed = getParsedHtml(getWrappedHtml(html)); | ||
var htmlRiskyParsed = getParsedHtml(getWrappedHtml(htmlRisky)); | ||
if (htmlRiskyParsed === '' || htmlParsed === '' || (htmlRiskyParsed !== htmlParsed)) { | ||
html = ''; | ||
} | ||
} | ||
} | ||
|
||
return html; | ||
} | ||
}); | ||
|
||
// Prior to jQuery 1.12 and 2.2, jQuery.clean(), jQuery.buildFragment(), and | ||
// jQuery.fn.html() did not call jQuery.htmlPrefilter(), so we add that. | ||
if ( (majorVersion === 1 && minorVersion < 12) || (majorVersion === 2 && minorVersion < 2) ) { | ||
// Filter the HTML coming into jQuery.fn.html(). | ||
var fnOriginalHtml = jQuery.fn.html; | ||
jQuery.fn.extend({ | ||
// @see https://github.com/jquery/jquery/blob/1.5/jquery.js#L5147 | ||
html: function (value) { | ||
if (typeof value === "string") { | ||
value = jQuery.htmlPrefilter(value); | ||
} | ||
// .html() can be called as a setter (with an argument) or as a getter | ||
// (without an argument), so invoke fnOriginalHtml() the same way that | ||
// we were invoked. | ||
return fnOriginalHtml.apply(this, arguments.length ? [value] : []); | ||
} | ||
}); | ||
|
||
// The regular expression that jQuery uses to determine if a string is HTML. | ||
// Used by both clean() and buildFragment(). | ||
// @see https://github.com/jquery/jquery/blob/1.5/jquery.js#L4960 | ||
var rhtml = /<|&#?\w+;/; | ||
|
||
// Filter HTML coming into: | ||
// - jQuery.clean() for versions prior to 1.9. | ||
// - jQuery.buildFragment() for 1.9 and above. | ||
// | ||
// The looping constructs in the two functions might be essentially | ||
// identical, but they're each expressed here in the way that most closely | ||
// matches their original expression in jQuery, so that we filter all of | ||
// the items and only the items that jQuery will treat as HTML strings. | ||
if (majorVersion === 1 && minorVersion < 9) { | ||
var originalClean = jQuery.clean; | ||
jQuery.extend({ | ||
// @see https://github.com/jquery/jquery/blob/1.5/jquery.js#L5493 | ||
'clean': function (elems, context, fragment, scripts) { | ||
for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) { | ||
if ( typeof elem === "string" && rhtml.test( elem ) ) { | ||
elems[i] = elem = jQuery.htmlPrefilter(elem); | ||
} | ||
} | ||
return originalClean.call(this, elems, context, fragment, scripts); | ||
} | ||
}); | ||
} | ||
else { | ||
var originalBuildFragment = jQuery.buildFragment; | ||
jQuery.extend({ | ||
// @see https://github.com/jquery/jquery/blob/1.9.0/jquery.js#L6419 | ||
'buildFragment': function (elems, context, scripts, selection) { | ||
var l = elems.length; | ||
for ( var i = 0; i < l; i++ ) { | ||
var elem = elems[i]; | ||
if (elem || elem === 0) { | ||
if ( jQuery.type( elem ) !== "object" && rhtml.test( elem ) ) { | ||
elems[i] = elem = jQuery.htmlPrefilter(elem); | ||
} | ||
} | ||
} | ||
return originalBuildFragment.call(this, elems, context, scripts, selection); | ||
} | ||
}); | ||
} | ||
} | ||
|
||
})(jQuery); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters