diff options
author | Michał Gołębiowski-Owczarek <m.goleb@gmail.com> | 2019-01-14 19:29:54 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-01-14 19:29:54 +0100 |
commit | c7c2855ed13f23322c4064407c1ed84561b95738 (patch) | |
tree | 0bae25a4dd554f3066fdc1df65ecf6ea43d81752 | |
parent | 9cb162f6b62b6d4403060a0f0d2065d3ae96bbcc (diff) | |
download | jquery-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.js | 10 | ||||
-rw-r--r-- | test/data/csp-nonce.html | 13 | ||||
-rw-r--r-- | test/data/csp-nonce.js | 8 | ||||
-rw-r--r-- | test/data/mock.php | 8 | ||||
-rw-r--r-- | test/jquery.js | 2 | ||||
-rw-r--r-- | test/middleware-mockserver.js | 8 | ||||
-rw-r--r-- | test/unit/manipulation.js | 20 |
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" ] +); |