Problem/Motivation

A nonce-based policy only works if the value in the Content-Security-Policy header is the same value printed in the nonce attribute of each inline <script>/<style> tag. The module generates a per-request nonce (csp.nonce) and can add it to the policy (PolicyHelper::appendNonce(), or #attached['csp_nonce']). Themes, however, have no supported way to print that nonce from a Twig template.

Proposed resolution

Add a Twig extension (csp.twig_extension) with a csp_nonce() function:

<script nonce="{{ csp_nonce('script') }}">...</script>
<style nonce="{{ csp_nonce('style', "'unsafe-inline'") }}">...</style>

The function returns a render array that:

  • prints the NonceBuilder placeholder, which is replaced with the current request's nonce for each response, and
  • attaches csp_nonce => [$directive => $fallback], so the nonce is added to script-src-elem/style-src-elem with the same fallback handling as other render elements. No policy alter subscriber is needed.

Because the render array bubbles its attachments like any other, it works inside render-cached blocks and on Dynamic Page Cache HITs. Each response gets a new nonce that matches the header.

The value must be printed directly ({{ csp_nonce(...) }}). It can't be passed through filters, concatenated, or set on an Attribute object.

Remaining tasks

User interface changes

API changes

Data model changes

Issue fork csp-3625595

Command icon 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

graber created an issue. See original summary.

graber’s picture

Assigned: graber » Unassigned
Status: Active » Needs review