Problem/Motivation
A nonce service was added so the CSP module can provide a single value for a request to all modules that require it, but it's currently still up to modules to apply the nonce to the policy directives and relevant markup as required.
Some consumers may need the nonce in JavaScript - e.g. google_tag needs the nonce applied to its inserted script which it then propagates to any additional scripts it includes (#3203811: Support Content Security Policy).
Proposed resolution
- add a csp/nonce library which other libraries can add as a dependency. The library will not have any files itself.
- other modules will be responsible for altering relevant directives to include the nonce value from the csp.nonce service via their csp.policy_alter event subscriber.
- when the csp/nonce library is present on a response and a directive includes the nonce value, csp's response event subscriber will add the nonce value to drupalSettings
Remaining tasks
User interface changes
n/a
API changes
a new library is available
Data model changes
n/a
Issue fork csp-3398535
Show commands
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
Comments
Comment #2
gapple#3398536: Enable conditional/alternate directive values
If a directive includes
'unsafe-inline', modules may need to fall back to adding domains to the directive instead of a nonce (which would disable'unsafe-inline'for other modules that rely on it). In that case the nonce should possibly not be added todrupalSettings¹¹ I don't think it would be harmful - any scripts should be allowed by
'unsafe-inline'or a domain as necessary and the nonce on their tag would just be ignored.Comment #4
gappleI previously had a concern about exposing the nonce value to JavaScript like this, but since the nonce attribute on any page element is accessible to JavaScript, this does not expose anything not already available to any script via
document.querySelector('script[nonce]').nonce.Any script not conforming to the page's policy (e.g. an inline script element injected into the page which does not contain the correct nonce attribute) will be blocked, but if a bad script is able to bypass the policy (e.g. by being injected with a correct nonce attribute, or from a domain otherwise allowed by the policy), then it could already do significant harm regardless of being able to propagate the nonce to additional harmful scripts¹.
See https://github.com/w3c/webappsec-csp/issues/458
Note that browser dev tools will hide the nonce attribute's value when inspecting script elements, but it is still available to any scripts run on the page or in the console.
¹ Propagating the nonce could potentially do more harm by it's ability to allow additional scripts from any domain, while a domain-only policy would restrict the ability to load additional scripts to domains that have some measure of trust. A nonce-only policy (or with a very limited set of domains) could make an initial compromise more difficult though.
Comment #5
dieterholvoet commentedNote for module maintainers: you can add
csp/nonceto your library dependencies without adding thecspmodule as dependency of your module. Not sure if it's a bug, butDrupal\Core\Asset\LibraryDependencyResolver::doGetDependenciesignores any libraries that are listed underdependenciesbut don't actually exist.Comment #6
dieterholvoet commentedHow would a directive currently include a nonce value? Shouldn't the module provide an option to do this? The nonce is random, so we can't hardcode it in config.
Comment #7
dieterholvoet commentedComment #8
gappleInteresting; good to know. I think the recommended way will be to use
hook_library_info_alter()to add the dependency if the csp module is enabled.The
csp.nonceservice will generate a value as needed so that all modules have the same value for a single response, and modules can useNonce::getSource()to get the formatted value for adding to the necessary directives in theircsp.policy_alterevent listener. (CSP handles removing duplicates in the header if multiple modules use the nonce value on the same directive).(I don't think the nonce-source should be automatically added to a policy header if the library is present as a dependency for the response; it's uncertain if any module is always adding a nonce source, which directives it's needed for, or if it will be needed for either or both of a report-only and enforced policy).
Comment #9
dieterholvoet commentedMakes sense, thanks! Is it possible for themes to alter the policy? Otherwise we won't be able to use this for #3399602: Support Content Security Policy.
Comment #10
gappleIt looks like no, not directly, since themes can't define services 😔: #2002606: Allow themes to provide services.yml
They can have a module dependency which has more capabilities: #474684: Allow themes to declare dependencies on modules
I've opened a new plan issue for figuring out changes for better support of themes (and maybe easier options for modules too): #3402029: Better CSP support for themes
Comment #12
gapple