Implement a "semi automatic" Nonce settings

Created on 20 October 2021, almost 3 years ago
Updated 27 July 2023, about 1 year ago

Problem/Motivation

When using inline JS scripts or CSS the directive script-src requires the 'unsafe-inline' value, which flags the CSP verification as an error:

This can be addressed by :
1 - Removing the 'unsa-inlline' - which in a lot cases it's not possible (example: facebook's pixel)
2 - Implement a sha-X hash - this has the drawback of having to recalculate the hash every time there's a change in the script source file.
3 - implement the 'nonce-BASE64' - Best case scenario (at least in my opinion) since it can per site. So you have a base 64 hash that is defined in the header, applied to any

tag so CSP knows it's a legitimate call.

Steps to reproduce

Access any CSP validation tool (https://observatory.mozilla.org/analyze/ for example) and check if the nonce implementation is correct.

Proposed resolution

In the module - Add a check box: "Use nonce" - Add a field: "Nonce hash" - If the option is checked, add the nonce Hash value to all script tags (using a hook?) and to the CSP directive.

Remaining tasks

- Add a check box: "Use nonce" - Add a field: "Nonce hash" - A hook alter to add the nonce hash to all script tags

User interface changes

Module settings page Add a check box: "Use nonce" Add a field: "Nonce hash"

API changes

Data model changes

Feature request
Status

Needs work

Version

2.0

Component

Miscellaneous

Created by

🇧🇷Brazil barone Belo Horizonte

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Comments & Activities

Not all content is available!

It's likely this issue predates Contrib.social: some issue and comment data are missing.

  • Open in Jenkins → Open on Drupal.org →
    Core: 10.0.7 + Environment: PHP 7.3 & MySQL 5.7
    last update about 1 year ago
    Composer error. Unable to continue.
  • 🇦🇺Australia larowlan 🇦🇺🏝.au GMT+10

    This works in my testing.

    It adds a new pre render callback to any #type => html_tag elements that are of #tag script.

    Turn it on with a checkbox.

    Uses a lazy builder so its render cache safe

    Adds an update hook and test coverage as well

  • 🇦🇺Australia larowlan 🇦🇺🏝.au GMT+10

    Please credit @dpi who came up with the element_info_alter idea

  • 🇦🇺Australia dpi Perth, Australia

    mcdruid credited dpi .

  • 🇬🇧United Kingdom mcdruid 🇬🇧🇪🇺

    Per chat with @larowlan this looks good to me at glance, but will ask @Rajeshreeputra for a proper review as they've volunteered to help maintain seckit ( 💬 Offering to maintain Security Kit Active ).

  • Assigned to Rajeshreeputra
  • Issue was unassigned.
  • 🇦🇺Australia dpi Perth, Australia

    Thanks, good to see this can be automated for third parties that participate in attaching scripts consistently with html_tag.

  • 🇦🇺Australia dpi Perth, Australia

    Sorry about the unassign, must be a stale form^

  • Assigned to Rajeshreeputra
  • Status changed to Needs work about 1 year ago
  • 🇮🇳India Rajeshreeputra Pune

    Patch applied cleanly:

    On existing site and ran database update I can see option to enable Nounce under CSP.

    Enabled the nounce and verified same it work as expected.

    Overall changes looks good, the only weird thing noticed is:

    +
    /**
    + * Implements hook_form_FORM_ID_alter().
    + */
    +function seckit_test_form_seckit_settings_form_alter(array &$form, FormStateInterface $form_state, string $form_id): void {
    +  $form['test_script'] = [
    +    '#type' => 'html_tag',
    +    '#weight' => 50,
    +    '#tag' => 'script',
    +    '#attributes' => ['id' => 'testScript'],
    +    '#value' => Markup::create('console.log("👋");'),
    +  ];
    +}
    

    '#value' => Markup::create('console.log("👋");'), - this special characters in console log.

  • Status changed to RTBC about 1 year ago
  • 🇦🇺Australia dpi Perth, Australia

    Special characters look like a good sanity test to make sure things aren't encoded oddly / hashed correctly.

  • 🇦🇺Australia larowlan 🇦🇺🏝.au GMT+10

    Yep, that's just test code, only used in the test
    Happy to change it to any other inline JS

  • 🇨🇦Canada gapple

    Adding a nonce to every inline script html_tag element gives me some concern, compared to requiring an attribute on the render element to specifically opt-in to having a nonce applied. I'm open to "it should be reasonable to assume that any content is sanitized / restricted from editing by non-privileged users / etc before being added to an html_tag element (and user's shouldn't be able to arbitrarily insert new html_tag elements)", but I'm wary of this feature being used to make warnings go away without exploring ways to address the root cause, and opening up unintended leniency in a site's policy.

    As more of a user knowledge or integration issue, adding a nonce to the policy will disable 'unsafe-inline' and block any other scripts that rely on it.
    While 9.5+ / 10.0+ no longer require 'unsafe-inline' for core/drupal.ajax to function, if any inline scripts are added to the page through a mechanism other than a html_tag element (e.g. directly in a theme template, or with a raw markup element), they would be blocked by the policy if a nonce is included.
    Any site continuing to use CKEditor 4 (from core in 9.x or contrib in 10.x) will break if this feature is used since CKE4 relies on inline attributes (which can't have a nonce applied).

  • Issue was unassigned.
  • 🇦🇺Australia geoffreyr

    @larowlan's patch works nicely for inline scripts, but to be able to use the 'strict-dynamic' directive, the nonce needs to be added to every script tag, not just inline JS. At some point I might take a crack at tweaking the patch to provide configuration for linked scripts as well, so we can harden our CSP config a bit further. That said, I'm probably missing something that's already out there that would make this work...

  • Open in Jenkins → Open on Drupal.org →
    Core: 9.5.x + Environment: PHP 8.1 & MySQL 8
    last update about 1 year ago
    2 fail
  • 🇬🇧United Kingdom mcdruid 🇬🇧🇪🇺

    This seems like it's a pretty decent implementation of the feature.

    Whether sites will actually want to use it is a somewhat different question; as with many aspects of CSP (and seckit's other features) it's hard to determine exactly what sane defaults should be; turning everything on will almost certainly break things.

    Seems like a useful addition to the toolkit that the module provides though.

  • Status changed to Needs work about 1 year ago
  • 🇬🇧United Kingdom mcdruid 🇬🇧🇪🇺

    Looks like 3x tests are failing for D9:

    • Drupal\Tests\seckit\Functional\SecKitTestCaseTest::testCspWithoutVendorPrefixes
    • Drupal\Tests\seckit\Functional\SecKitTestCaseTest::testCspWithCspVendorPrefix
    • Drupal\Tests\seckit\Functional\SecKitTestCaseTest::testCspWithWebkitCspVendorPrefix

    In each case, the new nonce is being added to the CSP but that's not what the assertion expects - e.g. the test got the following CSP header:

    "default-src *; script-src * 'nonce--8mf3Awmh4ut1257OFh-xWL-yGx8g65B'; object-src *; style-src *; img-src *; media-src *; frame-src *; frame-ancestors *; child-src *; font-src *; connect-src *; report-uri /subdirectory/report-csp-violation; upgrade-insecure-requests"
    

    ...but expected:

    "default-src *; script-src *; object-src *; style-src *; img-src *; media-src *; frame-src *; frame-ancestors *; child-src *; font-src *; connect-src *; report-uri /subdirectory/report-csp-violation; upgrade-insecure-requests" 
    

    So...

    1) Do we expect the nonce to appear like this within the header?

    2) If so, can we adjust these tests accordingly?

    FWIW it looks like a fluke that the nonce began with a dash in the example above resulting in two consecutive dashes, this wasn't the case in the other two test fails.

  • Open in Jenkins → Open on Drupal.org →
    Core: 10.0.7 + Environment: PHP 8.2 & MySQL 8
    last update about 1 year ago
    2 fail
  • Open in Jenkins → Open on Drupal.org →
    Core: 10.1.4 + Environment: PHP 8.2 & MySQL 8
    last update 6 months ago
    Patch Failed to Apply
Production build 0.71.5 2024