fix(server): allow inline styles in CSP so web math renders on non-loopback binds - #1847
Conversation
…opback binds The security CSP fell back to default-src 'self' for styles, which strips the inline style attributes that KaTeX (injected via innerHTML) uses for all glyph positioning — formulas collapsed into overlapping characters on any non-loopback-served web UI. Shiki highlighting and Mermaid diagrams hit the same mechanism. Add style-src 'self' 'unsafe-inline'; scripts remain strictly restricted.
🦋 Changeset detectedLatest commit: f3aa87c The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: dd79ebbb53
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| await hook({} as never, reply as never, 'payload'); | ||
| const csp = headers.get('content-security-policy'); | ||
| expect(csp).toContain("style-src 'self' 'unsafe-inline'"); | ||
| expect(csp).not.toContain("script-src 'self' 'unsafe-inline'"); |
There was a problem hiding this comment.
Assert the effective policy that forbids inline scripts
This negative substring check does not prove the behavior named by the test. If the policy later becomes default-src 'self' 'unsafe-inline', both this assertion and the following default-src 'self' assertion still pass even though inline scripts are then allowed through fallback; explicit variants such as script-src 'unsafe-inline' also evade this exact substring. Parse the directives and assert that the effective script-src (or its default-src fallback) excludes 'unsafe-inline'.
Useful? React with 👍 / 👎.
commit: |
A negative substring check only rejects one exact string: default-src gaining 'unsafe-inline' (inline <script> allowed via fallback) or an explicit script-src 'unsafe-inline' would both slip through. Parse the directives and assert the effective script policy (script-src, falling back to default-src) excludes 'unsafe-inline'/'unsafe-eval'/data:.
|
Codex Review: Didn't find any major issues. Another round soon, please! Reviewed commit: ℹ️ About Codex in GitHubCodex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback". |
…opback binds (MoonshotAI#1847) * fix(server): allow inline styles in CSP so web math renders on non-loopback binds The security CSP fell back to default-src 'self' for styles, which strips the inline style attributes that KaTeX (injected via innerHTML) uses for all glyph positioning — formulas collapsed into overlapping characters on any non-loopback-served web UI. Shiki highlighting and Mermaid diagrams hit the same mechanism. Add style-src 'self' 'unsafe-inline'; scripts remain strictly restricted. * test(server): assert the effective script-src in the CSP regression test A negative substring check only rejects one exact string: default-src gaining 'unsafe-inline' (inline <script> allowed via fallback) or an explicit script-src 'unsafe-inline' would both slip through. Parse the directives and assert the effective script policy (script-src, falling back to default-src) excludes 'unsafe-inline'/'unsafe-eval'/data:.
…opback binds (MoonshotAI#1847) * fix(server): allow inline styles in CSP so web math renders on non-loopback binds The security CSP fell back to default-src 'self' for styles, which strips the inline style attributes that KaTeX (injected via innerHTML) uses for all glyph positioning — formulas collapsed into overlapping characters on any non-loopback-served web UI. Shiki highlighting and Mermaid diagrams hit the same mechanism. Add style-src 'self' 'unsafe-inline'; scripts remain strictly restricted. * test(server): assert the effective script-src in the CSP regression test A negative substring check only rejects one exact string: default-src gaining 'unsafe-inline' (inline <script> allowed via fallback) or an explicit script-src 'unsafe-inline' would both slip through. Parse the directives and assert the effective script policy (script-src, falling back to default-src) excludes 'unsafe-inline'/'unsafe-eval'/data:.
…opback binds (MoonshotAI#1847) * fix(server): allow inline styles in CSP so web math renders on non-loopback binds The security CSP fell back to default-src 'self' for styles, which strips the inline style attributes that KaTeX (injected via innerHTML) uses for all glyph positioning — formulas collapsed into overlapping characters on any non-loopback-served web UI. Shiki highlighting and Mermaid diagrams hit the same mechanism. Add style-src 'self' 'unsafe-inline'; scripts remain strictly restricted. * test(server): assert the effective script-src in the CSP regression test A negative substring check only rejects one exact string: default-src gaining 'unsafe-inline' (inline <script> allowed via fallback) or an explicit script-src 'unsafe-inline' would both slip through. Parse the directives and assert the effective script policy (script-src, falling back to default-src) excludes 'unsafe-inline'/'unsafe-eval'/data:.
Related Issue
N/A — clear, reproducible bug with a focused fix; the problem is explained below.
Problem
When the server binds a non-loopback address (web UI accessed over LAN or a reverse proxy), LaTeX formulas in the chat render as garbled, overlapping characters.
Root cause: the security CSP sent on non-loopback binds is
default-src 'self'; …with nostyle-src, so style handling falls back todefault-src 'self'and the browser strips inlinestyle="…"attributes from injected markup. KaTeX output (rendered by the markdown renderer and injected via innerHTML) carries essentially all glyph positioning — vertical stacking, offsets, delimiter sizing — in inline style attributes (a single fraction formula contains ~68 of them), so formulas collapse into overprinted glyphs. Shiki code highlighting (inline colors) and Mermaid diagrams (inline<style>in the SVG) are degraded by the same mechanism. Loopback binds get no CSP header at all, which is why local development never surfaces this.What changed
style-src 'self' 'unsafe-inline'to the non-loopback CSP. Only styles are relaxed — script execution stays strictly restricted — which is the standard CSP posture for generated markup such as KaTeX/Shiki/Mermaid output. This restores math rendering, code-highlight colors, and Mermaid styling on network-served deployments.Checklist
gen-changesetsskill, or this PR needs no changeset.gen-docsskill, or this PR needs no doc update.