Skip to content

[BUGFIX] Restore CKEditor with hash-based CSP configuration - #117

Merged
Kanti merged 1 commit into
mainfrom
bugfix/ckeditor-csp-hashes
Aug 4, 2026
Merged

[BUGFIX] Restore CKEditor with hash-based CSP configuration#117
Kanti merged 1 commit into
mainfrom
bugfix/ckeditor-csp-hashes

Conversation

@Kanti

@Kanti Kanti commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

Use nonce-based CSP behavior in edit mode so CKEditor can apply its required
inline styles. Keep hash-based policies unchanged outside the Visual Editor.

fixes #115

Use nonce-based CSP behavior in edit mode so CKEditor can apply its required
inline styles. Keep hash-based policies unchanged outside the Visual Editor.
@Kanti
Kanti force-pushed the bugfix/ckeditor-csp-hashes branch from c30fd95 to e0477a6 Compare July 30, 2026 09:47
@Kanti
Kanti merged commit 232f10e into main Aug 4, 2026
33 checks passed
@Kanti
Kanti deleted the bugfix/ckeditor-csp-hashes branch August 4, 2026 06:42
@p2media

p2media commented Aug 4, 2026

Copy link
Copy Markdown

Sry for my delayed response. I tested your branch, but I've got CSP violations in the currently descriped setup:

The originally proposed fix also relaxed StyleSrcElem and ScriptSrcElem in CKEditor edit mode. However, your version no longer included these two changes, but only the relaxation of StyleSrc/StyleSrcAttr. As a result, the inline TYPO3.settings bootstrap script (script-src-elem) dynamically injected by TYPO3 Core, as well as the <style> elements (style-src-elem) injected at runtime by CKEditor5, continued to be blocked by the CSP.

The fix doesn't work for my setup. :/

@Kanti

Kanti commented Aug 4, 2026

Copy link
Copy Markdown
Contributor Author

@p2media, what does your CSP configuration look like?
Have you changed the defaults for StyleSrcElem and ScriptSrcElem in your csp.yaml file?

I can't reproduce the need for the two changes. It would be great if you could provide all the necessary information so that I can reproduce the problem.

@p2media

p2media commented Aug 4, 2026

Copy link
Copy Markdown

@Kanti Take a look into my CSP.yaml. I don't think it's very special:
csp.yaml
Maybe something is not optimal?

My working solution

PolicyMutatedEventListener approach cannot work reliably by its nature because it intervenes too early in the CSP pipeline. That is the reason why I implemented a middleware to fix it for me.
RelaxCspForVisualEditorMiddleware.php

A deeper explanation or maybe analysis:

After PolicyMutatedEvent (and even PolicyPreparedEvent) have already been fired and the PolicyMutatedEventListener has set ‘unsafe-inline’, the hashes collected during rendering (DirectiveHashCollection, populated in PageRenderer::addCssInlineBlock()/addJsInlineCode() etc. for style-src-elem/script-src-elem) are additionally merged into the directive.

This is a serious issue because, according to the CSP specification, as soon as a directive contains a hash-source or nonce-source, the browser completely ignores ‘unsafe-inline’ in that exact directive — regardless of whether it is present there. Result: style-src-elem ‘self’ 'unsafe-inline' ‘sha256-...’ → The browser ignores ‘unsafe-inline’, and <style> elements injected by CKEditor5 at runtime—which cannot be hashed in advance — continue to be blocked.

Even the policyPreparedEvent() part of the listener, which sets useHash = false; useNonce = true in edit mode for TYPO3 ≥ 14, does not actually solve the problem: A <style> element dynamically injected by CKEditor has no nonce attribute, and as soon as nonce-... is present as the source, ‘unsafe-inline’ is also ignored.

Any solution based solely on PolicyMutatedEvent/Mutation is structurally unreliable because Policy::compile() may only add hash/nonce sources again during the final header construction (after the event). Only a rewrite of the already fully compiled Content-Security-Policy header (as RelaxCspForVisualEditorMiddleware does) can reliably prevent this, because it explicitly removes all hash/nonce sources from style-src-elem and script-src-elem and replaces them exclusively with ‘self’ 'unsafe-inline'.

So my suggested fix couldn't work, I didn't test it enough beforehand.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

PolicyMutatedEventListener doesn't actually relax the CSP for CKEditor5 in the frontend

2 participants