aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichał Gołębiowski-Owczarek <m.goleb@gmail.com>2019-01-14 19:29:54 +0100
committerGitHub <noreply@github.com>2019-01-14 19:29:54 +0100
commitc7c2855ed13f23322c4064407c1ed84561b95738 (patch)
tree0bae25a4dd554f3066fdc1df65ecf6ea43d81752
parent9cb162f6b62b6d4403060a0f0d2065d3ae96bbcc (diff)
downloadjquery-c7c2855ed13f23322c4064407c1ed84561b95738.tar.gz
jquery-c7c2855ed13f23322c4064407c1ed84561b95738.zip
Core: Preserve CSP nonce on scripts in DOM manipulation
Fixes gh-3541 Closes gh-4269
-rw-r--r--src/core/DOMEval.js10
-rw-r--r--test/data/csp-nonce.html13
-rw-r--r--test/data/csp-nonce.js8
-rw-r--r--test/data/mock.php8
-rw-r--r--test/jquery.js2
-rw-r--r--test/middleware-mockserver.js8
-rw-r--r--test/unit/manipulation.js20
7 files changed, 68 insertions, 1 deletions
diff --git a/src/core/DOMEval.js b/src/core/DOMEval.js
index 199ec9518..8d2d0023b 100644
--- a/src/core/DOMEval.js
+++ b/src/core/DOMEval.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 ) );
}
}
}
diff --git a/test/data/csp-nonce.html b/test/data/csp-nonce.html
new file mode 100644
index 000000000..d35c33fc4
--- /dev/null
+++ b/test/data/csp-nonce.html
@@ -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>
diff --git a/test/data/csp-nonce.js b/test/data/csp-nonce.js
new file mode 100644
index 000000000..507e87e68
--- /dev/null
+++ b/test/data/csp-nonce.js
@@ -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 );
+} );
diff --git a/test/data/mock.php b/test/data/mock.php
index 79110dc45..7e6aa1bec 100644
--- a/test/data/mock.php
+++ b/test/data/mock.php
@@ -198,6 +198,14 @@ ok( true, "mock executed");';
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' );
}
diff --git a/test/jquery.js b/test/jquery.js
index 8ba139e6b..6b1aef42f 100644
--- a/test/jquery.js
+++ b/test/jquery.js
@@ -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>" );
}
} )();
diff --git a/test/middleware-mockserver.js b/test/middleware-mockserver.js
index 09371bbe9..feed28148 100644
--- a/test/middleware-mockserver.js
+++ b/test/middleware-mockserver.js
@@ -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 );
diff --git a/test/unit/manipulation.js b/test/unit/manipulation.js
index 300add5ec..c8d5cdefe 100644
--- a/test/unit/manipulation.js
+++ b/test/unit/manipulation.js
@@ -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" ]
+);