Skip to content

feat: add Content-Security-Policy to the desktop webview (#171) - #177

Merged
thcp merged 1 commit into
mainfrom
fix/desktop-csp
Jun 3, 2026
Merged

thcp merged 1 commit into
mainfrom
fix/desktop-csp

Conversation

@thcp

@thcp thcp commented Jun 2, 2026

Copy link
Copy Markdown
Collaborator

Closes #171.

The desktop webview ran with csp: null while withGlobalTauri: true exposed the Tauri API — so any markup injection could reach Tauri commands. Adds a strict CSP as defense-in-depth (the actual XSS hole, #170, is already fixed).

Changes

  • FastAPI CSP header (app/main.py) — the main app (where the library/folder UI and the window.__TAURI__ surface live) is served by FastAPI at 127.0.0.1, so a response header is the effective policy there, not just tauri.conf.json. script-src 'self', no unsafe-inline/eval.
  • Removed inline JS — moved the inline <script> + 3 inline onclick handlers out of index.html into a new static/js/ui-chrome.js module so the strict policy doesn't break them.
  • Tauri setup-shell CSP (tauri.conf.json) — matching policy for the bundled desktop/ui shell (verified it has no inline scripts).

Policy notes

  • style-src keeps 'unsafe-inline' (the UI sets many inline style attributes — low risk).
  • connect-src 'self' https://api.github.com ipc: http://ipc.localhost — same-origin API/SSE, the update check, and Tauri IPC.
  • img-src … https: — remote YouTube/SoundCloud thumbnails.
  • withGlobalTauri kept — disabling it is a bigger refactor for marginal gain once Stored XSS through library folder names #170 + CSP are in.

Verification

  • Served HTML has no inline <script>/onclick left; CSP header confirmed on /.
  • Scanned app + vendor: no eval/new Function/Worker/wasm; the one URL.createObjectURL (vendor audio) is covered by media-src blob:.
  • node --check all JS, ruff clean.
  • ⚠️ Needs on-device check before merge: run the desktop app — confirm setup completes, the studio loads, playback/SSE work, Tauri calls (open link, save file) work, and there are no CSP violations in the WebView console. The plain-browser path can't exercise Tauri IPC / the setup shell.

The desktop webview ran with csp:null while withGlobalTauri exposed the
Tauri API, so any markup injection could reach Tauri commands. Add a strict
CSP as defense-in-depth:

- FastAPI sends a CSP response header (the main app — where the library/
  folder UI and the window.__TAURI__ surface live — is served by FastAPI at
  127.0.0.1, so the header is the effective policy there). script-src 'self'
  with no unsafe-inline/eval.
- Move the inline <script> + 3 inline onclick handlers out of index.html into
  a new static/js/ui-chrome.js module so the strict policy doesn't break them.
- Set a matching CSP for the bundled Tauri setup shell in tauri.conf.json.

Styles keep 'unsafe-inline' (the UI sets many style attributes); connect-src
allows same-origin API/SSE, the GitHub update check, and Tauri ipc:; img-src
allows https: for remote thumbnails. withGlobalTauri kept (disabling it is a
larger refactor for marginal gain once the XSS in #170 is fixed + CSP is on).
@thcp
thcp force-pushed the fix/desktop-csp branch from a3b9fd3 to 0b440bf Compare June 2, 2026 17:39
@thcp
thcp marked this pull request as ready for review June 3, 2026 06:12
@thcp
thcp merged commit d159429 into main Jun 3, 2026
@thcp
thcp deleted the fix/desktop-csp branch June 3, 2026 06:13
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.

Desktop webview has CSP off while global Tauri IPC is exposed

1 participant