Support for Drupal 7 is ending on 5 January 2025—it’s time to migrate to Drupal 10! Learn about the many benefits of Drupal 10 and find migration tools in our resource center.
Modules will likely need to specify additional domains that don't appear in a *.libraries.yml
file.
E.g.
- A local JavaScript file that makes calls to a remote API
- A third party widget that calls a separate domain than the one it is loaded from for data
- Web fonts that may only be specified within a CSS file
Comment | File | Size | Author |
---|---|---|---|
#28 | csp-2895245-28.patch | 32.1 KB | gapple |
#6 | csp-2895245-6-library-sources.patch | 3.95 KB | gapple |
Comments
Comment #2
gappleComment #3
gappleMaybe it is possible to just add another attribute to the library info in
*.libraries.yml
, andhook_library_info_alter
can be used where dynamic values are required.e.g.
would result in
Content-Security-Policy: default-src 'self'; script-src 'self' https://cdn.example.com; connect-src 'self' https://api.example.com
Comment #4
gappleDue to CKEditor's reliance on
'unsafe-inline'
(#2942401: CKEditor is broken without 'unsafe-inlne'), I think there may be a need for both global and request-specific alterations, though request-specific alterations should probably be discouraged.This would allow only adding
'unsafe-inline'
to pages which include thecore/ckeditor
library.Comment #5
gappleComment #6
gappleThis patch parses an additional
content-security-policy
key in the library info, and useshook_library_info_alter
to add the necessary directives to core libraries (ckeditor and umami).Comment #7
gappleFor some directives, a module may also want to add sources without modifying a library.
e.g. child-src, img-src, object-src, media-src, prefetch-src, frame-ancestors, form-action, navigate-to
Comment #8
Ambient.ImpactHi there. Any chance of this making it into a stable release sometime soon?
Comment #9
gappleSince I think an event will be necessary to control non-library based sources anyways, I currently prefer that approach and not duplicating the same functionality with the current patch's library-based declaration.
Comment #10
Ambient.ImpactYeah, generalizing it via an event and not hard-coding the libraries in that way makes a lot of sense.
Comment #11
gappleHere's an initial patch to add a
csp.alter
event. The event is called for each policy, so a page that implements both a report-only and enforced policy will have the event called twice.I would like to also implement a default listener for the Umami profile before committing.
Comment #12
Ambient.ImpactLet me know if you'd like me to test it or contribute anything.
Comment #13
gappleIf you have any particular use-cases for this API you could share, that would be helpful to determine if it will sufficiently meet real-world needs.
And general testing / feedback is always welcome.
Comment #14
gappleThe current use-cases I'm trying to cover:
- Adding
script-src 'unsafe-inline'; script-src-attr 'unsafe-inline'
when ckeditor is added to a page- Adding
font-src https://fonts.gstatic.com
when umami adds Google fonts onto the page (CSS is automatically allowed by library parsing)- Attach Inline module #3095521: Provide Content Security Policy hashes
Comment #15
gappleChanges in this patch
- Make event's name a little move verbose.
- The event object now contains the relevant response object, which allows inspecting the response's attached libraries.
-
Csp
previously wasn't introspectable - add methods to retrieve directive values. This may be important in cases such as using hashes, which override'unsafe-inline'
, so an alter may need to skip adding hashes if the policy already includes'unsafe-inline'
.- When a page's policy is initially generated, directives configured with the base value n/a are added with an empty value. Directives which don't have any values after being altered are removed from the output header value. This will allow an alter implementation to differentiate which directives have been enabled in configuration.
----
Some thoughts so far:
In the case of Umami, the domain for Google Font API's CSS is added to every page's style-src (even if not used on the page), but the font domain is only added when a font library is actually attached to the page. This gives the alter event two possibilities:
1. Always add the font-src directive, even if not enabled in config. If the site expects font-src to not be enabled, this could break functionality until enabled in config with sufficient defaults.
2. Only add the domain if font-src (or default-src) is enabled in config. In this case it may not be clear to the user why font-src is not being applied.
There is no indication in the configuration page that font-src should be enabled with a reasonable default for theses dynamic properties to be applied.
If Inline Attach blindly adds hashes, it could break ckeditor since adding any hash or nonce overrides the
script-src 'unsafe-inline'
that ckeditor requires. In this case I think the only option is to skip adding hashes if'unsafe-inline'
is already present in the policy. (hashes could still be added toscript-src-elem
and be compatible with ckeditor).As noted in a comment in the patch, the Response object's attached libraries list does not include any dependencies. This causes a bit of a problem for ckeditor because the root library that requires the alter is
core.ckeditor
but it's only a dependency of other libraries that are included on the page (e.g.ckeditor/drupal.ckeditor
).I'm hoping the method core uses to resolve those dependencies is publicly accessible. Maybe the fully resolved set of libraries should be added as a property on the event so that each alter implementation doesn't have to repeat the resolution.
This per-response event is not mutually exclusive with the previous library definition property, or another event to collect defaults which should appear in the "Auto Sources" on the configuration page and are applied to all responses. It may be better to use one of these for things like Umami's use of Google Font API where per-response changes aren't really beneficial.
Comment #16
gappleOops, forgot the patch
Comment #17
Ambient.ImpactMy use case for the time being is the CKEditor requirement of
script-src 'unsafe-inline'
. I'd love to not have that on pages where CKEditor is not present, at least until core updates to CKEditor 5, which apparently does away with this requirement.I'll give the patch a try when I get a chance and will let you know.
Comment #18
Ambient.ImpactFirst thoughts: while implementing the event subscriber, I noticed that the documentation in the patch refers to an
AlterEvent
class but the actual class name isPolicyAlterEvent
.I've got a subscriber set up now, but I'm wondering what the best way to check if CKEditor is attached would be? I've found
\Drupal\Core\Asset\AttachedAssetsInterface::getLibraries()
, but I'm having trouble figuring what service I need to inject into the event subscriber to query what libraries are attached.Comment #19
gappleCoreCspSubscriber::onCspPolicyAlter()
handles alterations for core modules (including CKEditor), and is a good example implementation.Drupal's
HtmlResponse
class implementsDrupal\Core\Render\AttachmentsInterface
, which provides thegetAttachments()
method for retrieving an array of all libraries / drupalSettings added to the response. As I noted in a previous comment, the list of libraries does not include any dependencies, so the list may need to be passed toLibraryDependencyResolver::getLibrariesWithDependencies()
.Comment #20
gappleSome smaller changes in this patch:
- Configuration form previously wouldn't save a directive as enabled without any values (except for script/style, due to values retrieved from libraries), preventing alter implementations from being able to tell the difference between a disabled and enabled but empty directive.
- Add
LibraryDependencyResolver
service toCoreCspSubscriber
to allow checking against full list of libraries included in response.-
CoreCspSubscriber
handles case wheredefault-src
is defined, butscript-src
is not, by duplicating the default policy, making any necessary additions, and then applying it toscript-src
- #2952390: Off-canvas styles override CKEditor's reset and theme Introduced the need for
style-src-elem 'unsafe-inline'
when CKEditor is included on the page, so this is also handled.Comment #21
Ambient.Impact🤦♀ Of course you already took care of the core CKEditor stuff. For some reason I assumed I'd have to implement that myself. :P
On first glance, this seems to be working correctly for the CKEditor stuff, at least in my local dev copy of my site.
Comment #22
gappleMostly code style fixes, but also:
- Remove
script-src 'unsafe-inline'
from the default config on module install. An update should not be applied to existing sites since something other than ckeditor may also rely on it.- Fix ResponseCspSubscriber tests, which weren't injecting the now required event dispatcher service
Comment #23
gappleI think this is the last patch
- Refactor setting directives for CKEditor if fallback directive is defined (e.g. duplicate and modify default-src to script-src)
- Added test class for
CoreCspSubscriber
- Added test to
ResponseCspSubscriberTest
that alter event is dispatched with expected configuration.Comment #24
gapple🤦♂️
Comment #25
gappleI think the IE9 compatibility code should also be moved to an alter implementation - this will clean up the response subscriber a little bit.
Drupal 8.8 is schedule for release on Dec 4, and 8.6 (the last version of core to include the IE9 CSS workaround) will also then lose security support. CSP could:
- Keep check for Drupal version, but remove corresponding tests (that never get executed in Drupal CI)
- Remove Drupal version check and rely on presence of IE9 module for enabling compatibility.
- Move compatibility alter event to IE9 module
I've created #3098049: Move IE9 Compatibility code as a followup to this issue.
Comment #26
Ambient.Impact#24 seems to be working for me at first glance!
Comment #27
Ambient.ImpactHmm. Seems I'm getting an Ajax error now whenever I try to save a link in the CKEditor link dialogue. Are you getting this as well, or could it be something unrelated on my end?
Comment #28
gappleThanks for catching that. Looks like
AjaxResponse
implementsAttachmentsInterface
, but in this case returns an empty array.Comment #29
Ambient.ImpactThe updated patch seems to have fixed it, thanks!
Comment #31
gappleComment #32
Ambient.ImpactThanks for your awesome work! Just installing the new stable release now.
Comment #33
Ambient.ImpactUpon further testing, I'm unable to open any any dialogs in the Views UI if I have
script-src
disabled, and am getting CSP errors in the console that inline JavaScript was blocked. Am I doing something wrong, or is the policy not accounting for Views UI pages? This is under 8.8.0 core and CSP 8.x-1.6, by the way.Comment #34
gappleI've opened #3100068: Script/style included in AJAX responses blocked without 'unsafe-inline' - so far it looks like this may be an issue with an AJAX response trying to inject a script element into the page.
Comment #35
Ambient.ImpactExcellent, thanks!