Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue using JQuery 3.1.1 and CSP #3541

Closed
victorgaspar opened this Issue Feb 14, 2017 · 51 comments

Comments

Projects
None yet
@victorgaspar
Copy link

commented Feb 14, 2017

Description

Hi,

I'm using JQuery version 3.1.1 and I'm trying to implement Content Security Policy directives on my webpage.

I'm getting the following error:
Refused to execute inline script because it violates the following Content Security Policy directive: "script-src 'self' 'nonce-c20t41c7-73c6-4bf9-fde8-24a7b35t5f71'". Either the 'unsafe-inline' keyword, a hash ('sha256-KAcpKskREkEQf5B3mhDTonpPg34XnzaUC5IoBrOUrwY='), or a nonce ('nonce-...') is required to enable inline execution.

The error is produced on line 82 of the main jquery.js script file. The content of this line is:
doc.head.appendChild( script ).parentNode.removeChild( script );

Basically, it adds an inline script tag to the DOM, and violates the CSP.

I do not want to use 'unsafe-inline'. Is there any other way to circumvent this error?

As you can see on the CSP violation, I'm using CSP level 2 (nonce). Would it be possible (some how) to inform JQuery to use this nonce when appending the script tag?

Thank you very much.

Kind regards,
V.

@Brian-A

This comment has been minimized.

Copy link

commented Feb 26, 2017

Looks like all attributes get stripped by this call on line 5782
DOMEval( node.textContent.replace( rcleanScript, "" ), doc );
A new script tag gets created without any attributes and as a result the nonce is no longer present which causes the CSP violation.

The following can be used to demonstrate/replicate the issue:

<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="Content-Security-Policy" content="default-src http://localhost 'nonce-123456' ; child-src 'none'; object-src 'none'; script-src 'nonce-123456';">
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.js" nonce="123456"></script> <!-- HTML nonce works -->
    <script nonce="123456">
        //This works
        console.log('Inline nonce works');

        //This will also work
        var s = document.createElement('script');
        s.setAttribute('nonce', '123456');
        s.innerHTML = 'console.log("Dynamically generated inline tag works")';
        document.head.appendChild(s);

        // This won't work
        var s2 = document.createElement('script');
        s2.setAttribute('nonce', '123456');
        s2.innerHTML = 'console.log("Dynamically generated inline tag appended via jQuery doesn\'t work")';
        $(document.head).append( s2 ); // This will throw a CSP error    
    </script>    
</head>
<body>

</body>
</html>
@timmywil

This comment has been minimized.

Copy link
Member

commented Feb 27, 2017

Seems like this would be easy to fix. We can probably add the nonce attribute to our script tag if it exists.

@timmywil timmywil added this to the Future milestone Feb 27, 2017

Brian-A pushed a commit to Brian-A/jquery that referenced this issue Feb 28, 2017

Brian A Brian A
Core: Allow CSP nonce on script
Fixed CSP tags being stripped

Fixes: jquery#3541
@Brian-A

This comment has been minimized.

Copy link

commented Feb 28, 2017

I've implemented a fix by adding an optional argument to DOMEval which takes an object of attributes and passing the nonce through to it if one is present on a script tag. It currently passes all tests and I've added a relevant test to test that the nonce attribute does remain.

https://github.com/Brian-A/jquery/tree/3541-csp

Let me know if you'd like me to submit a PR or make any changes :)

@victorgaspar

This comment has been minimized.

Copy link
Author

commented Feb 28, 2017

Hi Brian, your solution works flawlessly! Hopefully it is promoted to main branch soon enough. In the meantime, I'm going to remove JQuery completly and use plain javascript to enable CSP. I'm quite surprise that such a powerful and widely use library as JQuery is not 'CSP friendly'. It took me two days until I finally decided to post the question.

Thanks for the help!

@koczkatamas

This comment has been minimized.

Copy link

commented Aug 23, 2017

Maybe I posting to the wrong issue (fix me pls!), but jQuery fails to handle the most common CSP-related case correctly.

