tauri-impl-security

Installation
SKILL.md

tauri-impl-security

Quick Reference

Security Architecture (Tauri 2)

Layer Mechanism Configuration
Content Security Policy Restricts resource loading in webview app.security.csp in tauri.conf.json
Permissions Define which IPC commands are allowed/denied src-tauri/permissions/*.toml
Capabilities Bind permissions to specific windows src-tauri/capabilities/*.json
Scopes Restrict what data commands can access Within permission definitions
Isolation Pattern Separate IPC from frontend context app.security.pattern
Prototype Freeze Prevent prototype pollution app.security.freezePrototype

Tauri-Specific Protocols

Protocol Purpose CSP Directive
tauri: Internal protocol for serving frontend assets default-src
asset: / https://asset.localhost Access bundled resources and filesystem assets img-src, media-src
ipc: / http://ipc.localhost IPC communication between frontend and Rust connect-src

Critical Warnings

NEVER set csp to null in production -- this disables all content security restrictions, exposing the app to XSS and injection attacks.

NEVER use "windows": ["*"] with broad permissions -- this grants all windows identical access. ALWAYS use specific window labels.

NEVER set dangerousDisableAssetCspModification: true unless you fully understand that it removes automatic CSP nonce injection for asset loading.

NEVER grant shell:default without scope restrictions -- this allows arbitrary command execution. ALWAYS define explicit command scopes.

ALWAYS enable freezePrototype: true in production -- it prevents JavaScript prototype pollution attacks.

ALWAYS add capabilities for every plugin you install -- plugins do NOT automatically receive permissions.

ALWAYS define deny rules for sensitive paths (e.g., $HOME/.ssh/*) when granting filesystem access.


Essential Patterns

Pattern 1: Content Security Policy Configuration

{
  "app": {
    "security": {
      "csp": "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' asset: https://asset.localhost data:; font-src 'self' data:; connect-src ipc: http://ipc.localhost https://api.example.com; media-src 'self' asset: https://asset.localhost"
    }
  }
}

Common CSP directives for Tauri:

Directive Recommended Value Purpose
default-src 'self' Fallback for all resource types
script-src 'self' JavaScript sources
style-src 'self' 'unsafe-inline' Stylesheets (inline needed for most frameworks)
img-src 'self' asset: https://asset.localhost data: Image sources including asset protocol
font-src 'self' data: Font files
connect-src ipc: http://ipc.localhost IPC + any external APIs
media-src 'self' asset: https://asset.localhost Audio/video sources

Pattern 2: Security Settings Block

{
  "app": {
    "security": {
      "csp": "default-src 'self'; script-src 'self'",
      "freezePrototype": true,
      "dangerousDisableAssetCspModification": false,
      "assetProtocol": {
        "enable": true,
        "scope": ["$APPDATA/**", "$RESOURCE/**"]
      },
      "pattern": {
        "use": "brownfield"
      }
    }
  }
}
Property Description
freezePrototype Freezes Object.prototype to prevent pollution attacks
dangerousDisableAssetCspModification Disables automatic CSP nonce injection for the asset protocol
assetProtocol.enable Enable the asset: protocol for file access
assetProtocol.scope Glob patterns defining allowed asset paths
pattern.use "brownfield" (default) or "isolation"

Pattern 3: Permissions System

Permissions follow the naming convention:

  • <plugin>:default -- Default permission set
  • <plugin>:allow-<command> -- Allow a specific command
  • <plugin>:deny-<command> -- Deny a specific command

Defining custom permissions (src-tauri/permissions/my-commands.toml):

[[permission]]
identifier = "allow-read-file"
description = "Enables the read_file command"
commands.allow = ["read_file"]

[[permission]]
identifier = "deny-write-file"
description = "Blocks the write_file command"
commands.deny = ["write_file"]

Permission with scopes:

[[permission]]
identifier = "scope-home"
description = "Access to files in $HOME but not .ssh"

[[scope.allow]]
path = "$HOME/*"

[[scope.deny]]
path = "$HOME/.ssh/*"

Permission sets (bundle multiple):

[[set]]
identifier = "allow-home-read-extended"
description = "Read access + directory creation in $HOME"
permissions = [
    "fs:read-files",
    "fs:scope-home",
    "fs:allow-mkdir"
]

Pattern 4: Capabilities System

Capabilities tie permissions to specific windows. Files in src-tauri/capabilities/ are automatically enabled.

{
  "$schema": "../gen/schemas/desktop-schema.json",
  "identifier": "main-capability",
  "description": "Capability for the main window",
  "windows": ["main"],
  "permissions": [
    "core:path:default",
    "core:event:default",
    "core:window:default",
    "core:app:default",
    "core:resources:default",
    "core:menu:default",
    "core:tray:default"
  ]
}

Platform-specific capabilities:

{
  "$schema": "../gen/schemas/desktop-schema.json",
  "identifier": "desktop-capability",
  "windows": ["main"],
  "platforms": ["linux", "macOS", "windows"],
  "permissions": ["global-shortcut:allow-register"]
}

Remote URL access:

{
  "$schema": "../gen/schemas/remote-schema.json",
  "identifier": "remote-capability",
  "windows": ["main"],
  "remote": {
    "urls": ["https://*.tauri.app"]
  },
  "permissions": ["nfc:allow-scan"]
}

Pattern 5: Scope-Based Access Control

File system scopes:

{
  "permissions": [
    {
      "identifier": "fs:allow-read-file",
      "allow": [{ "path": "$APPDATA/**" }],
      "deny": [{ "path": "$APPDATA/secrets/**" }]
    }
  ]
}

HTTP URL scopes:

{
  "permissions": [
    {
      "identifier": "http:default",
      "allow": [{ "url": "https://api.example.com/*" }],
      "deny": [{ "url": "https://api.example.com/admin/*" }]
    }
  ]
}

Shell command scopes:

{
  "permissions": [
    {
      "identifier": "shell:allow-execute",
      "allow": [{
        "name": "exec-sh",
        "cmd": "sh",
        "args": ["-c", { "validator": "\\S+" }],
        "sidecar": false
      }]
    }
  ]
}

Pattern 6: Accessing Scopes in Rust Commands

use tauri::ipc::{CommandScope, GlobalScope};

#[tauri::command]
async fn scoped_command<R: tauri::Runtime>(
    command_scope: CommandScope<'_, ScopeEntry>,
    global_scope: GlobalScope<'_, ScopeEntry>,
) -> Result<(), String> {
    let allowed = command_scope.allows();
    let denied = command_scope.denies();
    // Validate access against scopes
    Ok(())
}

Windows URL Scheme Change (v2)

On Windows, production frontend files load from http://tauri.localhost instead of https://tauri.localhost. This resets IndexedDB, LocalStorage, and Cookies unless:

  • dangerousUseHttpScheme was enabled in v1
  • app.windows[].useHttpsScheme is set to true in v2

Dangerous Permissions Audit Checklist

Review these permissions carefully before granting:

Permission Risk Mitigation
shell:allow-execute Arbitrary command execution Define explicit command scopes with validators
fs:allow-write-file with broad scope Data destruction/exfiltration Restrict to $APPDATA or specific directories
http:default without URL scope Unrestricted network access Define allowed URL patterns
clipboard-manager:allow-read-text Read sensitive clipboard data Only grant when functionally required
"windows": ["*"] All windows get same permissions Use specific window labels
dangerousDisableAssetCspModification Removes CSP nonce protection Almost never needed

Isolation Pattern

The isolation pattern creates a separate execution context for the IPC bridge, preventing the frontend from directly accessing Tauri internals:

{
  "app": {
    "security": {
      "pattern": {
        "use": "isolation",
        "options": {
          "dir": "../isolation-app"
        }
      }
    }
  }
}

Use "brownfield" (default) for standard apps. Use "isolation" for apps loading untrusted third-party content.


Core Permissions (Built-in)

These require no plugin installation but still need explicit capability grants:

core:path:default
core:event:default
core:window:default
core:app:default
core:resources:default
core:menu:default
core:tray:default
core:window:allow-set-title
core:window:allow-close
core:window:allow-minimize
core:window:allow-maximize

Reference Links

Official Sources

Related skills
Installs
1
GitHub Stars
1
First Seen
Apr 2, 2026