Account created on 20 April 2009, over 15 years ago
#

Merge Requests

More

Recent comments

🇨🇦Canada gapple

Is it worth it to include the contrib minor version? It's additional detail than previously, where the Compatibility-Major.PatchLevel scheme melded together changes that would now be separated to semantic minor and patch releases. I expect in most cases update functions are going to be tied to minor-level changes, so there would be a lot of M0101, M0201, M0301....

The minimum schema version sets the lower bound of numbering at 8000 while it still exists, but the default recommendation could just be Mdddd (major without leading zero + 4 digit increment). Only a note would be required for pre-stable 0.x.x versions to start the update numbering at 8001.
Contrib modules could choose to include the minor version if they will be concurrently supporting minor releases for a longer duration, or just leave an arbitrary gap (e.g. +10) to account for the potential of patch-level updates.

🇨🇦Canada gapple

Applying default-src 'none' to other private files should only have an impact if sites were serving HTML files, and would be irrelevant to other responses like image files, so it might be worth leaving for discussion in 📌 Add a default CSP and clickjacking defence and minimal API for CSP to core Active or breaking out to a separate issue. It could then be done in combination to applying the same change for the files directory htaccess so that private and public files would have consistent behaviour, like SVGs would with this issue.

🇨🇦Canada gapple

@timohuisman that's odd, but I guess not unexpected that a response might not have a content type header.

I think I would prefer to update the patch so that it only excludes content types and response classes that it knows are safe.

🇨🇦Canada gapple

I don't think a short persistent login lifetime is useful, since PL cookies are intended to have a longer lifetime than session cookies, and are ineffective in the inverse case.

If you can better outline your use-case, and how it's addressed by allowing short PL lifetimes, please reopen the issue.

🇨🇦Canada gapple

Quick fix to add new words to cspell dictionary

🇨🇦Canada gapple

Made a MR with changes from patch file.

🇨🇦Canada gapple

@damienmckenna
Possibly - the full violation report should include an original-policy property that you can verify if clients are receiving the updated directive.
Including a hash, nonce, or using 'strict-dynamic' would also disable inline scripts, but it sounds like you're not using any of those.