In my case replaceWith is called with a HTML including this snippet

<script src="/docs/assets/js/page_helper.js"></script>

And jQuery takes this script tag, downloads the JS file with Ajax (evalUrl) and tries to put the JS code inline into a new script tag via which triggers CSP (unsafe-inline is disabled in CSP which is basically a must-have configuration).

var n = t.createElement("script");
n.text = e,
t.head.appendChild(n).parentNode.removeChild(n)

Repro case: jquery_csp_bug.zip (should be running on a HTTP server hosted on a http(s):// endpoint)
Expected behavior: console shows test.js running
Actual behavior: console shows the following error:

Refused to execute inline script because it violates the following Content Security Policy directive: "default-src http: https:". Either the 'unsafe-inline' keyword, a hash ('sha256-VcShpWhuVGQiiDKCgS044k0QHqA0fnQ2a3xoroT4FaE='), or a nonce ('nonce-...') is required to enable inline execution.

Is there any workaround for this? Should I open a new issue or will this be handled as part of this issue?

@dmethvin

This comment has been minimized.

Copy link
Member

commented Aug 23, 2017

The changes that @Brian-A wrote here look good, we just need a PR with that and some unit tests to ensure they work and aren't broken by subsequent changes.

@Brian-A Brian-A referenced this issue Aug 28, 2017

Closed

Core: Allow CSP nonce on script #3766

4 of 4 tasks complete
@Brian-A

This comment has been minimized.

Copy link

commented Aug 28, 2017

@dmethvin I've submitted a PR here.

@koczkatamas if you can include a nonce in your policy & snippet my patch should do the trick (See above for example), alternatively if you're able to (which I'm guessing is unlikely or difficult given the details you've provided) the following will work without violating CSP:

var s = $("<script></script>");
$('body').append(s);
s.attr('src', 'test.js');

Hopefully this is helpful :)

Brian-A added a commit to Brian-A/jquery that referenced this issue Sep 14, 2017

Core: Allow CSP nonce on script
Fixed CSP tags being stripped

Fixes: jquery#3541

Brian-A added a commit to Brian-A/jquery that referenced this issue Sep 14, 2017

Core: Allow CSP nonce on script
Fixed CSP tags being stripped

Fixes: jquery#3541
@subversivo58

This comment has been minimized.

Copy link

commented Nov 8, 2017

Accompanying the PR... was there any definition about the change request?

The good application of CSP is important for the application, is there any forecast of when this can be added to the core?

@Brian-A

This comment has been minimized.

Copy link

commented Nov 9, 2017

I updated the PR with the requested changes although I see now it may have gotten missed/lost due to the thread being marked as outdated? #3766 (comment)

@cnizzardini

This comment has been minimized.

Copy link

commented Jan 23, 2018

Has this issue been resolved in any versions of jQuery?

@timmywil

This comment has been minimized.

Copy link
Member

commented Jan 24, 2018

Not yet, but this should make it into the next release.

@mgol

This comment has been minimized.

Copy link
Member

commented Jan 24, 2018

@timmywil If that's the case, the Milestone should get updated. Now it just points to Future.

@mgol

This comment has been minimized.

Copy link
Member

commented Feb 7, 2018

I've been wondering - the error is caused by us manually evaling the downloaded script. Now, when cross domain we already do it differently, via a script tag with the src attribute set, see:
https://github.com/jquery/jquery/blob/3.3.1/src/ajax/script.js#L47-L74

Is there any reason why this has to be restricted to cross-domain?

@dmethvin

This comment has been minimized.

Copy link
Member

commented Feb 7, 2018

It's been a LOOOONG time but I think this was because the onerror event for scripts is relatively recent--is it now supported everywhere? To avoid silent failures for 404s and script errors we grabbed the source and evaled it.

@mgol

This comment has been minimized.

Copy link
Member

commented Feb 7, 2018

@dmethvin I've just tested (test case: http://output.jsbin.com/kosexoy) and it doesn't work in IE 8 but works in IE 9+; it also works in iOS 7+ which is what we support.

