feat(csp): support CSP nonce on editor-injected style elements - #6811
Draft
Gxrvish wants to merge 2 commits into
Draft
feat(csp): support CSP nonce on editor-injected style elements#6811Gxrvish wants to merge 2 commits into
Gxrvish wants to merge 2 commits into
Conversation
The editor injects stylesheets at runtime, so a page served with a strict `style-src`/`style-src-elem` policy blocks them. Unlike scripts, styles have no `strict-dynamic` equivalent, so a nonce is the only way to allow them. Add a `cspNonce` editor config option and apply it to every `<style>` the editor creates: - `CanvasView` canvas style element. Moved out of the view template and created imperatively, so the nonce is set before the element enters the document. - `FrameView` frame base styles (`baseCss`/`frameStyle`/`canvasCss`/ `protectedCss`). - `CssRuleView`, which renders one `<style>` per CSS rule and is the main source of violations. - `CssRulesView` `@keyframes` grouping element. - `BrowserParserCss`, which round-trips CSS through a temporary `<style>` in `document.head` to reuse the browser parser. When blocked, `el.sheet` stays null and the parser silently returns no rules, so imported CSS was being dropped without any error under a strict policy. Nonces have to be in place before insertion, hence the shared `createStyleEl` and `setNonce` helpers in `utils/dom`. Out of scope: inline `style` attributes (governed by `style-src-attr`) and `<script>` elements appended to the canvas. The latter run today under `script-src 'strict-dynamic'`, and nonce-ing user-authored component scripts is a separate decision.
The editor builds most of its chrome by assigning HTML strings, so every
`style="..."` literal in a template is parsed as an inline style attribute and
blocked by a strict `style-src-attr` policy. `setAttribute('style', ...)` has
the same problem. CSSOM writes (`el.style.prop = value`) are not covered by
CSP, so they are the way to apply values only known at runtime.
Static styles move to utility classes, adding `gjs-pointer-events-all` and
`gjs-clear-float` next to the existing `gjs-hidden` and `gjs-no-pointer-events`:
canvas and frame tools, frame remove icon, modal collector, device add button
and the float clearers in the asset manager, file uploader, modal and style
manager.
Runtime values move to the CSSOM through a new `setStyleText` helper, which
applies a declaration string property by property. It splits only on top-level
`;`, so data URLs and quoted values survive, and it keeps `!important` and
custom properties: asset preview background, navigator indentation, style
manager layer preview, select option styles in the style and trait managers,
RTE action `style` attributes, the canvas iframe component and the color
picker swatches.
Elements whose visibility is toggled at runtime by resetting the inline
display keep using the CSSOM for their initial state, so the toggles still
work. The style manager clear button instead switches to toggling `gjs-hidden`,
since its update is debounced and a class avoids a flash on render.
Out of scope: the `style` attribute of user components (`ComponentView`), which
is the content the editor exists to author, and the SVG image placeholder,
which is serialized to a base64 data URL and governed by `img-src`. Both are
recorded in the allowlist of the new guard spec.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The editor injects stylesheets at runtime, so a page served with a strict
style-src/style-src-elempolicy blocks them. Unlike scripts, styles have nostrict-dynamicequivalent, so a nonce is the only way to allow them.Add a
cspNonceeditor config option and apply it to every<style>the editor creates:CanvasViewcanvas style element. Moved out of the view template and created imperatively, so the nonce is set before the element enters the document.FrameViewframe base styles (baseCss/frameStyle/canvasCss/protectedCss).CssRuleView, which renders one<style>per CSS rule and is the main source of violations.CssRulesView@keyframesgrouping element.BrowserParserCss, which round-trips CSS through a temporary<style>indocument.headto reuse the browser parser. When blocked,el.sheetstays null and the parser silently returns no rules, so imported CSS was being dropped without any error under a strict policy.Nonces have to be in place before insertion, hence the shared
createStyleElandsetNoncehelpers inutils/dom.Out of scope: inline
styleattributes (governed bystyle-src-attr) and<script>elements appended to the canvas. The latter run today underscript-src 'strict-dynamic', and nonce-ing user-authored component scripts is a separate decision.