Enable Tauri CSP and isolate HTML artifact iframes#188
Open
yoshibase wants to merge 1 commit into
Open
Conversation
The desktop shell has shipped with `app.security.csp: null` since the initial import (andrewyng#99). Any XSS in the webview could load remote script or open arbitrary connections — and the HTML artifact preview made that worse: its iframe used `sandbox="allow-scripts allow-same-origin"`, so agent-authored markup could reach `window.parent.__COWORKER_API_TOKEN__` and drive the local sidecar. Enable a production CSP shaped for this app: - connect-src allows Tauri IPC (`ipc:`, `http://ipc.localhost`) and the dynamically-chosen sidecar port (`http://127.0.0.1:*`, `ws://127.0.0.1:*`) - style-src keeps 'unsafe-inline' for React style={{…}} - worker-src / img-src allow blob: and data: for pdfjs and attachments - no remote connect, no unsafe-eval in production - a separate, looser devCsp so `tauri dev` still gets Vite HMR on :1420 And drop `allow-same-origin` from the artifact iframe. Scripts can still run for interactive previews; the frame gets a unique opaque origin, which is the actual XSS → tools fix. Parent CSP alone cannot contain a srcDoc iframe. Hermetic contract tests pin both: production/dev CSP shape, and the iframe sandbox tokens. CI does not boot a Tauri webview, so these assertions are what keeps the policy from regressing to null.
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.
Summary
Fixes #99.
The desktop shell has shipped with
app.security.csp: nullsince the initial import. Any XSSin the webview could load remote script or open arbitrary connections. The HTML artifact
preview made the practical exploit path worse: it used
so agent-authored markup in a
srcDociframe could reachwindow.parent.__COWORKER_API_TOKEN__and drive the local sidecar. Parent CSP alone cannot contain a
srcDociframe — that sandboxis the real XSS → tools fix.
What changed
Production CSP (object form in
tauri.conf.json), shaped for this codebase:connect-src…ipc:http://ipc.localhostwithGlobalTaurihttp://127.0.0.1:*ws://127.0.0.1:*free_port()→127.0.0.1:0at launch; a fixed port cannot workstyle-src 'self' 'unsafe-inline'style={{…}}worker-src 'self' blob:?urlimg-src … data: blob:unsafe-eval, no remotehttps:inconnect-srcconnect-srcdevCsp(mandatory): without it, Tauri injects the prod CSP intotauri devtoo, and ViteHMR on
localhost:1420dies. Dev allows'unsafe-eval'and the Vite HMR hosts; production doesnot.
Artifact iframe: drop
allow-same-origin. Scripts may still run for interactive previews;the frame gets a unique opaque origin, so it cannot read the parent token / SPA.
Honest scope note: a per-launch API token already gates the sidecar (
#28/#40lineage). CSPis defense-in-depth — especially against remote connect/script.
127.0.0.1:*still allows acompromised page to talk to any loopback port; pinning one port would require dropping
free_port(), which is out of scope here.Test plan
Hermetic contract tests (CI does not boot a Tauri webview):
They pin:
cspis non-null and contains IPC +127.0.0.1:*WS/HTTP wildcardsunsafe-eval/ no remotehttps:in prodconnect-srcdevCspis set and allows Vite HMR on:1420allow-scriptsand does not setallow-same-originManual smoke (please, before merge — CI will not catch webview CSP breakage):
cd surfaces/gui && npm run tauri devconnect-src)No new dependencies. Complementary to #170 (SSRF) and #92 (CORS) — those don't touch
tauri.confsecurity CSP.