Skip to content
Permalink
Browse files

Core: Preserve CSP nonce on scripts in DOM manipulation

Fixes gh-3541
Closes gh-4269
  • Loading branch information...
mgol committed Jan 14, 2019
1 parent 9cb162f commit c7c2855ed13f23322c4064407c1ed84561b95738
Showing with 68 additions and 1 deletion.
  1. +10 −0 src/core/DOMEval.js
  2. +13 −0 test/data/csp-nonce.html
  3. +8 −0 test/data/csp-nonce.js
  4. +8 −0 test/data/mock.php
  5. +1 −1 test/jquery.js
  6. +8 −0 test/middleware-mockserver.js
  7. +20 −0 test/unit/manipulation.js
@@ -6,6 +6,7 @@ define( [
var preservedScriptAttributes = {
type: true,
src: true,
nonce: true,
noModule: true
};

@@ -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 ) );
}
}
}
@@ -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>
@@ -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 );
} );
@@ -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' );
}
@@ -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>" );
}

} )();
@@ -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 );
@@ -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" ]
);

0 comments on commit c7c2855

Please sign in to comment.
You can’t perform that action at this time.