tauri-apps/tauri
ACL and capabilities
Tauri v2 replaced the v1 "allowlist" with a richer model. Three concepts, defined in crates/tauri-utils/src/acl/:
- Permission — an atomic rule that allows (or denies) one or more commands and constrains arguments via scope values. Plugins ship permissions as TOML files under
permissions/. The built-in ones live undercrates/tauri/permissions/. - Capability — a JSON document under your app's
src-tauri/capabilities/that grants a set of permissions to a set of webviews in either local or remote contexts. - Scope — typed allow/deny data attached to a permission (e.g. fs allow-paths, http URLs). Plugins parse scope into Rust types.
Each is a Rust type in crates/tauri-utils/src/acl/, has a JSON Schema (generated by tauri-schema-generator), and is resolved into a flat Resolved blob at build time.
Identifiers
Every plugin, permission, and capability has a stable identifier validated at build time (crates/tauri-utils/src/acl/identifier.rs). Identifiers follow namespace:name for plugin permissions and bare names for app-level objects. Invalid identifiers are a build failure, not a runtime error.
Build-time resolution
graph TD
Plugins["plugins' permissions/*.toml"] --> Build["tauri-build (acl.rs)"]
Defaults["plugin default sets"] --> Build
Caps["src-tauri/capabilities/*.json"] --> Build
Build -->|"writes Resolved"| OutDir["OUT_DIR/_acl_/"]
OutDir --> Codegen["tauri-codegen embeds into Context"]
Codegen --> Binary["compiled app binary"]The resolution algorithm (in crates/tauri-build/src/acl.rs, mirrored at runtime in crates/tauri/src/ipc/authority.rs):
- Read every plugin's permission manifest (emitted by
tauri-plugin's build helper). - Read every capability JSON in
src-tauri/capabilities/. - For each capability, expand
permissions: ["..."]into the underlying permission entries, applying default permission sets where requested. - Validate identifiers, scope shapes, and overlap (deny rules win over allow).
- Produce a
Resolvedobject that is a flat array of(webview_label, command_name, scope, allow|deny)rows.
Runtime enforcement
When an IPC message arrives, RuntimeAuthority::resolve_access (crates/tauri/src/ipc/authority.rs):
- Looks up the calling webview's label and origin URL.
- Filters
Resolvedrows for that webview and the requested command. - Merges the allowed scope values into a
ScopeValuefor the command and stores it where the command function can pull it via theCommandScopeextractor. - Returns
AlloworDeny. On deny, the error message lists the missing capability/permission so the developer can fix their config.
The dynamic-acl Cargo feature (default-on) lets app code call Manager::add_capability at runtime to add capabilities programmatically. The same RuntimeAuthority accepts the new rows.
Authoring a plugin permission
Inside a plugin crate:
# permissions/read-file.toml
"$schema" = "schemas/schema.json"
[[permission]]
identifier = "allow-read-file"
description = "Allow reading specific files"
commands.allow = ["read_file"]
[[permission]]
identifier = "deny-secrets"
commands.deny = ["read_file"]
"args" = { path = "deny:/etc/secrets/**" }Then in build.rs:
fn main() {
tauri_plugin::Builder::new(&["read-file"]).build();
}The build helper validates the file, generates a JSON Schema for it, and writes a manifest entry that tauri-build will pick up in downstream apps.
Authoring a capability
Inside a Tauri app:
// src-tauri/capabilities/main.json
{
"$schema": "../../crates/tauri-cli/schema.json",
"identifier": "main",
"description": "main webview capabilities",
"windows": ["main"],
"permissions": [
"core:default",
"fs:allow-read-file",
{ "identifier": "fs:allow-read-file", "allow": ["**/*.md"] }
]
}The windows field selects which webviews this capability applies to. Permissions are either bare identifiers (granting the permission as written) or objects that override scope.
CLI helpers
The CLI exposes tauri permission and tauri capability subcommands (crates/tauri-cli/src/acl/) for scaffolding new permissions, listing existing ones, and adding permissions to capabilities. tauri inspect dumps the resolved ACL as JSON.
Files at a glance
| File | Role |
|---|---|
crates/tauri-utils/src/acl/mod.rs |
Permission, PermissionSet, Scope |
crates/tauri-utils/src/acl/capability.rs |
Capability, CapabilityFile |
crates/tauri-utils/src/acl/identifier.rs |
Identifier validation |
crates/tauri-utils/src/acl/resolved.rs |
Resolved (the compiled-in blob) |
crates/tauri-utils/src/acl/schema.rs |
JSON Schema generation glue |
crates/tauri-utils/src/acl/manifest.rs |
Plugin permission manifest format |
crates/tauri-utils/src/acl/value.rs |
ScopeValue |
crates/tauri-utils/src/acl/build.rs |
Helpers shared with tauri-build |
crates/tauri-build/src/acl.rs |
Build-time resolver |
crates/tauri/src/ipc/authority.rs |
Runtime authority |
crates/tauri/permissions/ |
Built-in permissions for core: namespace |
crates/tauri/src/scope/ |
Helpers for evaluating scopes inside commands |
Cross-references
- The IPC dispatch path that ends in this enforcement: systems/ipc-and-commands.
- Plugin authorship workflow: systems/plugin-system, crates/tauri-plugin.
- Schema generation: crates/tauri-schema-generator.
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.