fix(shell): nonce inline theme-restore script and code style under a nonce-based CSP#7
Merged
Merged
Conversation
…nonce-based CSP DocsUI::Shell emits an inline <script> (the theme-restore script) and DocsUI::Code emits an inline <style>. Neither carried a CSP nonce, so a host app enforcing a nonce-based script-src (Rails' default when script-src is in content_security_policy_nonce_directives) blocked them — the visible casualty being that the persisted theme never applied. Summary - Shell and Code now include Phlex::Rails::Helpers::ContentSecurityPolicyNonce and emit the inline tag with `nonce:` from a private #csp_nonce. - #csp_nonce guards on `view_context` before delegating to the phlex-rails value helper: in phlex-rails 2.4.0 the helper delegates to the view context (which is nil in an isolated render / a host without a nonce and would raise), so we return nil there. Phlex omits a nil-valued attribute, keeping the un-nonced markup byte-identical to before. - style-src often still allows 'unsafe-inline', but Code is nonced too for symmetry and future-proofing. Test Coverage - spec/docs_ui/shell_spec.rb (new): the theme-restore <script> renders the JS; with no nonce it carries NO nonce attribute; with a nonce it renders nonce="testnonce". Plus a focused proof that Phlex omits a nil-valued attribute (the graceful-degradation primitive). - spec/docs_ui/code_spec.rb: the inline <style> carries NO nonce with no context and nonce="testnonce" when present. - spec/spec_helper.rb loads phlex-rails (+ the two ActiveSupport core-exts it and the theme-restore script need) so DocsUI:: components that compose phlex-rails helpers render standalone. Verification - [x] bundle exec rspec — 55 examples, 0 failures (stable across seeds) - [x] bundle exec rubocop (app lib spec) — 31 files, no offenses - [x] No-nonce path is byte-identical (no nonce attribute emitted) Closes #2
This was referenced Jul 3, 2026
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.
Problem
DocsUI::Shellemits an inline<script>(the theme-restore script) andDocsUI::Codeemits an inline<style>— neither carried a CSP nonce. On a host app that enforces a nonce-basedscript-src(Rails' default whencontent_security_policy_nonce_directivesincludesscript-src), the browser blocks these inline tags. The visible casualty: the persisted theme never applied on first paint.Fix
DocsUI::ShellandDocsUI::Codenowinclude Phlex::Rails::Helpers::ContentSecurityPolicyNonceand emit their inline tag withnonce:from a small private#csp_nonce.#csp_nonceguards onview_contextbefore delegating to the phlex-rails value helper. In phlex-rails 2.4.0 thecontent_security_policy_noncehelper delegates to the view context — which isnilin an isolated render (or on a host that doesn't noncescript-src) and would otherwise raise — so we returnnilthere. Phlex omits anil-valued attribute, so the un-nonced markup stays byte-identical to before.style-srcoften still allows'unsafe-inline', butCode's inline<style>is nonced too, for symmetry and future-proofing.Graceful degradation is the whole point: on a host without a nonce, nothing changes; on a host with one, the tag carries it and the browser allows it.
Test plan
spec/docs_ui/shell_spec.rb(new): the theme-restore<script>renders the JS; with no nonce it carries nononceattribute; with a nonce it rendersnonce="testnonce". Plus a focused proof that Phlex omits anil-valued attribute (the primitive the fix relies on).spec/docs_ui/code_spec.rb: the inline<style>carries nononcewith no view context andnonce="testnonce"when a nonce is present.spec/spec_helper.rbloads phlex-rails (plus the two ActiveSupport core-exts it and the theme-restore script need) soDocsUI::components that compose phlex-rails helpers render standalone in the suite.Verification
bundle exec rspec— 55 examples, 0 failures (stable across seeds 1, 42, 999, and random).bundle exec rubocop app lib spec— 31 files, no offenses.nonceattribute is emitted when there is no CSP nonce, so existing consuming sites and all prior specs are unaffected.Closes #2