Unfortunately, it also doesn't work in Android Browser (all 4.0-4.3). Fortunately, Android Browser doesn't seem to support CSP so perhaps it'd work to extend the cross-domain way of loading scripts to modern browsers? Not sure how to check it, though. Android Browser satisfies document.createElement('script').onerror === null even though unknown attributes should have a value of undefined.

@aimee-katherine

This comment has been minimized.

Copy link

commented Feb 10, 2018

Hi, I'm using JQuery version 3.3.1 and I'm trying to implement Content Security Policy on my webpage.

I'm getting the following error:

Refused to execute inline script because it violates the following Content Security Policy directive: "script-src 'self' 'nonce-8WJnAqGXkJewcnh5byFtLu1IRq9Zu0Adv31B0k18DLaNBD1xHb19y8ppRMlY'
The error is produced on line 2 of jquery.min.js script file. The content of this line is:

function m(e,t,n){var i,o=(t=t||r).createElement("script");
Is there a way around this problem without having to use "unsafe-inline"? I've been looking all over the internet, desperate for a solution. =( I tried what Brian suggested to no avail...

@Brian-A

This comment has been minimized.

Copy link

commented Feb 10, 2018

Hi @aimee-katherine the following comments assume you're dynamically generating the script tags as that's what this issue is related to. you could try adding a hash ( sha256-yourhash; )of the script to your CSP although this isn't something I've tested with dynamically generated script tags I only tested if the attributes on the tag were stripped. Alternatively I've patched 3.1.1 to work with some dynamically generated tags and should work fine if the tag is generated using jQuery and a nonce (or possibly hash) is applied https://github.com/Brian-A/jquery/tree/3541-csp

If my comments don't help an example of how you're creating the script tags or a test case would help immensely :)

@Pomax

This comment was marked as off-topic.

Copy link

commented Mar 1, 2018

@mgol on a technical note, IE8 and IE9 were finally fully discontinued by Microsoft in mid-January of 2016, so it might not make sense to still aim for compat in these browsers anymore.

@mgol

This comment was marked as off-topic.

Copy link
Member

commented Mar 1, 2018

@Pomax The same applies to IE 10. That said, jQuery wouldn't gain a lot in size by cutting just IE 9 & 10 support; even cutting out IE 6-8 support only brought a ~12% size decrease and it eliminated a whole alternative event model & a lot of quirks. Apart from size a good motivation to dropping support would be an issue that is hard to fix while maintaining IE <11 support.

We might drop IE <11 one day but since most JS frameworks & (non-UI) libraries still support IE 9} I don't think we should be the ones to cut support first.

UI libraries like jQuery UI are dropping IE <11 a lot since they want to rely on flexbox; this is not a concern for jQuery core.

@Pomax

This comment was marked as off-topic.

Copy link

commented Mar 6, 2018

Amazingly IE10 has a weird grace-period still, thanks to Windows Server 2012, but that's more of a crazy bit of trivia than functional data that changes anything about the planned browser version support =)

@cnsgithub

This comment has been minimized.

Copy link

commented Jul 25, 2018

@fr4x1nu5

Btw, as a workaround one might use document.getElementById().outerHTML = newHTML where newHTML="<script nonce='123' />.

This will not work as expected since the script will not be executed. I think the best solution is adding nonce to preservedScriptAttributes as suggested by @timmywil.

cnsgithub added a commit to cnsgithub/primefaces that referenced this issue Jul 25, 2018

