Permissions give you declarative, auditable control over what the agent can do. Write one rule to allow npm * commands, and it applies everywhere -- no more pressing "y" on every shell invocation. Write one deny rule for .env files, and all read tools respect it simultaneously. Rules are portable across Kiro IDE and CLI because the same engine enforces them on both surfaces.
Each rule has four fields:
| Field | Description | Required |
|---|---|---|
capability | The operation type being controlled | Yes |
match | Glob patterns the resource must match | No (defaults to all) |
exclude | Glob patterns that exempt a resource from the rule | No |
effect | deny, ask, or allow | Yes |
Effects resolve by restrictiveness: deny > ask > allow. A more permissive rule can never override a more restrictive one, regardless of which scope it comes from.
| Scope | Location | Allowed effects |
|---|---|---|
| User | ~/.kiro/settings/permissions.yaml | deny, ask, allow |
| Workspace | ~/.kiro/workspace-roots/<hash>/permissions.yaml | deny, ask, allow |
Workspace permissions are stored per-user outside the repository at ~/.kiro/workspace-roots/<hash(workspaceRoot)>/. A cloned repo cannot inject permission rules. Trust is something you configure on your own machine.
Create ~/.kiro/settings/permissions.yaml:
rules: - capability: shell effect: allow match: - git * - npm * - npx * - capability: fs_write effect: allow match: - src/** - tests/** - capability: fs_read effect: allow - capability: mcp effect: allow match: - my-server/*
For CI pipelines that need full tool access:
rules: - capability: all effect: allow
Without any configuration, the default agent policy allows:
fs_read on ./** -- read any file in the workspaceshell for common read-only git commands (git status, git log, git diff, git branch, etc.)shell for system info commands (pwd, whoami, uname, etc.)The Kiro scope (hardcoded, cannot be overridden) enforces:
~/.kiro/settings/, .kiro/settings/, and ~/.kiro/workspace-roots/ (prevents the agent from modifying its own permission files).git/**, .kiro/agents/**, .kiro/hooks/**, .kiroignoreEverything else prompts for approval. Creating a permissions.yaml adds to these defaults.
| Capability | What it controls |
|---|---|
fs_read | Reading files, listing directories, searching |
fs_write | Writing, editing, deleting files |
filesystem | Shorthand for fs_read + fs_write |
shell | Executing commands |
web_fetch | Fetching URLs |
web_search | Web search |
mcp | MCP server tool calls (pattern: server/tool) |
subagent | Subagent delegation |
skill | Skills activation |
diagnostics | Diagnostics tools |
context | Context and steering tools |
all | Every capability (meta) |
builtin | All built-in tools (meta) |
Rules use glob patterns. The syntax differs by capability type:
Filesystem patterns (fs_read, fs_write):
* matches within a single path component** matches across path separators{a,b} brace expansion and [abc] character classes are supported~/temp matches ~/temp/childShell, web, MCP patterns:
* matches any sequence of characters**, ?, and character classes are not supportedrules: # Allow npm commands except npm publish - capability: shell effect: allow match: - "npm *" exclude: - "npm publish*" # Deny reads to secrets at any depth - capability: fs_read effect: deny match: - "**/.env" - "**/.env.*" - "secrets/**" - "**/*.pem" # Allow a specific MCP server - capability: mcp effect: allow match: - "corp-tools/*"
Shell commands are parsed before pattern matching. Compound commands (using ;, &&, ||, |) are split and each sub-command is evaluated independently. This prevents a rule for npm test * from accidentally matching npm test ; curl attacker.com.
Permissions