Feature: #100887 - Prefer CSP hash values over nonce values 

See forge#100887

Description 

Content-Security-Policy nonce values are per-request random tokens that prevent HTTP response caching. By collecting hash values of assets at render time instead, responses can be cached (e.g. by lochmueller/staticfilecache or reverse proxies) while still enforcing a strict CSP.

Hash-based CSP is an explicit opt-in configured per site via csp.yaml. Nonce values remain the default when no behavior is configured.

New DirectiveHashCollection service 

The new \TYPO3\CMS\Core\Security\ContentSecurityPolicy\DirectiveHashCollection service is a per-request registry that collects CSP hash values for inline and static assets during page rendering.

Both inline content and static file resources are supported:

  • Inline assets: the SHA-256 hash is computed over the content that appears inside the <script> or <style> element.
  • Static assets: if an integrity attribute is already present, its value is reused; otherwise the file content is hashed on demand.
  • Style attributes: the new f:asset.styleAttr ViewHelper hashes inline style values and covers the style-src-attr directive.

The collected hashes survive the frontend page cache round-trip via \TYPO3\CMS\Frontend\Cache\MetaDataState .

Updated Behavior class 

\TYPO3\CMS\Core\Security\ContentSecurityPolicy\Configuration\Behavior now carries a second nullable boolean property $useHash:

  • true – explicitly enable hash collection and CSP hash sources.
  • null – off (the default); hashes are not collected or applied.
  • false – explicitly disabled.

Configuring behavior via csp.yaml 

Both $useNonce and $useHash can be set in a site's config/sites/<site>/csp.yaml under the top-level behavior: key:

behavior:
  useNonce: false
  useHash: true

enforce:
  inheritDefault: true
  includeResolutions: true
Copied!

Setting useHash: true enables hash-based CSP for that site. Setting useNonce: false removes nonce sources from the compiled policy, which is required for responses to be cacheable by reverse proxies.

Updated Policy::prepare() and Policy::compile() 

Both methods now accept a \TYPO3\CMS\Core\Security\ContentSecurityPolicy\Middleware\PolicyBag instead of separate ConsumableNonce, Behavior, and HashCollection arguments. The PolicyBag is forwarded directly from the CSP middlewares, making the hash collection visible to PSR-14 event listeners via PolicyPreparedEvent::$policyBag->directiveHashCollection.

The behavior resolution (applying collected hashes and suppressing nonce sources) now happens inside Policy::prepare().

New f:asset.styleAttr ViewHelper 

A new ViewHelper registers inline style values with the style-src-attr CSP directive:

<div style="{f:asset.styleAttr(value: 'color: green', csp: true)}"></div>
Copied!

The csp argument (default: true) controls whether the hash is collected.

Updated f:asset.script and f:asset.css ViewHelpers 

The useNonce argument has been renamed to csp (deprecated, see Deprecation: #100887 - Deprecation of useNonce argument in f:asset:css and f:asset:script view helpers). The new default is true for external files (static resources) and false for inline content.

<!-- static file: csp=1 by default, hash collected from file content -->
<f:asset.script identifier="my-script" src="EXT:my_ext/Resources/Public/JavaScript/foo.js" />

<!-- with integrity attribute: hash reused directly, no file read -->
<f:asset.script identifier="my-script"
    src="EXT:my_ext/Resources/Public/JavaScript/foo.js"
    integrity="sha256-abc123==" />

<!-- inline script: opt in explicitly -->
<f:asset.script identifier="my-inline" csp="1">
    document.querySelector('.foo').classList.add('active');
</f:asset.script>
Copied!

Migration 

The useNonce ViewHelper argument and 'useNonce' asset option key are deprecated and replaced by csp / 'csp'. See Deprecation: #100887 - Deprecation of useNonce argument in f:asset:css and f:asset:script view helpers.

The signature of Policy::prepare() and Policy::compile() has changed to accept a PolicyBag. Code calling these methods directly (they are @internal) must be updated.

Impact 

Sites that configure behavior.useHash: true (and optionally behavior.useNonce: false) in their csp.yaml can use hash-based CSP sources, which allows HTTP responses to be cached by reverse proxies and static-file-cache extensions without sacrificing Content-Security-Policy enforcement. Sites without this configuration continue to use nonce-based CSP.