fix: replacing jquery's replaceWith with outerHTML does not work as e…
…xpected since outerHTML does not execute contained scripts (patched jquery as suggested in jquery/jquery#3541 by preserving the nonce attribute in jquery's DOMEval function)
@jlherren

This comment has been minimized.

Copy link

commented Sep 13, 2018

I implemented @timmywil's solution by adding 'nonce' to preservedScriptAttributes which works great in Chrome, but still failed on Edge/Firefox. The problem is these browsers seem to be picky about how you read/write the nonce attribute of the script element. So in addition to that I had to modify the code as follows:

for ( i in preservedScriptAttributes ) {
	// "node.getAttribute(i)" works in Edge/FF but not in chrome and "node[i]" works in chrome but not in Edge/FF
	// so just try both
	var val = node[i] || node.getAttribute(i);
	if ( val ) {
		// "script[i] = val" doesn't work in Edge/FF, setAttribute() works everywhere
		script.setAttribute(i, val);
	}
}
@boompig

This comment was marked as off-topic.

Copy link

commented Sep 25, 2018

What is the current workaround while we wait for the PR?

The issue has been open over 1.5 years so I feel we might be waiting a while longer for the fix to land...

@timmywil

This comment was marked as off-topic.

Copy link
Member

commented Sep 26, 2018

@boompig The issue has a PR that should make it into the next release, which we're trying to close out in the coming weeks. Issues can be open longer than 1.5 years and we purposefully avoid frequent releases. If you need to add a script tag with a noonce attribute, this is pretty easy to do with vanilla JS.

cnsgithub added a commit to cnsgithub/primefaces that referenced this issue Nov 19, 2018

fix: replacing jquery's replaceWith with outerHTML does not work as e…
…xpected since outerHTML does not execute contained scripts (patched jquery as suggested in jquery/jquery#3541 by preserving the nonce attribute in jquery's DOMEval function)

mgol added a commit to mgol/jquery that referenced this issue Jan 9, 2019

@mgol mgol self-assigned this Jan 9, 2019

@mgol

This comment has been minimized.

Copy link
Member

commented Jan 9, 2019

A new PR: #4269.

mgol added a commit to mgol/jquery that referenced this issue Jan 9, 2019

@tandraschko

This comment has been minimized.

Copy link

commented Jan 14, 2019

@mgol do you have a compiled jquery.js of your branch? So i could just test it.

@mgol mgol closed this in #4269 Jan 14, 2019

mgol added a commit that referenced this issue Jan 14, 2019

mgol added a commit that referenced this issue Jan 14, 2019

Tests: Skip nonce tests in old iOS/Android as well
Old iOS & Android Browser versions support script-src but not nonce, making the
nonce test impossible to run. Browsers not supporting CSP at all are not
a problem as they'll skip script-src restrictions completely.

Ref gh-3541
Ref gh-4269
Ref c7c2855
@mgol

This comment has been minimized.

Copy link
Member

commented Jan 14, 2019

@tandraschko The PR has landed so you can try https://code.jquery.com/jquery-git.js. Just please don't load this file in production. :)

@tandraschko

This comment has been minimized.

Copy link

commented Jan 15, 2019

@mgol all right, thanks :)
What about $.globalEval? Should we provide a way to pass the nonce?
How can i use DOMEval from my scripts until we we introduce something for $.globalEval?
XXX(?).DOMEval(myScript, document, { nonce: 'mynonce') }?

@mgol

This comment has been minimized.

Copy link
Member

commented Jan 15, 2019

@tandraschko It's not possible to pass nonce through $.globalEval at the moment. The merged PR just makes nonce preserved during DOM manipulation. If you'd like to see support for nonce in $.globalEval, please submit a separate issue. Thanks!

@tandraschko

This comment has been minimized.

Copy link

commented Jan 15, 2019

@mgol Done: #4278 - Thanks :)

mgol added a commit to mgol/jquery that referenced this issue Jan 17, 2019

mgol added a commit to mgol/jquery that referenced this issue Jan 17, 2019

mgol added a commit to mgol/jquery that referenced this issue Jan 18, 2019

mgol added a commit that referenced this issue Jan 21, 2019

@jfoclpf

This comment has been minimized.

Copy link

commented Feb 9, 2019

Good day
Considering that the error still persists, why the milestone 18 for v.3.4.0 and attached to this issue, doesn't mention this issue?
Thanks in advance

PS: Now I see is set to v4.0.0 through #3969. Thanks

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.