Tauri Permissions Configuration
This skill covers the Tauri v2 permission system for controlling frontend access to backend commands and system resources.
Permission System Overview
Permissions in Tauri are explicit privileges that grant or deny access to specific commands. They form the security boundary between frontend code and system resources.
Core Components
Component Purpose
Permission Defines access to specific commands
Scope Restricts commands to specific paths/resources
Capability Links permissions to windows/webviews
Identifier Unique name referencing a permission
Security Model
-
Frontend code cannot access commands without explicit permission
-
Deny rules always take precedence over allow rules
-
Permissions must be linked to capabilities to be active
-
Each window/webview can have different permissions
Permission Identifiers
Naming Convention
Format: <plugin-name>:<permission-type>
Pattern Example Description
<name>:default
fs:default
Default permission set
<name>:allow-<command>
fs:allow-read-file
Allow specific command
<name>:deny-<command>
fs:deny-write-file
Deny specific command
<name>:allow-<scope>
fs:allow-app-read
Allow with predefined scope
Identifier Rules
-
Lowercase ASCII letters only: [a-z]
-
Maximum length: 116 characters
-
Plugin prefixes (tauri-plugin- ) added automatically at compile time
Directory Structure
Application Structure
src-tauri/ ├── capabilities/ │ ├── default.json # Main capability file │ └── admin.toml # Additional capabilities ├── permissions/ │ └── custom-permission.toml # Custom app permissions └── tauri.conf.json
Plugin Structure
tauri-plugin-example/ ├── permissions/ │ ├── default.toml # Default permission set │ ├── autogenerated/ # Auto-generated from commands │ │ └── commands/ │ └── custom-scope.toml # Custom scopes └── src/ ├── commands.rs └── build.rs
Capability Configuration
Capabilities link permissions to windows and define what frontend contexts can access.
JSON Format (Recommended for Apps)
{ "$schema": "../gen/schemas/desktop-schema.json", "identifier": "main-capability", "description": "Main window permissions", "windows": ["main"], "permissions": [ "core:default", "fs:default", "fs:allow-read-text-file", { "identifier": "fs:allow-write-text-file", "allow": [{ "path": "$APPDATA/*" }] } ] }
TOML Format
"$schema" = "../gen/schemas/desktop-schema.json" identifier = "main-capability" description = "Main window permissions" windows = ["main"] permissions = [ "core:default", "fs:default", "fs:allow-read-text-file" ]
[[permissions]] identifier = "fs:allow-write-text-file" allow = [{ path = "$APPDATA/*" }]
Window Targeting
{ "identifier": "admin-capability", "windows": ["admin", "settings"], "permissions": ["fs:allow-write-all"] }
Use "*" to target all windows:
{ "windows": ["*"], "permissions": ["core:default"] }
Platform-Specific Capabilities
{ "identifier": "desktop-capability", "platforms": ["linux", "macOS", "windows"], "windows": ["main"], "permissions": ["fs:allow-app-read-recursive"] }
{ "identifier": "mobile-capability", "platforms": ["iOS", "android"], "windows": ["main"], "permissions": ["fs:allow-app-read"] }
Allow and Deny Lists
Basic Scope Configuration
{ "identifier": "fs:allow-read-file", "allow": [ { "path": "$HOME/Documents/" }, { "path": "$APPDATA/**" } ], "deny": [ { "path": "$HOME/Documents/secrets/" } ] }
Scope Variables
Variable Description
$APP
Application install directory
$APPCONFIG
App config directory
$APPDATA
App data directory
$APPLOCALDATA
App local data directory
$APPCACHE
App cache directory
$APPLOG
App log directory
$HOME
User home directory
$DESKTOP
Desktop directory
$DOCUMENT
Documents directory
$DOWNLOAD
Downloads directory
$RESOURCE
App resource directory
$TEMP
Temporary directory
Glob Patterns
Pattern Matches
Any file in directory
**
Recursive (all subdirectories)
*.txt
Files with .txt extension
Deny Precedence
Deny rules always override allow rules:
{ "permissions": [ { "identifier": "fs:allow-read-file", "allow": [{ "path": "$HOME/" }], "deny": [{ "path": "$HOME/.ssh/" }] } ] }
Plugin Permissions
Using Default Plugin Permissions
{ "permissions": [ "fs:default", "shell:default", "http:default", "dialog:default" ] }
Common Plugin Permission Patterns
Filesystem Plugin
{ "permissions": [ "fs:default", "fs:allow-read-text-file", "fs:allow-write-text-file", "fs:allow-app-read-recursive", "fs:allow-app-write-recursive", "fs:deny-default" ] }
HTTP Plugin
{ "permissions": [ "http:default", { "identifier": "http:default", "allow": [{ "url": "https://api.example.com/" }], "deny": [{ "url": "https://api.example.com/admin/" }] } ] }
Shell Plugin
{ "permissions": [ "shell:allow-open", { "identifier": "shell:allow-execute", "allow": [ { "name": "git", "cmd": "git", "args": true } ] } ] }
Directory-Specific Filesystem Permissions
Permission Access
fs:allow-appdata-read
Read $APPDATA (non-recursive)
fs:allow-appdata-read-recursive
Read $APPDATA (recursive)
fs:allow-appdata-write
Write $APPDATA (non-recursive)
fs:allow-appdata-write-recursive
Write $APPDATA (recursive)
fs:allow-home-read-recursive
Read $HOME (recursive)
fs:allow-temp-write
Write to temp directory
Custom Permission Definition
TOML Permission File
Create src-tauri/permissions/my-permission.toml :
[[permission]] identifier = "my-app:config-access" description = "Access to app configuration files" commands.allow = ["read_config", "write_config"]
[[scope.allow]] path = "$APPCONFIG/*"
[[scope.deny]] path = "$APPCONFIG/secrets.json"
Permission Sets
Group multiple permissions:
[[set]] identifier = "my-app:full-access" description = "Full application access" permissions = [ "my-app:config-access", "fs:allow-app-read-recursive", "fs:allow-app-write-recursive" ]
Auto-Generated Command Permissions
In plugin src/build.rs :
const COMMANDS: &[&str] = &["get_user", "save_user", "delete_user"];
fn main() { tauri_plugin::Builder::new(COMMANDS) .build(); }
This generates:
-
allow-get-user / deny-get-user
-
allow-save-user / deny-save-user
-
allow-delete-user / deny-delete-user
Default Permission Set
Create permissions/default.toml :
[default] description = "Default permissions for my-plugin" permissions = [ "allow-get-user", "allow-save-user" ]
Remote Access Configuration
Allow remote URLs to access Tauri APIs (use with caution):
{ "identifier": "remote-capability", "windows": ["main"], "remote": { "urls": ["https://*.myapp.com"] }, "permissions": [ "core:default" ] }
Security Warning: Linux and Android cannot distinguish iframe requests from window requests.
Configuration in tauri.conf.json
Reference capabilities by identifier:
{ "app": { "security": { "capabilities": ["main-capability", "admin-capability"] } } }
Or inline capabilities directly:
{ "app": { "security": { "capabilities": [ { "identifier": "inline-capability", "windows": ["*"], "permissions": ["core:default"] } ] } } }
Troubleshooting
Common Errors
"Not allowed on this command"
-
Verify command permission is in capability
-
Check scope includes the target path
-
Ensure capability targets correct window
Permission not found
-
Check identifier spelling (lowercase only)
-
Verify plugin is installed
-
Run cargo build to regenerate permissions
Debugging Permissions
-
Check generated schema: src-tauri/gen/schemas/
-
Review capability files load correctly
-
Verify window names match capability targets
-
Check deny rules are not blocking access
Best Practices
-
Principle of Least Privilege: Only grant permissions actually needed
-
Use Specific Scopes: Prefer $APPDATA/* over $HOME/**
-
Deny Sensitive Paths: Always deny access to .ssh , credentials, etc.
-
Separate Capabilities: Use different capabilities for different window types
-
Document Custom Permissions: Include clear descriptions
-
Review Plugin Defaults: Understand what default permissions grant
-
Platform-Specific Config: Use platform targeting for OS-specific needs