.claude/skills/tauri-scope/SKILL.md
Guides users through configuring Tauri command scopes for security, including filesystem restrictions, URL patterns, dynamic scope management, and capability-based access control.
npx skillsauth add rdjakovic/todo2 configuring-tauri-scopesInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
This skill covers configuring scopes in Tauri v2 applications to control fine-grained access to commands and resources.
Scopes are a granular authorization mechanism in Tauri that controls what specific operations a command can perform. They function as fine-grained permission boundaries beyond basic command access.
The scope is passed to the command during execution. The command implementation is responsible for validating against the scope and enforcing restrictions. This means developers must carefully implement scope validation to prevent bypasses.
Scopes are configured in capability files located at:
src-tauri/capabilities/default.json (primary)src-tauri/capabilities/*.json (additional capability files)The filesystem plugin uses glob-compatible path patterns to define accessible paths.
{
"$schema": "../gen/schemas/desktop-schema.json",
"identifier": "default",
"description": "Default capability for the application",
"windows": ["main"],
"permissions": [
{
"identifier": "fs:scope",
"allow": [{ "path": "$APPDATA" }, { "path": "$APPDATA/**" }]
}
]
}
Restrict individual filesystem operations rather than global access:
{
"permissions": [
{
"identifier": "fs:allow-read-text-file",
"allow": [{ "path": "$DOCUMENT/**" }]
},
{
"identifier": "fs:allow-write-text-file",
"allow": [{ "path": "$HOME/notes.txt" }]
}
]
}
{
"permissions": [
{
"identifier": "fs:allow-rename",
"allow": [{ "path": "$HOME/**" }],
"deny": [{ "path": "$HOME/.config/**" }]
}
]
}
Tauri provides runtime-injected variables for common system directories:
| Variable | Description |
|----------|-------------|
| $APPCONFIG | Application config directory |
| $APPDATA | Application data directory |
| $APPLOCALDATA | Application local data directory |
| $APPCACHE | Application cache directory |
| $APPLOG | Application log directory |
| $AUDIO | User audio directory |
| $CACHE | System cache directory |
| $CONFIG | System config directory |
| $DATA | System data directory |
| $DESKTOP | User desktop directory |
| $DOCUMENT | User documents directory |
| $DOWNLOAD | User downloads directory |
| $EXE | Application executable directory |
| $HOME | User home directory |
| $PICTURE | User pictures directory |
| $PUBLIC | Public directory |
| $RESOURCE | Application resource directory |
| $TEMP | Temporary directory |
| $VIDEO | User video directory |
Scopes support glob patterns for flexible path matching.
{
"permissions": [
{
"identifier": "fs:scope",
"allow": [
{ "path": "$APPDATA/databases/*" },
{ "path": "$DOCUMENT/**/*.txt" },
{ "path": "$HOME/project/src/**" }
],
"deny": [
{ "path": "$HOME/.ssh/**" },
{ "path": "$HOME/.gnupg/**" }
]
}
]
}
| Pattern | Meaning |
|---------|---------|
| * | Matches any characters except path separator |
| ** | Matches any characters including path separator (recursive) |
| ? | Matches a single character |
| [abc] | Matches any character in brackets |
Tauri prevents path traversal attacks. These paths are NOT allowed:
/usr/path/to/../file../path/to/fileThe HTTP plugin uses URL patterns to control network access.
{
"permissions": [
{
"identifier": "http:default",
"allow": [{ "url": "https://*.tauri.app" }],
"deny": [{ "url": "https://private.tauri.app" }]
}
]
}
{
"permissions": [
{
"identifier": "http:default",
"allow": [
{ "url": "https://api.example.com/*" },
{ "url": "https://*.cdn.example.com/**" }
]
}
]
}
For plugins or custom commands, define permissions in TOML files.
# permissions/my-permission.toml
[[permission]]
identifier = "scope-appdata-recursive"
description = "Recursive access to APPDATA folder"
[[permission.scope.allow]]
path = "$APPDATA/**"
[[permission]]
identifier = "deny-sensitive-data"
description = "Denies access to sensitive directories"
platforms = ["linux", "macos"]
[[permission.scope.deny]]
path = "$HOME/.ssh/**"
[[permission.scope.deny]]
path = "$HOME/.gnupg/**"
Combine permissions into reusable sets:
[[set]]
identifier = "safe-appdata-access"
description = "Allows APPDATA access while denying sensitive folders"
permissions = ["scope-appdata-recursive", "deny-sensitive-data"]
Tauri allows runtime scope modification using the FsExt trait from Rust.
use tauri_plugin_fs::FsExt;
pub fn run() {
tauri::Builder::default()
.plugin(tauri_plugin_fs::init())
.setup(|app| {
let scope = app.fs_scope();
// Allow a specific directory (non-recursive)
scope.allow_directory("/path/to/directory", false)?;
// Check what's currently allowed
dbg!(scope.allowed());
Ok(())
})
.run(tauri::generate_context!())
.expect("error while running tauri application");
}
use tauri_plugin_fs::FsExt;
#[tauri::command]
fn expand_scope(
app_handle: tauri::AppHandle,
folder_path: std::path::PathBuf
) -> Result<(), String> {
// Verify path before expanding scope
if !folder_path.exists() {
return Err("Path does not exist".to_string());
}
// true = allow inner directories recursively
app_handle
.fs_scope()
.allow_directory(&folder_path, true)
.map_err(|err| err.to_string())
}
#[tauri::command]
fn allow_file(
app_handle: tauri::AppHandle,
file_path: std::path::PathBuf
) -> Result<(), String> {
app_handle
.fs_scope()
.allow_file(&file_path)
.map_err(|err| err.to_string())
}
Dynamic scope expansion should be used carefully:
Control which remote URLs can access your application's commands.
{
"identifier": "remote-api-access",
"description": "Allow remote access from specific domains",
"windows": ["main"],
"remote": {
"urls": ["https://*.mydomain.dev", "https://app.example.com"]
},
"permissions": ["core:default"]
}
{
"$schema": "../gen/schemas/desktop-schema.json",
"identifier": "default",
"description": "Default capability for desktop application",
"windows": ["main", "settings"],
"platforms": ["linux", "macos", "windows"],
"permissions": [
"core:default",
"core:window:allow-set-title",
{
"identifier": "fs:default"
},
{
"identifier": "fs:allow-read-text-file",
"allow": [
{ "path": "$DOCUMENT/**/*.md" },
{ "path": "$DOCUMENT/**/*.txt" }
]
},
{
"identifier": "fs:allow-write-text-file",
"allow": [{ "path": "$APPDATA/notes/**" }],
"deny": [{ "path": "$APPDATA/notes/.secret/**" }]
},
{
"identifier": "http:default",
"allow": [{ "url": "https://api.example.com/*" }]
}
]
}
fs:allow-read-text-file over global fs:scope$APPDATA over hardcoded paths for portability{
"permissions": [
{
"identifier": "fs:allow-read-text-file",
"allow": [{ "path": "$APPDATA/**" }]
},
{
"identifier": "fs:allow-exists",
"allow": [{ "path": "$APPDATA/**" }]
}
]
}
{
"permissions": [
{
"identifier": "fs:scope",
"allow": [{ "path": "$DOCUMENT/**" }],
"deny": [
{ "path": "$DOCUMENT/.hidden/**" },
{ "path": "$DOCUMENT/**/*.key" }
]
}
]
}
{
"permissions": [
{
"identifier": "http:default",
"allow": [
{ "url": "https://api.myapp.com/v1/*" },
{ "url": "https://cdn.myapp.com/**" }
],
"deny": [
{ "url": "https://api.myapp.com/v1/admin/*" }
]
}
]
}
This error indicates the requested path is outside the configured scope. Solutions:
Run in development mode to test permissions:
pnpm tauri dev
# or
cargo tauri dev
Permission errors will appear in the console indicating which permissions need configuration.
development
Enforce web security and avoid security vulnerabilities
development
Guides users through distributing Tauri applications on Windows, including creating MSI and NSIS installers, customizing installer behavior, configuring WebView2 installation modes, and submitting apps to the Microsoft Store.
documentation
Guides users through Tauri window customization including custom titlebar implementation, transparent windows, window decorations, drag regions, window menus, submenus, and menu keyboard shortcuts for desktop applications.
tools
Assists users with updating Tauri dependencies including the Tauri CLI, Rust crates, JavaScript packages, and checking for outdated versions to upgrade to the latest version.