Open-Source Wikis

/

Tauri

/

Systems

/

ACL and capabilities

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 under crates/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):

  1. Read every plugin's permission manifest (emitted by tauri-plugin's build helper).
  2. Read every capability JSON in src-tauri/capabilities/.
  3. For each capability, expand permissions: ["..."] into the underlying permission entries, applying default permission sets where requested.
  4. Validate identifiers, scope shapes, and overlap (deny rules win over allow).
  5. Produce a Resolved object 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):

  1. Looks up the calling webview's label and origin URL.
  2. Filters Resolved rows for that webview and the requested command.
  3. Merges the allowed scope values into a ScopeValue for the command and stores it where the command function can pull it via the CommandScope extractor.
  4. Returns Allow or Deny. 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

Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.

ACL and capabilities – Tauri wiki | Factory