fix: Linux desktop app freeze — layered CSP with runtime port pinning#181
fix: Linux desktop app freeze — layered CSP with runtime port pinning#181
Conversation
roborev: Combined Review (
|
|
Thanks for looking at this. I'll have a closer look today on a Linux box and get this hardened and merged. |
roborev: Combined Review (
|
|
Trying a different approach, static CSP here is a problem. |
roborev: Combined Review (
|
roborev: Combined Review (
|
roborev: Combined Review (
|
|
Hmm, still not ready. Retesting |
roborev: Combined Review (
|
|
Now an issue between native dialogs and the webview on linux. Working on a fix. |
The Tauri CSP only allowed 'self' for script-src/default-src. After redirecting from tauri://localhost to the Go backend at http://127.0.0.1, the CSP blocked resources from the backend origin, causing the WebKitGTK webview to freeze on Linux. Add http://127.0.0.1:* to all CSP directives and include 'unsafe-inline'/'unsafe-eval' for scripts so the SPA can load and run after navigation to the backend. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…e frame-ancestors Remove 'unsafe-inline' and 'unsafe-eval' from script-src (not needed by Svelte/Vite production builds) and restore the frame-ancestors 'none' directive that was dropped in the previous commit. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
roborev: Combined Review (
|
The Tauri compile-time CSP must use http://127.0.0.1:* in default-src because the Go server port is unknown at build time. To prevent this wildcard from allowing script execution from arbitrary local ports, the Tauri CSP now sets an explicit `script-src 'self'` (no wildcard). A new Go-side cspMiddleware sets a port-pinned Content-Security-Policy header on all non-API responses. Since CSPs are additive (most restrictive wins), the runtime policy intersects with Tauri's broad default-src to narrow connect-src/default-src to the exact port. - Tauri CSP: explicit script-src 'self' (no wildcard port for scripts) - Tauri CSP: wildcard only in default-src and connect-src (needed for cross-origin page load and API/SSE access) - Go server: cspMiddleware as outermost handler wrapper pins exact port - Tests: verify CSP present on SPA routes, absent on API routes Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Address review feedback: cspMiddleware was using fmt.Sprintf to build origins, which produced invalid URIs for IPv6 (http://::1:8081) and wrong origins for bind-all mode (http://0.0.0.0:8081). - Use httpOrigin()/net.JoinHostPort for correct IPv6 bracketing - Mirror buildAllowedOrigins loopback logic for 0.0.0.0/:: hosts - Include publicOrigins with https->wss mapping for proxy/TLS setups - Add test cases for IPv6, bind-all, and public origin scenarios Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The previous commit removed the wildcard from script-src, img-src, style-src, and font-src in the Tauri CSP, causing the UI to freeze. Root cause: 'self' in the Tauri CSP resolves to tauri://localhost (the Tauri origin), NOT the Go server origin. After the webview navigates to http://127.0.0.1:{port}, resources served by the Go server are cross-origin from Tauri's perspective. Without http://127.0.0.1:* in each directive, WebKitGTK blocks scripts, styles, images, and fonts from the Go server. The wildcard port is unavoidable in the Tauri compile-time CSP. The Go server's runtime CSP (script-src 'self', where 'self' = http://127.0.0.1:8081) provides the port-pinned tightening via CSP intersection. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
WebKitGTK in a Tauri webview does not resolve 'self' to the Go server origin after navigating from tauri://localhost. Using only 'self' in script-src/default-src causes the UI to freeze because WebKitGTK blocks all resources from http://127.0.0.1:{port}. The pinned server origin (exact host:port, not a wildcard) is now included in all resource directives. Public origins and LAN IPs remain restricted to connect-src only, so the script execution surface is limited to the server's own origin. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
On Linux/WebKitGTK, dismissing a native GTK dialog (e.g. the auto-update confirmation) can leave the webview frozen — it renders but does not process input events. Fix by calling set_focus() on the main webview window in every dialog callback. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add Google Fonts CDN to style-src and font-src directives so the frontend can load web fonts. Remove unnecessary frame-ancestors directive. Set Tauri csp to null since the Go server handles CSP at runtime, avoiding double-policy conflicts. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
f1a901b to
ac090d4
Compare
roborev: Combined Review (
|
… focus restore - Restore restrictive compile-time CSP in tauri.conf.json with localhost and Google Fonts entries needed for WebKitGTK compatibility - Add frame-ancestors 'none' to runtime CSP middleware and X-Frame-Options: DENY as defense in depth against clickjacking - Delay webview focus restoration by 100ms after GTK dialog dismissal so the dialog fully releases focus before set_focus() fires Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
roborev: Combined Review (
|
|
Does the app, especially the desktop app use IPv6 anywhere between client and server? I can't find it binding to any ipv6 address. Seems like a false positive for the reviewing agent? |
|
The security reviewer is susceptible to false positives. You can halt here and let me take a look at this to get it merged, thanks for working on it |
Summary
tauri://localhostto the Go backend athttp://127.0.0.1:{port}cspMiddlewarethat sets a port-pinnedContent-Security-Policyheader on all non-API responses, narrowing Tauri's compile-time wildcard to the exact runtime portscript-src 'self'(no wildcard port) so scripts can only load from the app's own origin, addressing the security review concern about arbitrary local port trustHow the two CSP layers interact
default-src'self' http://127.0.0.1:*'self' http://127.0.0.1:8081'self' http://127.0.0.1:8081script-src'self''self' http://127.0.0.1:8081'self'connect-src'self' http://127.0.0.1:* ws://127.0.0.1:*'self' http://127.0.0.1:8081 ws://127.0.0.1:8081'self' http://127.0.0.1:8081 ws://127.0.0.1:8081Test plan
make test— Go tests pass including new CSP middleware tests🤖 Generated with Claude Code