"The capability system guards the bridge. The CSP guards the page itself — the layer where the injection happens in the first place."
Two Layers, Two Jobs
Capabilities decide what native powers the webview can reach. A Content Security Policy works one layer up: it tells the webview which scripts, styles, images, and connections are allowed to load inside the page at all. A good CSP blocks the classic XSS vector — an attacker injecting <script> or an inline onclick that the browser would otherwise happily run. Defense in depth: CSP makes injection hard, capabilities limit the damage if it happens anyway.
csp: null Is for Prototyping Only
The scaffold often sets "csp": null, which means 'no policy' — convenient while you iterate, but it ships zero XSS protection. Before release, set a real CSP in app.security.csp. The helpful part: Tauri automatically injects the hashes/nonces for your own bundled scripts and styles, so a strict policy doesn't break your app's legitimate code. You declare the policy; Tauri keeps your assets on the allowlist.
Start Strict, Open Only What You Need
Begin with the tightest policy that loads your app — default-src 'self' — then add exactly the sources you actually use: an API host under connect-src, a font CDN under font-src, the Tauri asset protocol under img-src if you load local files as images. Each directive you loosen is a door; open the specific ones your features need and no more. A strict CSP plus scoped capabilities is what 'secure Tauri app' concretely means.