mirror of
https://github.com/jquery/jquery.git
synced 2024-11-23 02:54:22 +00:00
Core: Support passing nonce through jQuery.globalEval
Fixes gh-4278 Closes gh-4280 Ref gh-3541 Ref gh-4269
This commit is contained in:
parent
e4de8b4626
commit
5bdc85b82b
@ -238,8 +238,8 @@ jQuery.extend( {
|
|||||||
},
|
},
|
||||||
|
|
||||||
// Evaluates a script in a global context
|
// Evaluates a script in a global context
|
||||||
globalEval: function( code ) {
|
globalEval: function( code, options ) {
|
||||||
DOMEval( code );
|
DOMEval( code, { nonce: options && options.nonce } );
|
||||||
},
|
},
|
||||||
|
|
||||||
each: function( obj, callback ) {
|
each: function( obj, callback ) {
|
||||||
|
@ -10,26 +10,29 @@ define( [
|
|||||||
noModule: true
|
noModule: true
|
||||||
};
|
};
|
||||||
|
|
||||||
function DOMEval( code, doc, node ) {
|
function DOMEval( code, node, doc ) {
|
||||||
doc = doc || document;
|
doc = doc || document;
|
||||||
|
|
||||||
var i,
|
var i, val,
|
||||||
script = doc.createElement( "script" );
|
script = doc.createElement( "script" );
|
||||||
|
|
||||||
script.text = code;
|
script.text = code;
|
||||||
if ( node ) {
|
if ( node ) {
|
||||||
for ( i in preservedScriptAttributes ) {
|
for ( i in preservedScriptAttributes ) {
|
||||||
if ( node[ i ] ) {
|
|
||||||
script[ i ] = node[ i ];
|
|
||||||
} else if ( node.getAttribute( i ) ) {
|
|
||||||
|
|
||||||
// Support: Firefox 64+, Edge 18+
|
// Support: Firefox 64+, Edge 18+
|
||||||
// Some browsers don't support the "nonce" property on scripts.
|
// Some browsers don't support the "nonce" property on scripts.
|
||||||
// On the other hand, just using `setAttribute` & `getAttribute`
|
// On the other hand, just using `getAttribute` is not enough as
|
||||||
// is not enough as `nonce` is no longer exposed as an attribute
|
// the `nonce` attribute is reset to an empty string whenever it
|
||||||
// in the latest standard.
|
// becomes browsing-context connected.
|
||||||
// See https://github.com/whatwg/html/issues/2369
|
// See https://github.com/whatwg/html/issues/2369
|
||||||
script.setAttribute( i, node.getAttribute( i ) );
|
// See https://html.spec.whatwg.org/#nonce-attributes
|
||||||
|
// The `node.getAttribute` check was added for the sake of
|
||||||
|
// `jQuery.globalEval` so that it can fake a nonce-containing node
|
||||||
|
// via an object.
|
||||||
|
val = node[ i ] || node.getAttribute && node.getAttribute( i );
|
||||||
|
if ( val ) {
|
||||||
|
script.setAttribute( i, val );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -202,7 +202,7 @@ function domManip( collection, args, callback, ignored ) {
|
|||||||
jQuery._evalUrl( node.src );
|
jQuery._evalUrl( node.src );
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
DOMEval( node.textContent.replace( rcleanScript, "" ), doc, node );
|
DOMEval( node.textContent.replace( rcleanScript, "" ), node, doc );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
13
test/data/csp-nonce-globaleval.html
Normal file
13
test/data/csp-nonce-globaleval.html
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||||
|
<title>CSP nonce via jQuery.globalEval Test Page</title>
|
||||||
|
<script nonce="jquery+hardcoded+nonce" src="../jquery.js"></script>
|
||||||
|
<script nonce="jquery+hardcoded+nonce" src="iframeTest.js"></script>
|
||||||
|
<script nonce="jquery+hardcoded+nonce" src="csp-nonce-globaleval.js"></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<p>CSP nonce via jQuery.globalEval Test Page</p>
|
||||||
|
</body>
|
||||||
|
</html>
|
5
test/data/csp-nonce-globaleval.js
Normal file
5
test/data/csp-nonce-globaleval.js
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
/* global startIframeTest */
|
||||||
|
|
||||||
|
jQuery( function() {
|
||||||
|
$.globalEval( "startIframeTest()", { nonce: "jquery+hardcoded+nonce" } );
|
||||||
|
} );
|
@ -201,9 +201,10 @@ ok( true, "mock executed");';
|
|||||||
protected function cspNonce( $req ) {
|
protected function cspNonce( $req ) {
|
||||||
// This is CSP only for browsers with "Content-Security-Policy" header support
|
// This is CSP only for browsers with "Content-Security-Policy" header support
|
||||||
// i.e. no old WebKit or old Firefox
|
// i.e. no old WebKit or old Firefox
|
||||||
|
$test = $req->query['test'] ? '-' . $req->query['test'] : '';
|
||||||
header( "Content-Security-Policy: script-src 'nonce-jquery+hardcoded+nonce'; report-uri ./mock.php?action=cspLog" );
|
header( "Content-Security-Policy: script-src 'nonce-jquery+hardcoded+nonce'; report-uri ./mock.php?action=cspLog" );
|
||||||
header( 'Content-type: text/html' );
|
header( 'Content-type: text/html' );
|
||||||
echo file_get_contents( __DIR__ . '/csp-nonce.html' );
|
echo file_get_contents( __DIR__ . '/csp-nonce' . $test . '.html' );
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function cspLog( $req ) {
|
protected function cspLog( $req ) {
|
||||||
|
@ -208,11 +208,13 @@ var mocks = {
|
|||||||
resp.end( body );
|
resp.end( body );
|
||||||
},
|
},
|
||||||
cspNonce: function( req, resp ) {
|
cspNonce: function( req, resp ) {
|
||||||
|
var testParam = req.query.test ? "-" + req.query.test : "";
|
||||||
resp.writeHead( 200, {
|
resp.writeHead( 200, {
|
||||||
"Content-Type": "text/html",
|
"Content-Type": "text/html",
|
||||||
"Content-Security-Policy": "script-src 'nonce-jquery+hardcoded+nonce'; report-uri /base/test/data/mock.php?action=cspLog"
|
"Content-Security-Policy": "script-src 'nonce-jquery+hardcoded+nonce'; report-uri /base/test/data/mock.php?action=cspLog"
|
||||||
} );
|
} );
|
||||||
var body = fs.readFileSync( __dirname + "/data/csp-nonce.html" ).toString();
|
var body = fs.readFileSync(
|
||||||
|
__dirname + "/data/csp-nonce" + testParam + ".html" ).toString();
|
||||||
resp.end( body );
|
resp.end( body );
|
||||||
},
|
},
|
||||||
cspLog: function( req, resp ) {
|
cspLog: function( req, resp ) {
|
||||||
|
@ -2888,3 +2888,26 @@ testIframe(
|
|||||||
// script-src restrictions completely.
|
// script-src restrictions completely.
|
||||||
QUnit[ /\bedge\/|iphone os [789]|android 4\./i.test( navigator.userAgent ) ? "skip" : "test" ]
|
QUnit[ /\bedge\/|iphone os [789]|android 4\./i.test( navigator.userAgent ) ? "skip" : "test" ]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
testIframe(
|
||||||
|
"jQuery.globalEval supports nonce",
|
||||||
|
"mock.php?action=cspNonce&test=globaleval",
|
||||||
|
function( assert, jQuery, window, document ) {
|
||||||
|
var done = assert.async();
|
||||||
|
|
||||||
|
assert.expect( 1 );
|
||||||
|
|
||||||
|
supportjQuery.get( baseURL + "support/csp.log" ).done( function( data ) {
|
||||||
|
assert.equal( data, "", "No log request should be sent" );
|
||||||
|
supportjQuery.get( baseURL + "mock.php?action=cspClean" ).done( done );
|
||||||
|
} );
|
||||||
|
},
|
||||||
|
|
||||||
|
// Support: Edge 18+, iOS 7-9 only, Android 4.0-4.4 only
|
||||||
|
// Edge doesn't support nonce in non-inline scripts.
|
||||||
|
// See https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/13246371/
|
||||||
|
// Old iOS & Android Browser versions support script-src but not nonce, making this test
|
||||||
|
// impossible to run. Browsers not supporting CSP at all are not a problem as they'll skip
|
||||||
|
// script-src restrictions completely.
|
||||||
|
QUnit[ /\bedge\/|iphone os [789]|android 4\./i.test( navigator.userAgent ) ? "skip" : "test" ]
|
||||||
|
);
|
||||||
|
Loading…
Reference in New Issue
Block a user