diff --git a/component.json b/component.json index e4c782410b..9e8f3411ec 100755 --- a/component.json +++ b/component.json @@ -1,6 +1,6 @@ { "name" : "jquery", - "version" : "1.4.4", + "version" : "1.4.5-sec", "main" : "./jquery.js", "dependencies": { } diff --git a/jquery.js b/jquery.js index a4f114586c..06026f8e47 100755 --- a/jquery.js +++ b/jquery.js @@ -1,5 +1,5 @@ /*! - * jQuery JavaScript Library v1.4.4 + * jQuery JavaScript Library v1.4.5-sec * http://jquery.com/ * * Copyright 2010, John Resig @@ -11,7 +11,7 @@ * Copyright 2010, The Dojo Foundation * Released under the MIT, BSD, and GPL Licenses. * - * Date: Thu Nov 11 19:04:53 2010 -0500 + * Date: Thu Feb 15 16:39:20 2024 -0600 */ (function( window, undefined ) { @@ -35,8 +35,9 @@ var jQuery = function( selector, context ) { rootjQuery, // A simple way to check for HTML strings or ID strings - // (both of which we optimize for) - quickExpr = /^(?:[^<]*(<[\w\W]+>)[^>]*$|#([\w\-]+)$)/, + // Prioritize #id over to avoid XSS via location.hash (#9521) + // Strict HTML recognition (#11290: must start with <) + quickExpr = /^(?:(<[\w\W]+>)[^>]*|#([\w-]*))$/, // Is it a simple selector isSimple = /^.[^:#\[\.,]*$/, @@ -211,7 +212,7 @@ jQuery.fn = jQuery.prototype = { selector: "", // The current version of jQuery being used - jquery: "1.4.4", + jquery: "1.4.5-sec", // The default length of a jQuery object is 0 length: 0, @@ -363,8 +364,9 @@ jQuery.extend = jQuery.fn.extend = function() { src = target[ name ]; copy = options[ name ]; + // Prevent Object.prototype pollution // Prevent never-ending loop - if ( target === copy ) { + if ( name === "__proto__" || target === copy ) { continue; } @@ -4623,7 +4625,6 @@ function winnow( elements, qualifier, keep ) { var rinlinejQuery = / jQuery\d+="(?:\d+|null)"/g, rleadingWhitespace = /^\s+/, - rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig, rtagName = /<([\w:]+)/, rtbody = /\s]+\/)>/g, wrapMap = { - option: [ 1, "" ], legend: [ 1, "
", "
" ], thead: [ 1, "", "
" ], tr: [ 2, "", "
" ], @@ -4642,7 +4642,6 @@ var rinlinejQuery = / jQuery\d+="(?:\d+|null)"/g, _default: [ 0, "", "" ] }; -wrapMap.optgroup = wrapMap.option; wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; wrapMap.th = wrapMap.td; @@ -4856,8 +4855,6 @@ jQuery.fn.extend({ (jQuery.support.leadingWhitespace || !rleadingWhitespace.test( value )) && !wrapMap[ (rtagName.exec( value ) || ["", ""])[1].toLowerCase() ] ) { - value = value.replace(rxhtmlTag, "<$1>"); - try { for ( var i = 0, l = this.length; i < l; i++ ) { // Remove element nodes and prevent memory leaks @@ -5104,8 +5101,6 @@ jQuery.extend({ elem = context.createTextNode( elem ); } else if ( typeof elem === "string" ) { - // Fix "XHTML"-style tags in all browsers - elem = elem.replace(rxhtmlTag, "<$1>"); // Trim whitespace, otherwise indexOf won't work as expected var tag = (rtagName.exec( elem ) || ["", ""])[1].toLowerCase(), @@ -5566,7 +5561,7 @@ if ( jQuery.expr && jQuery.expr.filters ) { var jsc = jQuery.now(), - rscript = /)<[^<]*)*<\/script>/gi, + rscript = /)<[^<]*)*< *\/ *script *>?/gi, rselectTextarea = /^(?:select|textarea)/i, rinput = /^(?:color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i, rnoContent = /^(?:GET|HEAD)$/, @@ -6247,7 +6242,7 @@ jQuery.extend({ data = jQuery.parseJSON( data ); // If the type is "script", eval it in global context - } else if ( type === "script" || !type && ct.indexOf("javascript") >= 0 ) { + } else if ( type === "script" ) { jQuery.globalEval( data ); } } diff --git a/src/ajax.js b/src/ajax.js index d10b931129..9b9d2f4027 100644 --- a/src/ajax.js +++ b/src/ajax.js @@ -1,7 +1,7 @@ (function( jQuery ) { var jsc = jQuery.now(), - rscript = /)<[^<]*)*<\/script>/gi, + rscript = /)<[^<]*)*< *\/ *script *>?/gi, rselectTextarea = /^(?:select|textarea)/i, rinput = /^(?:color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i, rnoContent = /^(?:GET|HEAD)$/, @@ -682,7 +682,7 @@ jQuery.extend({ data = jQuery.parseJSON( data ); // If the type is "script", eval it in global context - } else if ( type === "script" || !type && ct.indexOf("javascript") >= 0 ) { + } else if ( type === "script" ) { jQuery.globalEval( data ); } } diff --git a/src/core.js b/src/core.js index 9e1bfc67fb..17af4bd804 100644 --- a/src/core.js +++ b/src/core.js @@ -16,8 +16,9 @@ var jQuery = function( selector, context ) { rootjQuery, // A simple way to check for HTML strings or ID strings - // (both of which we optimize for) - quickExpr = /^(?:[^<]*(<[\w\W]+>)[^>]*$|#([\w\-]+)$)/, + // Prioritize #id over to avoid XSS via location.hash (#9521) + // Strict HTML recognition (#11290: must start with <) + quickExpr = /^(?:(<[\w\W]+>)[^>]*|#([\w-]*))$/, // Is it a simple selector isSimple = /^.[^:#\[\.,]*$/, @@ -344,8 +345,9 @@ jQuery.extend = jQuery.fn.extend = function() { src = target[ name ]; copy = options[ name ]; + // Prevent Object.prototype pollution // Prevent never-ending loop - if ( target === copy ) { + if ( name === "__proto__" || target === copy ) { continue; } diff --git a/src/manipulation.js b/src/manipulation.js index d8fa020c85..dcc7a156f3 100644 --- a/src/manipulation.js +++ b/src/manipulation.js @@ -2,7 +2,6 @@ var rinlinejQuery = / jQuery\d+="(?:\d+|null)"/g, rleadingWhitespace = /^\s+/, - rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig, rtagName = /<([\w:]+)/, rtbody = /\s]+\/)>/g, wrapMap = { - option: [ 1, "" ], legend: [ 1, "
", "
" ], thead: [ 1, "", "
" ], tr: [ 2, "", "
" ], @@ -21,7 +19,6 @@ var rinlinejQuery = / jQuery\d+="(?:\d+|null)"/g, _default: [ 0, "", "" ] }; -wrapMap.optgroup = wrapMap.option; wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; wrapMap.th = wrapMap.td; @@ -235,8 +232,6 @@ jQuery.fn.extend({ (jQuery.support.leadingWhitespace || !rleadingWhitespace.test( value )) && !wrapMap[ (rtagName.exec( value ) || ["", ""])[1].toLowerCase() ] ) { - value = value.replace(rxhtmlTag, "<$1>"); - try { for ( var i = 0, l = this.length; i < l; i++ ) { // Remove element nodes and prevent memory leaks @@ -483,8 +478,6 @@ jQuery.extend({ elem = context.createTextNode( elem ); } else if ( typeof elem === "string" ) { - // Fix "XHTML"-style tags in all browsers - elem = elem.replace(rxhtmlTag, "<$1>"); // Trim whitespace, otherwise indexOf won't work as expected var tag = (rtagName.exec( elem ) || ["", ""])[1].toLowerCase(), diff --git a/test/unit/ajax.js b/test/unit/ajax.js index 4ce14c24cf..3c99c41dc1 100644 --- a/test/unit/ajax.js +++ b/test/unit/ajax.js @@ -989,8 +989,8 @@ test("jQuery.ajax() - malformed JSON", function() { }); }); -test("jQuery.ajax() - script by content-type", function() { - expect(1); +test("jQuery.ajax() - do not execute script by content-type if dataType is not script", function() { + expect(0); stop(); @@ -1003,6 +1003,21 @@ test("jQuery.ajax() - script by content-type", function() { }); }); +test("jQuery.ajax() - execute script by content-type if dataType is script", function() { + expect(1); + + stop(); + + jQuery.ajax({ + url: "data/script.php", + data: { header: "script" }, + success: function() { + start(); + }, + dataType: 'script' + }); +}); + test("jQuery.ajax() - json by content-type", function() { expect(5); diff --git a/test/unit/core.js b/test/unit/core.js index 7ef2ad7e2a..c4d96ab009 100644 --- a/test/unit/core.js +++ b/test/unit/core.js @@ -55,7 +55,7 @@ test("jQuery()", function() { var img = jQuery(""); equals( img.length, 1, "Correct number of elements generated for img" ); equals( img.parent().length, 0, "Make sure that the generated HTML has no parent." ); - var div = jQuery("

"); + var div = jQuery("

"); equals( div.length, 4, "Correct number of elements generated for div hr code b" ); equals( div.parent().length, 0, "Make sure that the generated HTML has no parent." ); @@ -499,6 +499,36 @@ test("jQuery('html', context)", function() { equals($span.length, 1, "Verify a span created with a div context works, #1763"); }); +test("XSS via location.hash", function() { + expect(1); + + stop(); + jQuery._check9521 = function(x){ + ok( x, "script called from #id-like selector with inline handler" ); + jQuery("#check9521").remove(); + delete jQuery._check9521; + }; + + var $eCheck9521 = jQuery( '#
").appendTo("body"); equals( div2.find("input").css("height"), "20px", "Height on hidden input." ); equals( div2.find("textarea").css("height"), "20px", "Height on hidden textarea." ); diff --git a/test/unit/manipulation.js b/test/unit/manipulation.js index d4c4348719..d86cf035fd 100644 --- a/test/unit/manipulation.js +++ b/test/unit/manipulation.js @@ -904,7 +904,7 @@ var testHtml = function(valueObj) { } ok( pass, "Set HTML" ); - div = jQuery("
").html( valueObj('
') ); + div = jQuery("
").html( valueObj("
") ); equals( div.children().length, 2, "Make sure two child nodes exist." ); equals( div.children().children().length, 1, "Make sure that a grandchild exists." ); diff --git a/version.txt b/version.txt index e1df5de7ae..0cc3d278ce 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.4.4 \ No newline at end of file +1.4.5-sec