Read before touching the CSP, Tauri capabilities, credential storage or the agent endpoint. The wider picture (credential flow, network, destructive operation safeguards) is in ARCHITECTURE.md section 6.
SQLPilot uses Tauri's built-in protections plus a Content Security Policy set
in app.security of src-tauri/tauri.conf.json:
csp for release builds and devCsp for just dev.
Release builds (csp):
default-src 'self';
script-src 'self' 'unsafe-eval' blob:;
style-src 'self' 'unsafe-inline';
worker-src 'self' blob:;
connect-src ipc: http://ipc.localhost
Development (devCsp) is the same plus
connect-src http://localhost:* http://127.0.0.1:*, for the Vite dev server.
Keep the two in step: a directive added to one usually belongs in both.
| Directive | Value | Reason |
|---|---|---|
default-src |
'self' |
Baseline: all resources must come from the application package |
script-src |
'self' |
Loaded scripts must be bundled with the app |
script-src |
'unsafe-eval' |
Required by Monaco Editor's worker and dynamic module loading |
script-src |
blob: |
Needed for Monaco worker bootstrapping in the embedded webview |
style-src |
'self' |
Bundled stylesheets (Tailwind build) |
style-src |
'unsafe-inline' |
Inline styles for dynamic layout values (width/height calculations) |
worker-src |
'self' blob: |
Monaco's editor.worker, set up in src/main.tsx |
connect-src |
ipc: http://ipc.localhost |
Tauri IPC command channel |
connect-src |
http://localhost:* |
Dev only: the Vite dev server (devUrl is http://localhost:1420) |
connect-src |
http://127.0.0.1:* |
Dev only: local servers during development |
Release builds allow no loopback connect-src. The frontend makes no requests
to loopback; the agent endpoint is reached by the harness, not by the webview.
unsafe-eval: Monaco Editor is fundamental to the app. Its worker and dynamic module loading still require this directive. Don't try to "fix" it.unsafe-inlinefor styles: inline styles are used for dynamic layout values. Removing it would need every dynamic value pre-computed, moved to CSS custom properties, or nonce-injected at runtime.
This CSP protects against:
- XSS injecting external scripts (
default-src 'self') - Remote resource loading (images, fonts, stylesheets from untrusted CDNs)
- Inline XSS only partially:
unsafe-inlinestyles andunsafe-evalremain
It assumes:
- App dependencies come from trusted sources (npm and crates.io, with
npm audit,npm audit signaturesandcargo auditin CI) - Only the commands registered in
src-tauri/src/lib.rsare callable, and the window's plugin permissions are limited bysrc-tauri/capabilities/ - No untrusted user content is evaluated (no
eval(user_input))
Connection passwords and SSH secrets are stored in the OS credential store via
keyring-core (Windows Credential Manager, macOS Keychain, the Linux Secret
Service, with kernel keyutils as an in-memory fallback), never in SQLite, and never sent back to the frontend. Details:
ARCHITECTURE.md section 6.1.
The MCP endpoint (mas-mcp/src/endpoint.rs)
listens on 127.0.0.1 only, behind a bearer token kept in a 0600 file in the
data directory and rotatable from Tools → Agents…. Requests carrying an
Origin header are refused: no harness sends one, and it is what a
DNS-rebinding web page would need. Nothing is exposed to an agent until the
user shares a connection, columns whose names indicate credentials return no
values at any posture, and every agent write or schema change is approved in
SQLPilot's own window. Design: AI_INTEGRATION.md.
- Updater artifacts are signed during
tauri buildwithTAURI_SIGNING_PRIVATE_KEY, becausebundle.createUpdaterArtifactsis on. See RELEASING.md. - Windows artifacts are code-signed only when
WINDOWS_CERTIFICATEandWINDOWS_CERTIFICATE_PASSWORDare set. The workflow imports the certificate and writes its thumbprint into the build config at runtime, so the repository stores no machine-specific signing metadata. Without the secrets it skips signing. - macOS builds are produced but not signed or notarized.