Skip to content
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
10 changes: 10 additions & 0 deletions src/core/DOMEval.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ define( [
var preservedScriptAttributes = {
type: true,
src: true,
nonce: true,
noModule: true
};

Expand All @@ -20,6 +21,15 @@ define( [
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 ) );
Copy link
Member

Choose a reason for hiding this comment

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

Oh joy. Thanks for the comment!

Copy link
Member

@gibson042 gibson042 Jan 14, 2019

Choose a reason for hiding this comment

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

I think we should use the attribute path for all preservedScriptAttributes, rather than introducing separate paths.

Copy link
Member Author

Choose a reason for hiding this comment

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

This will only work if the property & an attribute is named with identical casing but from our fixed list only nonce may get to this line so we should be safe for now.

}
}
}
Expand Down
13 changes: 13 additions & 0 deletions test/data/csp-nonce.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 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.js"></script>
</head>
<body>
<p>CSP nonce Test Page</p>
</body>
</html>
8 changes: 8 additions & 0 deletions test/data/csp-nonce.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/* global startIframeTest */

jQuery( function() {
var script = document.createElement( "script" );
script.setAttribute( "nonce", "jquery+hardcoded+nonce" );
script.innerHTML = "startIframeTest()";
$( document.head ).append( script );
} );
8 changes: 8 additions & 0 deletions test/data/mock.php
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,14 @@ protected function cspFrame( $req ) {
echo file_get_contents( __DIR__ . '/csp.include.html' );
}

protected function cspNonce( $req ) {
// This is CSP only for browsers with "Content-Security-Policy" header support
// i.e. no old WebKit or old Firefox
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' );
}

protected function cspLog( $req ) {
file_put_contents( $this->cspFile, 'error' );
}
Expand Down
2 changes: 1 addition & 1 deletion test/jquery.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@

// Otherwise, load synchronously
} else {
document.write( "<script id='jquery-js' src='" + parentUrl + src + "'><\x2Fscript>" );
document.write( "<script id='jquery-js' nonce='jquery+hardcoded+nonce' src='" + parentUrl + src + "'><\x2Fscript>" );
}

} )();
8 changes: 8 additions & 0 deletions test/middleware-mockserver.js
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,14 @@ var mocks = {
var body = fs.readFileSync( __dirname + "/data/csp.include.html" ).toString();
resp.end( body );
},
cspNonce: function( req, resp ) {
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();
resp.end( body );
},
cspLog: function( req, resp ) {
cspLog = "error";
resp.writeHead( 200 );
Expand Down
20 changes: 20 additions & 0 deletions test/unit/manipulation.js
Original file line number Diff line number Diff line change
Expand Up @@ -2835,3 +2835,23 @@ QUnit.test( "Ignore content from unsuccessful responses (gh-4126)", 1, function(
jQuery.globalEval = globalEval;
}
} );

testIframe(
"Check if CSP nonce is preserved",
"mock.php?action=cspNonce",
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+
// Edge doesn't support nonce in non-inline scripts.
// See https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/13246371/
QUnit[ /\bedge\//i.test( navigator.userAgent ) ? "skip" : "test" ]
);