Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Core: Support passing nonce through jQuery.globalEval #4280

Merged
merged 1 commit into from
Jan 21, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/core.js
Original file line number Diff line number Diff line change
Expand Up @@ -238,8 +238,8 @@ jQuery.extend( {
},

// Evaluates a script in a global context
globalEval: function( code ) {
DOMEval( code );
globalEval: function( code, options ) {
DOMEval( code, { nonce: options && options.nonce } );
},

each: function( obj, callback ) {
Expand Down
27 changes: 15 additions & 12 deletions src/core/DOMEval.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,26 +10,29 @@ define( [
noModule: true
};

function DOMEval( code, doc, node ) {
function DOMEval( code, node, doc ) {
doc = doc || document;

var i,
var i, val,
script = doc.createElement( "script" );

script.text = code;
if ( node ) {
for ( i in preservedScriptAttributes ) {
if ( node[ i ] ) {
script[ i ] = node[ i ];
} else if ( node.getAttribute( i ) ) {

// Support: Firefox 64+, Edge 18+
// Some browsers don't support the "nonce" property on scripts.
// On the other hand, just using `setAttribute` & `getAttribute`
// is not enough as `nonce` is no longer exposed as an attribute
// in the latest standard.
// See https://github.com/whatwg/html/issues/2369
script.setAttribute( i, node.getAttribute( i ) );
// Support: Firefox 64+, Edge 18+
// Some browsers don't support the "nonce" property on scripts.
// On the other hand, just using `getAttribute` is not enough as
// the `nonce` attribute is reset to an empty string whenever it
// becomes browsing-context connected.
// See https://github.com/whatwg/html/issues/2369
// 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 );
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

}
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/manipulation.js
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ function domManip( collection, args, callback, ignored ) {
jQuery._evalUrl( node.src );
}
} else {
DOMEval( node.textContent.replace( rcleanScript, "" ), doc, node );
DOMEval( node.textContent.replace( rcleanScript, "" ), node, doc );
}
}
}
Expand Down
13 changes: 13 additions & 0 deletions test/data/csp-nonce-globaleval.html
Original file line number Diff line number Diff line change
@@ -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 changes: 5 additions & 0 deletions test/data/csp-nonce-globaleval.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
/* global startIframeTest */

jQuery( function() {
$.globalEval( "startIframeTest()", { nonce: "jquery+hardcoded+nonce" } );
} );
3 changes: 2 additions & 1 deletion test/data/mock.php
Original file line number Diff line number Diff line change
Expand Up @@ -201,9 +201,10 @@ protected function cspFrame( $req ) {
protected function cspNonce( $req ) {
// This is CSP only for browsers with "Content-Security-Policy" header support
// 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-type: text/html' );
echo file_get_contents( __DIR__ . '/csp-nonce.html' );
echo file_get_contents( __DIR__ . '/csp-nonce' . $test . '.html' );
}

protected function cspLog( $req ) {
Expand Down
4 changes: 3 additions & 1 deletion test/middleware-mockserver.js
Original file line number Diff line number Diff line change
Expand Up @@ -208,11 +208,13 @@ var mocks = {
resp.end( body );
},
cspNonce: function( req, resp ) {
var testParam = req.query.test ? "-" + req.query.test : "";
resp.writeHead( 200, {
"Content-Type": "text/html",
"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 );
},
cspLog: function( req, resp ) {
Expand Down
23 changes: 23 additions & 0 deletions test/unit/manipulation.js
Original file line number Diff line number Diff line change
Expand Up @@ -2858,3 +2858,26 @@ testIframe(
// script-src restrictions completely.
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" ]
);