This article outlines some advantages of using nonces to allow external scripts: https://scotthelme.co.uk/csp-nonces-the-easy-way-with-cloudflare-workers/.
- Allowing a CDN domain (e.g. cdnjs.com) allows any library available on the cdn, including older (potentially insecure) versions
- A single nonce can allow multiple scripts across external domains, shortening the policy header
Though the article uses Cloudflare Workers to isolate nonce generation from the application, having Drupal generate the nonce would have the same effect.
TODO
- Some way to specify scripts that should use a nonce instead of being allowed by domain
- Generate nonce value and add attribute to relevant elements
----
I previously assumed that each request required a new nonce so would be incompatible with page caching, but if I understand correctly a nonce must only be unique each time a page is generated.
Comments
Comment #2
neuquen commented+1
I am also interested in seeing this feature implemented.
Comment #3
gappleOne issue that likely makes this impractical is that using a nonce (or hash) overrides
unsafe-inline, which is currently required by CKEditor 4 and drupal/ajax, so it would likely break functionality.It will also require #2716115: Allow attributes passed with CSS in libraries (SRI) in order to be able to add an additional attribute to script tags.
Comment #4
prudloff commentedIt seems this would also allow using @strict-dynamic@ in order to allow scripts loaded by other scripts.
Comment #5
gappleEither a nonce or hash is required to use
strict-dynamic(since any other sources, including'self'are then ignored), but it will still have the same issues with blocking CKEditor 4 anddrupal/ajax.Since CKEditor 4 uses inline element attributes (which, in my understanding, are parser-inserted), it cannot be compatible with
strict-dynamic.Comment #6
mattcarrollnz commentedFor users who are comfortable with
core/ckeditorandcore/drupal.ajaxbreaking, is it possible to give them the option to enablestrict-dynamicand nonces?Nonces are currently the standard recommended practice for CSP, so I would argue that the lack of them is not something to be easily put aside. I'm curious if anyone is working on removing inline scripts (and styles) from these modules.
Comment #7
gappleSince drupal.ajax is pretty important to the admin pages of a site, I don't think it's a good idea currently to offer just a config option that would generate a nonce and apply it to all library scripts and styles. Maybe an API that front-end themes could call to enable when relevant, but I don't think a generic option is practical or beneficial.
The module's current API doesn't prevent anyone from implementing nonces for their own use case, but they'll also need to hook into the library system to apply it. CSP module could assist in this in the future - I would appreciate more defined use-cases so that the module can provide an appropriate generic solution - but it will probably remain a feature for developers to dynamically enable when appropriate rather than a configurable option.
The configuration form already allows enabling
'strict-dynamic', but without generating and applying hashes / a nonce to the page it will just currently block everything :).I would appreciate references for this - there are benefits as outlined in the issue summary and linked article, but I haven't seen any other recommendations for nonces as a generally preferred practice over a source list.
Yes, work is being done to add CKEditor 5 to core, which doesn't have the same inline script issues, and fixing an issue in how JavaScript is executed after new scripts are added to the page by drupal.ajax would also make it no longer require
'unsafe-inline'(at least for JS in the current implementation, but I will be pushing for changes to CSS handling as well. I'm not sure if this implementation would also be compatible with'strict-dynamic'or not).Comment #8
mattcarrollnz commentedMakes sense -- thank you for explaining all of that.
In regards to the recommendation for using nonces, you can find that Google specifies nonces as the preferred practice on these pages:
https://csp.withgoogle.com/docs/strict-csp.html
https://web.dev/strict-csp/
Upon submitting a website to Google's CSP Evaluator, if the website uses a source list it results in a "high severity finding", with the explanation: "Host whitelists can frequently be bypassed. Consider using 'strict-dynamic' in combination with CSP nonces or hashes."
Comment #9
kferencz91 commented+ 1 for this functionality as well.
We're using this module to generate a whitelist-approach CSP, and it's awesome. Thank you for all of the work that has been put into this.
Because the Google CSP Checker flags several of the domains we're whitelisting - several Google API endpoints, Google Analytics & Ad network URLs, most popular CDN - there are client concerns that this whitelist approach is still "failing", and the preferred method would be a nonce approach instead. Knowing the current conflicts with CKEditor, ideally, we'd be able to either apply this nonce-based CSP only for specific roles (non-admins who wouldn't be using CKEditor anyway for the current conflict), or at the bare minimum, in instances where those conflicting CKEditor libraries aren't present on page request.
Related to this, totally stumped on what the best way would be to automatically apply a nonce to all active scripts on a page (core + anything used in the active theme) that isn't then cached and re-served. We turned off the Internal (Anonymous) and Dynamic Cache in our testing environment, but were still running into issues where altering JS attributes was still saved into a per-page library_info cache, meaning the nonce was re-used across multiple user sessions, which is a no-go.
Comment #10
gapple@kferencz91
If you were using
hook_library_info_alterto apply a nonce - loading library info is relatively expensive since it parses yml files, so is cached globally.Post-
hook_css_alter/hook_js_alteris cached per set of libraries (so sort-of, but not quite per-page) by theAssetResolverservice. You could possibly decorate this service to apply changes on top of the cached values, but I'm pretty sure the later Grouper / Optimizer stages would omit a nonce from any local assets (though should still be fine with a'self' 'nonce-abcde'policy).The last phase in the rendering pipeline for assets is the CssCollectionRenderer / JsCollectionRenderer services, which could be decorated to apply the nonce attribute to all assets.
Comment #11
gappleSince report-only and enforced policies are separate objects, the page nonce will need to be generated & statically cached in a separate service so that it is consistent between them if both policies are added to a response.
Comment #12
gapple'unsafe-inline'Comment #13
dieterholvoet commentedCaching nonces is usually not a problem, but it's not 100% safe either. See the explanation at https://serverfault.com/a/1064775. Maybe you could add a disclaimer somewhere in the module description, or on the FAQ page in the documentation?
Comment #14
mstrelan commentedSince we have nonce support now this should no longer be postponed. Please change it back if I'm wrong. I'm interested to see if we can add the nonce to all external scripts that are loaded by libraries and therefore allow strict-dynamic
Comment #15
undersound3 commented+1 for being able to use strict-dynamic. Uncertain how to proceed but curious about what work needs to be done to get this going. Able to test if necessary.
Comment #16
john.glynn.davies commentedHi,
I just implementing using nonces on our site to allow scripts, but I'm having an issue where the nonce remains the same on subsequent page loads, so it appears to be getting cached somewhere.
I noticed your comment above suggests this might be by design but that doesn't seem to marry up with MDN docs on the subject.
If the nonce is cached and the same on repeated visits, it becomes accessible for an attacker to make use of it, no?
Hopefully I've just made a setup error of some kind?
Thanks
Comment #17
handkerchief+1 for being able to use strict-dynamic.
Comment #18
dragos-dumi commentedso with strict-dynamic, the whitelisting of script-src is ignored, including self. I was playing around with having strict-dynamic and as I've tested today, the nonce is not added to the libraries script tags. Not sure if I missed some configuration, but looking over the code I don't see where would that be. So this comment I guess is still up to date: https://www.drupal.org/project/csp/issues/3510684#comment-16026009