('inline' isn't a valid directive source, but it should just be ignored).

🇨🇦Canada gapple

Updated the patch from #105 in a MR

- Move allowedSlots property declaration to constructor; replaces mismatched default value on property (#106)
- Added missing early return in set() (#113)
- Override setMultiple() to only count() extra items once before removal (#108)
- Code style fixes

🇨🇦Canada gapple

gapple made their first commit to this issue’s fork.

🇨🇦Canada gapple

Can you elaborate on your use-case of this short of a token lifetime, and why you would like to do this with Persistent Login rather than setting a short session lifetime or use a module that enforces a session timeout after a configurable period?

With the module's recommended setting of the cookie_lifetime to 0, a browser will keep the session cookie until the browser is closed (provided it isn't still kept longer because of a session restore feature). With browsers remaining open in the background even when all windows are closed, the short-lifetime PL token could expire before the browser cleans up the session cookie.
Since the session cookie takes precedence, it will in most cases likely outlive a short persistent login.

🇨🇦Canada gapple

The test includes a couple keys previously supported by core, but not an unknown key (e.g. the csp example in the issue summary)

🇨🇦Canada gapple

Something that came up in #2868079: Add a default Content-Security-Policy-header for svg files is that there may be a need for different policies in certain cases - uploaded files should probably have scripts and styles blocked, though SVGs may need inline styles, image data, and fonts. Private files can have the header applied from the event subscriber, but public files would require an addition to .htaccess.

Instead of a single set of policies, the service parameter could be keyed by use:

default:
  report_only:
  enforced: "script-src * 'unsafe-inline'; object-src 'none'; frame-ancestors 'self'"
private_files:
  report_only:
  enforced: "default-src 'none'"
svg:
  report_only:
  enforced: "default-src 'none'; style-src 'unsafe-inline'; image-src data: font-src: data:"
🇨🇦Canada gapple

👋 CSP module maintainer here.
CSP module provides APIs for modules to amend a site's policy . In most cases it's pretty straightforward, but gets more involved for cases where it's not just adding an additional external domain to a directive. The goal of the module is that anyone can install the module for a security improvement, that it's easily configurable for site builders to add exceptions not captured automatically (& ideally harden the default config with basic knowledge), but also flexible for developers to handle any more complex uses (and to do so safely without breaking other site functionality).
Module subscribers with the same priority will execute after core, so it's the module's responsibility to preserve/amend/replace any value previously set by core.

CSP has its own issue for applying a different policy to private files ( Provide different CSP policy for private files Active ), though there hasn't been any work done on it so far. If a special value is added to core for SVGs, then I'll update the module to match. If there's consensus on what should be added to core, I'll probably have a new release of the module before it's committed to core 🙂.
Alternately, the CSP module would be a good way to evaluate a potential solution (at least for private files, I'm not sure about the module altering htaccess), with users who have opted in to using a policy on their site. It would have to be an optional feature for the current major version, but could be enabled by default for new modules installs (and a site status message could prompt existing sites to try enabling it).

This issue for core would add a static policy that can be configured in a service parameter: 📌 Add a default CSP and clickjacking defence and minimal API for CSP to core Active
Instead of providing a single policy set, maybe it should be keyed policies to allow for additional cases (e.g. default, private-files, svg, etc, each with report-only and enforced values).

🇨🇦Canada gapple

Better description of alter priority; example of nonce & fallback

🇨🇦Canada gapple

Ran into an issue with the the return type change, since I was developing a module using the latest version of core and copied the new return type hint.

When using the new return type in an override with a stable version of core <=11.0.5, the child class is returning a wider type than it's parent.
When using the old return type in an override with 11.x-dev, parent::formatMultipleViolationsMessage() returns a wider type than the child class.

For a module to maintain compatibility with older versions of core and not break if it calls the parent method which now returns Markup, it will need to change the value returned from its parent:

    $parent = parent::formatMultipleViolationsMessage($form_element_name, $violations);
    if ($parent instanceof TranslatableMarkup) {
      return $parent;
    }
    else {
      // phpcs:ignore Drupal.Semantics.FunctionT.NotLiteralString
      return $this->t((string) $parent);
    }

Once the module drops support for older versions of core, it can update its typehint and remove the extra code.

\Drupal\update\UpdateSettingsForm also needs its return type updated.

🇨🇦Canada gapple

The current MR would address multiple violations on a non-sequence value, but if an item within a sequence has multiple violations it looks like only the last one will be kept.

ConfigFormBase::formatMultipleViolationsMessage() also assumes it's being called on a sequence, so multiple constraint violations on a non-sequence value would still be formatted like "Entry 0: Constraint 1 message \n Entry 1: Constraint 2 message".
Forms can override the method to change the output based on the form element name in this case though.

🇨🇦Canada gapple

Changes to provide a form error if an unavailable reporting plugin is referenced in config are in the 2.1.1 release.

Be sure to run module updates, and let me know if you continue to see a similar error.

🇨🇦Canada gapple

Is this after updating from 1.x to 2.x? Do you have a pending site update?

https://www.drupal.org/docs/extending-drupal/contributed-modules/contrib...
The sitelog reporting handler was removed from 2.x in favour of the Reporting API module , and an update will disable policy violation reporting on a directive if it has not been changed to a supported alternative.

It is still possible to better handle the configuration referencing an unavailable reporting plugin there though...

🇨🇦Canada gapple

🤞 that's a final fix for this issue.

Just wanted to also note that the tokens in the database aren't accepted even if provided by a browser, and this cleanup is only really needed for sites with tokens configured to a permanent lifetime, so there isn't a problem if the update is not completed on a site (provided it doesn't block any other necessary updates).

🇨🇦Canada gapple

That's odd... On the last iteration $sandbox['#finished'] = $sandbox['processed'] / $sandbox['total']; should equal 1 to complete the batch.
Are there tokens stored for the anonymous user (uid:0)? That would increase $sandbox['total'] to one more than will be returned in the $token_users queries - but that shouldn't happen so some checks might need to be added elsewhere 😬.

🇨🇦Canada gapple

Didn't catch @jabeler's review before - updating to RTBC :)

Bumping priority - CSP 1.x is still the most used version at this time, but is no longer receiving feature updates.

🇨🇦Canada gapple

The double-hashing was fixed in 8.x-1.7 and 2.2.1
Cleaning up tokens for deleted users was fixed in 8.x-1.9 and 2.2.3

🇨🇦Canada gapple

Thanks for the quick patch & review :)

New patch releases should be available shortly.

🇨🇦Canada gapple

@sokru My understanding is that whole page caching of a response with a nonce can be acceptable: https://serverfault.com/a/1064775/66144
Using a render placeholder ensures that a new nonce is sent for any request from an authenticated user or otherwise not served from the page cache, where new markup could be placed on the page but could only be aware of an outdated nonce value.

An issue with the proxy / edge cache worker example is that that using a predictable placeholder like NGINX_CSP_NONCE could allow any injected content to use that value as well and have it replaced with the valid nonce.
The current patch also has this issue, as sprintf('nonce_%s', Crypt::hashBase64(__METHOD__)) will result in a known static value. The CSP module uses a random value in its placeholder so that it's not predictable between requests, but using the site's hash_salt would would also work as a way to provide a consistent but unique and unpredictable placeholder value for a site.

🇨🇦Canada gapple

@rgpublic A hash can't be used on the external gtm or gtag js because their contents aren't known or static. The loader file could change at any time, making the hash invalid, and any additional dynamically loaded scripts won't be permitted.
The tag manager script loader will propagate the nonce to additional scripts (as verified by @chrissnyder in #12), without requiring the originating page to know the script contents (for a hash) or source domain (for non-tag manager scripts) to place in the policy.

🇨🇦Canada gapple

@berliner From the one post I've seen that's worked through the impact of full-page caching with a CSP nonce https://serverfault.com/a/1064775/66144:

Let's say you as an attacker are served the same nonce as your victim on a response to the URL /foo/bar. Now you could use this nonce in your XSS payload. Let's consider two of the most common XSS scenario's:
- URL parameter based reflected XSS: /foo/bar?payload=... will likely have a different cache key than /foo/bar, therefore causing the user to be delivered a fresh response with a new nonce. The attack fails.
- Stored XSS in dynamic HTML: your payload is now included when the user loads /foo/bar. However, if the user refreshes and gets a response from the cache, then this won't include your injected XSS payload. Alternatively, if they get a fresh response they will also get a fresh nonce. In either case the attack fails.

Now, this doesn't mean that this situation can never be exploited: for example, if /foo/bar has vulnerable JavaScript that modifies the DOM in a way that the attacker payload can be injected it might possible to use the cached nonce. Think of DOM based XSS attacks via data in the # segment of a URL or in AJAX responses.

It will be much trickier for an attacker to exploit the latter situation though, which may be sufficient since the point of CSP is to just provide defense-in-depth; it can not guarantee immunity for 100% of XSS attacks.

For Drupal, that means to not use AJAX responses to inject unsanitized markup, from user provided data, containing an inline script with a nonce attribute. This would also only be an effective attack against anonymous users on a single page for the duration of the calling page's cache lifetime, and other pages that receive the injected inline script with a nonce (and the original page when it's re-rendered with a new nonce) will send a violation report that should prompt investigation to address the underlying markup injection.

(AddJsCommand for adding new script files to the page through AJAX does not (currently) propagate the page's nonce to the new scripts, so they must be permitted by the originating page's policy through another source like 'self'.)

The CSP module includes a test that authenticated users receive a unique nonce for each request of a page that is cacheable in the dynamic page cache.

----

I've seen an approach where an edge cache worker handles replacing a placeholder value from the application, so that even responses served from the cache receive a unique nonce. But if the worker fails then responses are receiving a truly static value for all requests, and some examples I've seen have used a potentially predictable placeholder value such that markup injection would also be replaced with a valid nonce.
This would be possible with the CSP module by swapping out the Nonce service to one that responds with a static nonce value that includes some secret shared between the application and edge cache.

🇨🇦Canada gapple

Removed "Define accepted keys" option from summary, update how CSP now uses #attached.

Slightly different title; "Don't prevent modules from using #attached for additional data" would mean the same thing.

🇨🇦Canada gapple

- I'm not sure if this could be done entirely in csp.schema.yml by directives extending/overriding the basic constraints in the csp_directive_source_list schema, or would need a custom validator.
- Would a custom validator receive context of the parent config item, in order to be able to filter the list of valid flags?

🇨🇦Canada gapple

There's some additional validation constraints that are useful:
- The reporting plugin id
- Required / optional mapping keys

Some possible future enhancements:
- Only permit the 'flags' property on relevant directives
- Validate the 'flags' values permitted for the respective directive
- Validate directives sequence keys

🇨🇦Canada gapple

Being fixed in one merge request on parent issue.

🇨🇦Canada gapple

Being fixed in one merge request on parent issue

🇨🇦Canada gapple

Rebased.

CSP is now working around core by decorating the core attachments processor service, but it would be nice to not have to do this, since it also requires any module implementing CSP's new options to do a moduleExists() check.

🇨🇦Canada gapple

- Squashed and rebased
- Draft Change Record created
- Postponed issue for 12.x created 📌 [12.x] Set default Content-Security-Policy in services.yml Postponed

I'm not sure why tests are failing on ImageStylesPathAndUrlTest:L315

Remaining questions:
- Service parameter name: http.response.content_security_policy (like http.response.debug_cacheability_headers) or csp.config (like cors.config) or ?
- Should any X-Frame-Options header present on a response be removed, since browsers will ignore it when CSP is present?
- Review additional directives to add by default: script-src * 'unsafe-inline'; object-src 'none'

🇨🇦Canada gapple

I'm not sure about best practices, but I do have thoughts :)

Ideally, other modules use CSP's APIs so that site builders, or anyone else, just needs to enable the module and the site's policy will be updated as needed for the module's functionality to work. CSP handles any adjustments for core, but shouldn't take on the responsibility for every other contrib module or hosting platform.
It's definitely a challenge that every site may need a pretty bespoke policy for its functionality (and the dev/support team's capacity for monitoring and managing its strictness).

A lot of cases for scripts and styles are handled transparently by parsing library info, but more complex cases or non script/style sources will currently need to implement an alter subscriber (e.g. Google Tag Manager / Google Analytics, which uses a loader script and can use a nonce, and also needs to modify img-src and connect-src [ Merge Request pending on google_tag Support Content Security Policy Needs review ]; or Google Fonts, where a local CSS file needs an external domain included in font-src).
The render attached info should enable supporting some cases in a more direct way than an alter subscriber, and some more cases for libraries would be supported if/when Enable specifying additional directives in library definitions Active is implemented.

If someone's implementing a custom module instead of a public contrib module, then I'm not particularly worried. I assume by them implementing a CSP policy they'll know to make necessary policy modifications, and they can use the contrib module's subscriber as a reference.

There's a possibility of another contrib module that extends CSP's config form with a new tab that has checkboxes to enable policy modifications for additional services that are used without a module, but that could get fairly long and messy for a lot of services that any particular site is not going to use.

There was a GitHub repo some time ago that documented the directives required for a lot of different services - I'll have to search if it still exists and is up to date. If there isn't a good reference somewhere else, a page could be added to the module's documentation for services commonly used on Drupal sites, and then site builders could choose to apply the changes in their configuration or a custom subscriber according to their preference (and anyone can contribute new services or changes to the documentation).

----

Where the policy values are static and global (and the config form could be disabled so it's not used), adding them using config overrides in settings.php would also be an option, and would make it clearer that the base value is enabled too (so, e.g., img-src data: isn't enabled without 'self' when uncommented).

🇨🇦Canada gapple

An option could be for libraries to specify if they should be a conditional include, so that their sources are only added when the library is present on the page instead of the current behaviour of always being added on every request. This would be one method to resolve the issue where a module may have optional libraries that are only included when a certain feature is enabled (e.g. IIRC webform has some libraries with external domains that are not used by default).

🇨🇦Canada gapple

The webrtc directive is defined in the CSP spec, but is not yet implemented by all browsers. The message is only displayed in the browser console, and it does not send a violation report if you have configured a reporting option.
https://www.w3.org/TR/CSP3/#directive-webrtc

The module config form defaults to 'block' when enabled, but if the directive is not yet supported by a browser (or not present in the policy), then webrtc connections are allowed by the browser by default (webrtc 'allow' is explicit, but functionally the same as omitting the directive). Nothing you can do about that, but if you're not using webrtc and want browsers to block it when they add support, you can enable the directive with 'block' now.

🇨🇦Canada gapple

@defcon0 the theme hook is a relatively new addition specifically for themes, since they can't register a subscriber for the long-available Policy Alter event for modules.

I've done documentation updates alongside the 2.x releases to enumerate the options for dynamically altering the policy: https://www.drupal.org/docs/extending-drupal/contributed-modules/contrib...
I personally learn best from functional examples, and the CSP module provides multiple examples by using the alter event itself.

🇨🇦Canada gapple

Changing status from "needs work" to "no known problems, since 2.0.0 is released.

🇨🇦Canada gapple

Thanks for testing out the new feature :)

That looks right. IIRC, hook_page_attachments is called after the page contents are rendered and all the metadata is bubbled up. html_head is then rendered separately by the attachments processor without bubbling.

----

Won't be an issue until something else uses csp_nonce with a fallback that's not 'unsafe-inline', but the fallback value should be an array so it can be merged.
$attachments['#attached']['csp_nonce']['script'][] = Csp::POLICY_UNSAFE_INLINE;

🇨🇦Canada gapple

From the 17.20 InnoDB memcached Plugin documentation page:

The InnoDB memcached plugin was removed in MySQL 8.3.0, and was deprecated in MySQL 8.0.22.

🇨🇦Canada gapple

Fix attached nonce placeholder code example

🇨🇦Canada gapple

*sigh*
One day core will run its tests with script-src 'self'; style-src 'self'...

If CSP is going to have to replace that JS file in the library with its own version that applies a nonce, then it can also add a dependency on drupalSettings.

🇨🇦Canada gapple

Attaching policy to render elements is now available in a 2.1.0-beta1 release, and provides a mechanism to attach a nonce with a placeholder lazy builder so that the element can be cached and still receive a new nonce value on each request.

https://www.drupal.org/docs/extending-drupal/contributed-modules/contrib...

🇨🇦Canada gapple

D11 is released, so I think this is fully resolved 🙂

🇨🇦Canada gapple

I prefer the not-needle version 🙂, but the book and shield alone don't seem very representative or informative of the module's purpose.

The most notable feature of the module is preventing Cross Site Scripting vulnerabilities, but I've lately been thinking of it more broadly as a form of firewall which filters allowable content (external assets / requests) for a site.

🇨🇦Canada gapple

Enumable things
- Directives (default-src, script-src)
- Directive Schemas (source-list, ancestor-source-list, token-list)
- Keywords ('self', 'none')

Function type hints may cause some problems, where they're currently typehinted to string, and would need to change to string|enum.
2.x could accept both where possible, and translate to strings where necessary. 3.x can widen type hints to string|enum, 4.x could narrow them to enum where appropriate.

🇨🇦Canada gapple

Allow CSP to be added by render elements Needs review has been merged and will appear in CSP 2.1.0

This needs some work to function with the changes in that issue, and could be added in 2.2.0. (I'm hoping for some community feedback on the attached functionality before building more on top of it).

🇨🇦Canada gapple

Note that element directives may not appear in policy if not enabled in config

🇨🇦Canada gapple

Render element attached properties in 2.1.0

🇨🇦Canada gapple

Feature has been merged; Changing status to Needs Work for writing a Change Notice and updating documentation.
I'll probably do a 2.1.0-beta1 release with some other changes after those are complete.

Minimum version has been bumped to 10.1, in order to use the TrustedCallback attribute.

Opened some additional issues for other changes that were in the original merge request, to be added to future releases
🌱 Use Autowire & Autoconfigure for services Active
🌱 Use Enums Active

🇨🇦Canada gapple

Your comment is correct.
Just make sure that your additional JS elements aren't being cached in the dynamic page cache if they're being added by something more granular then hook_preprocess_page(), so that they receive the new nonce value each time.

2.1 should make this easier when it's released, by attaching information to the relevant render element and providing a placeholder for the nonce value Allow CSP to be added by render elements Needs review

Production build 0.71.5 2024