managing-tauri-plugin-permissions
npx skills add https://github.com/beshkenadze/claude-code-tauri-skills --skill managing-tauri-plugin-permissions
Agent 安装分布
Skill 文档
Managing Tauri Plugin Permissions
Tauri’s capability and permission system provides granular security control for desktop and mobile applications. This skill covers configuring capabilities for windows and platforms, using plugin permissions effectively, and writing custom plugin permissions.
Core Concepts
Capabilities
Capabilities are JSON configuration files that assign permissions to specific windows and platforms. They follow the principle of least privilege.
Location: src-tauri/capabilities/
Structure:
{
"identifier": "capability-name",
"description": "Human-readable purpose",
"local": true,
"windows": ["window-label"],
"permissions": ["plugin:allow-action"],
"platforms": ["linux", "windows", "macos", "android", "ios"]
}
Permission Levels
Permissions operate at two levels:
- Commands: Individual operations (e.g.,
allow-write-text-file) - Scopes: Path-based restrictions defining accessible files/directories
Platform-Specific Capabilities
Targeting Platforms
Restrict capabilities to specific operating systems using the platforms field:
{
"identifier": "desktop-fs-access",
"description": "Filesystem access for desktop platforms",
"windows": ["main"],
"permissions": ["fs:allow-home-read"],
"platforms": ["linux", "windows", "macos"]
}
Available platforms: linux, windows, macos, android, ios
Mobile-Only Capabilities
{
"identifier": "mobile-camera",
"description": "Camera access for mobile devices",
"windows": ["main"],
"permissions": ["camera:allow-capture"],
"platforms": ["android", "ios"]
}
Window-Specific Capabilities
Configuring Multiple Windows
Define windows in tauri.conf.json:
{
"windows": [
{
"label": "main",
"title": "Main Window",
"width": 800,
"height": 600
},
{
"label": "settings",
"title": "Settings",
"width": 400,
"height": 300
}
]
}
Assigning Capabilities to Windows
Create separate capability files for each window’s needs:
src-tauri/capabilities/main-window.json:
{
"identifier": "main-window-capabilities",
"description": "Full access for main window",
"local": true,
"windows": ["main"],
"permissions": [
"fs:allow-home-read",
"fs:allow-home-write",
"dialog:allow-open",
"dialog:allow-save"
]
}
src-tauri/capabilities/settings-window.json:
{
"identifier": "settings-window-capabilities",
"description": "Limited access for settings window",
"local": true,
"windows": ["settings"],
"permissions": [
"fs:allow-app-read",
"fs:allow-app-write"
]
}
Shared Capabilities Across Windows
{
"identifier": "shared-dialog",
"description": "Dialog access for multiple windows",
"local": true,
"windows": ["main", "settings"],
"permissions": ["dialog:allow-ask", "dialog:allow-message"]
}
Using Plugin Permissions
Default Permission Sets
Every plugin provides a default permission set with baseline access. Enable it with:
{
"permissions": ["plugin-name:default"]
}
Finding Available Permissions
- Official plugins: Check Tauri documentation’s permission tables
- Plugin source: Look in
permissions/autogenerateddirectories - Community plugins: Check repository or crates.io page
Permission Identifier Format
plugin-name:permission-name
Examples:
fs:allow-readfs:allow-write-text-filedialog:allow-openshell:allow-spawn
Configuring with Scopes
Restrict permissions to specific paths:
{
"identifier": "default",
"description": "Main window capabilities",
"windows": ["main"],
"permissions": [
"fs:allow-write-text-file",
{
"identifier": "fs:allow-read",
"allow": [{ "path": "$HOME/Documents/**" }]
},
{
"identifier": "fs:allow-write",
"allow": [{ "path": "$APP/**" }]
}
]
}
Common Scope Variables
| Variable | Description |
|---|---|
$APP |
Application data directory |
$HOME |
User home directory |
$RESOURCE |
Application resources |
$TEMP |
Temporary directory |
$DESKTOP |
User desktop |
$DOCUMENT |
User documents |
$DOWNLOAD |
User downloads |
Deny Permissions
Explicitly deny specific operations:
{
"permissions": [
"fs:default",
"fs:deny-write-text-file"
]
}
Writing Custom Plugin Permissions
Plugin Structure
Create a plugin with the Tauri CLI:
cargo tauri plugin new my-plugin
cd tauri-plugin-my-plugin
Implementing Commands
src/commands.rs:
use tauri::{command, AppHandle, Runtime};
#[command]
pub(crate) async fn read_data<R: Runtime>(
key: String,
app: AppHandle<R>,
) -> Result<String, String> {
// Implementation
Ok(format!("Data for key: {}", key))
}
#[command]
pub(crate) async fn write_data<R: Runtime>(
key: String,
value: String,
app: AppHandle<R>,
) -> Result<(), String> {
// Implementation
Ok(())
}
#[command]
pub(crate) async fn delete_data<R: Runtime>(
key: String,
app: AppHandle<R>,
) -> Result<(), String> {
// Implementation
Ok(())
}
Auto-Generating Permissions
src/build.rs:
const COMMANDS: &[&str] = &["read_data", "write_data", "delete_data"];
fn main() {
tauri_plugin::Builder::new(COMMANDS)
.global_api_script_path("./api-iife.js")
.build();
}
This generates:
allow-read-data/deny-read-dataallow-write-data/deny-write-dataallow-delete-data/deny-delete-data
Defining Default Permissions
permissions/default.toml:
"$schema" = "schemas/schema.json"
[default]
description = "Default permissions for my-plugin. Allows read operations only."
permissions = ["allow-read-data"]
Creating Permission Sets
permissions/read-write.toml:
"$schema" = "schemas/schema.json"
[[set]]
identifier = "read-write"
description = "Allows both read and write operations"
permissions = ["allow-read-data", "allow-write-data"]
permissions/full-access.toml:
"$schema" = "schemas/schema.json"
[[set]]
identifier = "full-access"
description = "Allows all operations including delete"
permissions = ["allow-read-data", "allow-write-data", "allow-delete-data"]
Registering Commands
src/lib.rs:
use tauri::{
plugin::{Builder, TauriPlugin},
Manager, Runtime,
};
mod commands;
pub fn init<R: Runtime>() -> TauriPlugin<R> {
Builder::new("my-plugin")
.invoke_handler(tauri::generate_handler![
commands::read_data,
commands::write_data,
commands::delete_data,
])
.build()
}
Frontend JavaScript Bindings
guest-js/index.ts:
import { invoke } from '@tauri-apps/api/core';
export async function readData(key: string): Promise<string> {
return await invoke('plugin:my-plugin|read_data', { key });
}
export async function writeData(key: string, value: string): Promise<void> {
return await invoke('plugin:my-plugin|write_data', { key, value });
}
export async function deleteData(key: string): Promise<void> {
return await invoke('plugin:my-plugin|delete_data', { key });
}
Using Custom Plugin Permissions
In your application’s capability file:
{
"identifier": "default",
"windows": ["main"],
"permissions": [
"my-plugin:default",
"my-plugin:read-write",
"my-plugin:allow-delete-data"
]
}
Complete Example: Cross-Platform App
src-tauri/capabilities/desktop.json:
{
"$schema": "../gen/schemas/desktop-schema.json",
"identifier": "desktop",
"windows": ["main"],
"platforms": ["linux", "windows", "macos"],
"permissions": [
"core:default",
"fs:default",
{ "identifier": "fs:allow-read", "allow": [{ "path": "$HOME/Documents/**" }] },
{ "identifier": "fs:allow-write", "allow": [{ "path": "$APP/**" }] },
"dialog:allow-open",
"dialog:allow-save",
"shell:allow-open"
]
}
src-tauri/capabilities/mobile.json:
{
"identifier": "mobile",
"windows": ["main"],
"platforms": ["android", "ios"],
"permissions": [
"fs:allow-app-read",
"fs:allow-app-write",
"notification:default"
]
}
Best Practices
Security
- Principle of least privilege: Grant only required permissions
- Use scopes: Restrict file access to specific paths rather than broad permissions
- Separate by window: Each window should have only the permissions it needs
- Platform targeting: Avoid granting mobile permissions on desktop and vice versa
Organization
- Organize by function: Group capabilities by feature area
- Use descriptive identifiers: Make capability purposes clear
- Document permissions: Include descriptions explaining why each permission is needed
Plugin Development
- Minimal defaults: Default permission sets should be restrictive
- Create permission sets: Offer tiered access levels (read-only, read-write, full)
- Use auto-generation: Let Tauri generate allow/deny permissions for commands
- Test permissions: Verify permission behavior with example applications
Troubleshooting
Permission Denied Errors
If you encounter permission errors:
- Check capability file syntax (valid JSON)
- Verify the window label matches your configuration
- Confirm the permission identifier is correct
- Check if a scope is required for path-based operations
Capability Not Applied
- Ensure capability files are in
src-tauri/capabilities/ - Verify the
windowsarray contains the correct window labels - Check
platformsincludes your target OS - Rebuild the application after capability changes