🌐 AI搜索 & 代理 主页
Skip to content

Commit c7c2855

Browse files
authored
Core: Preserve CSP nonce on scripts in DOM manipulation
Fixes gh-3541 Closes gh-4269
1 parent 9cb162f commit c7c2855

File tree

7 files changed

+68
-1
lines changed

7 files changed

+68
-1
lines changed

src/core/DOMEval.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ define( [
66
var preservedScriptAttributes = {
77
type: true,
88
src: true,
9+
nonce: true,
910
noModule: true
1011
};
1112

@@ -20,6 +21,15 @@ define( [
2021
for ( i in preservedScriptAttributes ) {
2122
if ( node[ i ] ) {
2223
script[ i ] = node[ i ];
24+
} else if ( node.getAttribute( i ) ) {
25+
26+
// Support: Firefox 64+, Edge 18+
27+
// Some browsers don't support the "nonce" property on scripts.
28+
// On the other hand, just using `setAttribute` & `getAttribute`
29+
// is not enough as `nonce` is no longer exposed as an attribute
30+
// in the latest standard.
31+
// See https://github.com/whatwg/html/issues/2369
32+
script.setAttribute( i, node.getAttribute( i ) );
2333
}
2434
}
2535
}

test/data/csp-nonce.html

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
5+
<title>CSP nonce Test Page</title>
6+
<script nonce="jquery+hardcoded+nonce" src="../jquery.js"></script>
7+
<script nonce="jquery+hardcoded+nonce" src="iframeTest.js"></script>
8+
<script nonce="jquery+hardcoded+nonce" src="csp-nonce.js"></script>
9+
</head>
10+
<body>
11+
<p>CSP nonce Test Page</p>
12+
</body>
13+
</html>

test/data/csp-nonce.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
/* global startIframeTest */
2+
3+
jQuery( function() {
4+
var script = document.createElement( "script" );
5+
script.setAttribute( "nonce", "jquery+hardcoded+nonce" );
6+
script.innerHTML = "startIframeTest()";
7+
$( document.head ).append( script );
8+
} );

test/data/mock.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,14 @@ protected function cspFrame( $req ) {
198198
echo file_get_contents( __DIR__ . '/csp.include.html' );
199199
}
200200

201+
protected function cspNonce( $req ) {
202+
// This is CSP only for browsers with "Content-Security-Policy" header support
203+
// i.e. no old WebKit or old Firefox
204+
header( "Content-Security-Policy: script-src 'nonce-jquery+hardcoded+nonce'; report-uri ./mock.php?action=cspLog" );
205+
header( 'Content-type: text/html' );
206+
echo file_get_contents( __DIR__ . '/csp-nonce.html' );
207+
}
208+
201209
protected function cspLog( $req ) {
202210
file_put_contents( $this->cspFile, 'error' );
203211
}

test/jquery.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@
5454

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

6060
} )();

test/middleware-mockserver.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,14 @@ var mocks = {
207207
var body = fs.readFileSync( __dirname + "/data/csp.include.html" ).toString();
208208
resp.end( body );
209209
},
210+
cspNonce: function( req, resp ) {
211+
resp.writeHead( 200, {
212+
"Content-Type": "text/html",
213+
"Content-Security-Policy": "script-src 'nonce-jquery+hardcoded+nonce'; report-uri /base/test/data/mock.php?action=cspLog"
214+
} );
215+
var body = fs.readFileSync( __dirname + "/data/csp-nonce.html" ).toString();
216+
resp.end( body );
217+
},
210218
cspLog: function( req, resp ) {
211219
cspLog = "error";
212220
resp.writeHead( 200 );

test/unit/manipulation.js

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2835,3 +2835,23 @@ QUnit.test( "Ignore content from unsuccessful responses (gh-4126)", 1, function(
28352835
jQuery.globalEval = globalEval;
28362836
}
28372837
} );
2838+
2839+
testIframe(
2840+
"Check if CSP nonce is preserved",
2841+
"mock.php?action=cspNonce",
2842+
function( assert, jQuery, window, document ) {
2843+
var done = assert.async();
2844+
2845+
assert.expect( 1 );
2846+
2847+
supportjQuery.get( baseURL + "support/csp.log" ).done( function( data ) {
2848+
assert.equal( data, "", "No log request should be sent" );
2849+
supportjQuery.get( baseURL + "mock.php?action=cspClean" ).done( done );
2850+
} );
2851+
},
2852+
2853+
// Support: Edge 18+
2854+
// Edge doesn't support nonce in non-inline scripts.
2855+
// See https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/13246371/
2856+
QUnit[ /\bedge\//i.test( navigator.userAgent ) ? "skip" : "test" ]
2857+
);

0 commit comments

Comments
 (0)