Guides the user through configuring Tauri permissions, including the security permission system, allow and deny lists, plugin permissions, permission identifiers, scopes, and capability integration.
Scanned 2/12/2026
Install via CLI
openskills install dchuk/claude-code-tauri-skills---
name: configuring-tauri-permissions
description: Guides the user through configuring Tauri permissions, including the security permission system, allow and deny lists, plugin permissions, permission identifiers, scopes, and capability integration.
---
# 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)
```json
{
"$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
```toml
"$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
```json
{
"identifier": "admin-capability",
"windows": ["admin", "settings"],
"permissions": ["fs:allow-write-all"]
}
```
Use `"*"` to target all windows:
```json
{
"windows": ["*"],
"permissions": ["core:default"]
}
```
### Platform-Specific Capabilities
```json
{
"identifier": "desktop-capability",
"platforms": ["linux", "macOS", "windows"],
"windows": ["main"],
"permissions": ["fs:allow-app-read-recursive"]
}
```
```json
{
"identifier": "mobile-capability",
"platforms": ["iOS", "android"],
"windows": ["main"],
"permissions": ["fs:allow-app-read"]
}
```
## Allow and Deny Lists
### Basic Scope Configuration
```json
{
"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:
```json
{
"permissions": [
{
"identifier": "fs:allow-read-file",
"allow": [{ "path": "$HOME/**" }],
"deny": [{ "path": "$HOME/.ssh/**" }]
}
]
}
```
## Plugin Permissions
### Using Default Plugin Permissions
```json
{
"permissions": [
"fs:default",
"shell:default",
"http:default",
"dialog:default"
]
}
```
### Common Plugin Permission Patterns
#### Filesystem Plugin
```json
{
"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
```json
{
"permissions": [
"http:default",
{
"identifier": "http:default",
"allow": [{ "url": "https://api.example.com/*" }],
"deny": [{ "url": "https://api.example.com/admin/*" }]
}
]
}
```
#### Shell Plugin
```json
{
"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`:
```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:
```toml
[[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`:
```rust
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`:
```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):
```json
{
"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:
```json
{
"app": {
"security": {
"capabilities": ["main-capability", "admin-capability"]
}
}
}
```
Or inline capabilities directly:
```json
{
"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
1. Check generated schema: `src-tauri/gen/schemas/`
2. Review capability files load correctly
3. Verify window names match capability targets
4. Check deny rules are not blocking access
## Best Practices
1. **Principle of Least Privilege**: Only grant permissions actually needed
2. **Use Specific Scopes**: Prefer `$APPDATA/*` over `$HOME/**`
3. **Deny Sensitive Paths**: Always deny access to `.ssh`, credentials, etc.
4. **Separate Capabilities**: Use different capabilities for different window types
5. **Document Custom Permissions**: Include clear descriptions
6. **Review Plugin Defaults**: Understand what default permissions grant
7. **Platform-Specific Config**: Use platform targeting for OS-specific needs
No comments yet. Be the first to comment!