tencent cloud

Permission Rules

Download
Focus Mode
Font Size
Last updated: 2026-09-30 18:41:47
AI-Translated

Overview

Use fine-grained allow / ask / deny rules, permission modes, and multi-level settings to precisely constrain what CodeBuddy Code can do. Rules can be committed to a repository and shared with the team, or overridden locally by developers.

Permission System Overview

CodeBuddy Code permissions are not determined solely by the current mode. Instead, they follow a layered evaluation chain. For each tool invocation, the evaluation proceeds roughly in the following order:
Phase
Check Item
Action After Hit
0
Hooks / Special Cases for Interactive Tools
PreToolUse can directly allow / deny / ask; tools like AskUserQuestion inherently require interaction.
1
Deny Rules
Deny immediately with the highest priority.
2
Trusted Allow Rules (user / CLI / session / policy / trusted project rules / --allowedTools)
Allow immediately, and can bypass the interactive dangerous command check.
3
Command Security Check (Interactive Only)
High-risk Bash commands are forced to go to ask.
4
Ask Rules
Force ask.
5
Bypass Mode Short Circuit
bypassPermissions allows most actions here; if disabled, it degrades.
6
Untrusted Allow Rules (untrusted project rules, command / sandbox sources)
Can be allowed, but cannot bypass the dangerous command check in the previous step.
7
Permission Mode Baseline Policy
The current permission mode determines whether the default is allow or ask.
8
Non-interactive Fallback
When the approval dialog cannot be displayed, convert unresolved ask to deny.
9
dontAsk / auto Final Gate
dontAsk rewrites ask to deny; auto only takes over ask and hands it to the classifier.
Key point 1: deny always takes precedence.
Key point 2: CodeBuddy divides allow into two tiers: "trusted allow" and "untrusted allow". Before you explicitly trust the project directory, allow rules in .codebuddy/settings.json / .codebuddy/settings.local.json within the repository cannot bypass dangerous command checks, preventing malicious repositories from committing their own settings to silently weaken local security boundaries.
Key point 3: auto is not a replacement for the entire chain. It only handles actions that would still end with an ask. Explicit ask rules do not go to the classifier.
Read-only tools (Read / Grep / Glob, and others) do not prompt for approval by default within trusted directories. Edit, Bash, and most side-effect tools go through the full evaluation chain.

Which Takes Precedence: Permission Modes or Rules?

The permission system can be understood as two layers:
Rule layer: deny / ask / allow
Mode layer: default / acceptEdits / auto / dontAsk / ...
In CodeBuddy, the rule layer typically takes precedence over the mode layer. Here are the most important examples:
deny takes effect before any mode.
Explicit ask rules take effect before auto, so manual confirmation is still required.
dontAsk does not bypass rules. It only rewrites the final ask into deny.
bypassPermissions does not erase preceding rules. deny / ask can still block it.
Dangerous Bash commands in interactive sessions may enter the ask state due to security checks, even under bypassPermissions.

Three Rule Behaviors

The three arrays under the permissions object correspond to three behaviors:
{
"permissions": {
"allow": ["Bash(npm test)", "Read(/tmp/data/**)"],
"ask": ["WebFetch"],
"deny": ["Bash(rm -rf *)", "Edit(.git/**)"]
}
}
allow: CodeBuddy can be used without approval prompts.
ask: An approval prompt appears on every use.
deny: Never use it.

Where to Manage Rules

/permissions Command

Enter /permissions in a session to open the permission management panel. You can view all current allow / ask / deny rules and the settings layer each rule comes from, and temporarily add or remove rules (written to the user, project, or project-local scope). When you select "Yes, don't ask again" in the dialog, CodeBuddy writes the most stable prefix for the current command to the allow array in the corresponding settings scope.

CLI Startup Parameters

Parameter
Function
--allowedTools <tools...>
Process-level temporary allow rule. Separate by spaces or commas. Example: --allowedTools "Bash(git:*) Edit"
--disallowedTools <tools...>
Process-level temporary deny rule. Same as above.
--add-dir <path>
Add extra directories to the trusted directory scope (affects whether Read requires a confirmation prompt).
-y / --dangerously-skip-permissions
Equivalent to --permission-mode bypassPermissions.

Configuration File

For details, see Settings Configuration. CodeBuddy merges settings across these four scopes:
Scope
Path
user
~/.codebuddy/settings.json
project
<repo>/.codebuddy/settings.json (committed to git)
project-local
<repo>/.codebuddy/settings.local.json (not committed to git, local override)
cliArg / flagSettings / session / policySettings
Process state, not persisted to disk

Rule Syntax

Rule format: Tool or Tool(specifier).

Matching a Tool as a Whole

Remove all calls to the bracket matching tool:
Rule
Description
Bash
All Bash Commands
WebFetch
All web Fetching Operations
Read
Reads all files
Edit
Edits all files
* can also be used alone as a rule, functioning as a full-match wildcard. However, it does not cover MCP tools. For details, see MCP Tools.

Adding Specifiers for Fine-Grained Control

Write the parameters in parentheses:
Rule
Match
Bash(npm run build)
Exact match for npm run build
Bash(npm:*) or Bash(npm *)
All commands starting with npm
Read(./.env)
The .env file in the current directory
Edit(/src/**/*.ts)
src/**/*.ts under the project root
Read(~/.zshrc)
The .zshrc file in the user directory
Read(//tmp/scratch.txt)
An absolute path in the file system: /tmp/scratch.txt
WebFetch(domain:example.com)
Fetch example.com.
mcp__puppeteer__navigate
The navigate tool of the puppeteer service in MCP
Agent(Explore)
Subagent Explore

Tool-Specific Rules

Bash

Bash rules support three syntaxes:
Syntax
Description
Example
Exact match
The pattern exactly matches the command.
Bash(npm run build) matches only npm run build
:* prefix
A :* at the end of the pattern matches the first word / multi-word prefix of a command.
Bash(git:*) matches git status / git push origin main
Wildcard
When a pattern contains *, it is matched in bash glob mode (*** can cross /**).
Bash(npm run *) matches npm run build; Bash(ls *) matches ls -al /tmp/x
The wildcard pattern is intentionally designed to allow * to cross /. Otherwise, ls * cannot match ls -al /xxx, which is the most common pitfall for users.

Compound Commands

CodeBuddy parses the shell operators && / || / ; / |, and evaluates each subcommand independently:
deny / ask rules: Triggered when any subcommand matches.
allow rules: All subcommands must match before the command is allowed. A compound command where one subcommand matches and another does not will still trigger a prompt, preventing attackers from hiding dangerous commands alongside allowed ones.
For example:
allow: ["Bash(git:*)"]

git status → Allowed
git status && rm * → Prompt (rm * is not in the allow list, and all subcommands must match)
git status; rm * → Prompt (same as above)

Redirection

Commands containing > / < / >> / << / &> require exact matching under allow rules, and wildcard rules do not apply.

Read / Edit / Write

File-based rules are matched by glob patterns, and three levels of path normalization are applied:
pattern
Description
Example
//path
File system absolute path
Read(//etc/hosts)
~/path
Starts from the user directory
Read(~/.zshrc)
/path
Starts from the project root
Edit(/src/**/*.ts)
path or ./path
Starts from the current working directory
Read(.env)
Matching options: Leading dots are allowed, matching is case-insensitive, and bare filenames can match at any depth.
Note:
A deny rule such as Edit(.git/**) blocks all attempts through Edit / Write / NotebookEdit. However, it does not block indirect paths such as running python -c 'open(".git/config", "w")...' through Bash. OS-level protection relies on the Bash sandbox.
Read rules are also intercepted and parsed by some Bash file read commands, such as cat, head, and tail.

WebFetch

WebFetch # Any URL
WebFetch(domain:example.com) # Only example.com and its subdomains
The domain: prefix is supported for hostname matching, including subdomains.

MCP Tools

MCP tool naming format: mcp__<server>__<tool>, with segments separated by double underscores __ (single underscores in names are treated as regular characters). Four ways to write rules:
Rule
Match
mcp__puppeteer
All tools with the prefix mcp__puppeteer__
mcp__puppeteer__*
Same as above. The two are equivalent.
mcp__puppeteer__navigate
Only the navigate tool
mcp__*
All MCP tools. Only deny / ask takes effect.
Note:
Rules are case-insensitive. Symbols such as hyphens and periods are treated as underscores, so mcp__web-search is equivalent to mcp__web_search.
* can only replace the entire last segment. mcp__pup* and mcp__puppeteer__nav* do not match any tools, and no error is reported.
MCP tools only recognize rules that start with mcp__. A bare * has no effect on them. To deny all MCP tools, write "deny": ["mcp__*"].

Agent (Subagent)

{
"permissions": {
"deny": ["Agent(Explore)", "Agent(Plan)"]
}
}
You can also use a CLI flag:
codebuddy --disallowedTools "Agent(Explore) Agent(Plan)"
After being denied, the subagent_type is rejected when the main agent invokes an Agent tool.

Skill

{
"permissions": {
"deny": ["Skill(dangerous-skill-name)"]
}
}
Skill rules must be exact matches. Wildcards are not supported.

Trusted Directories

By default, CodeBuddy considers only the current working directory as trusted. The Read tool is allowed within trusted directories and prompts for confirmation outside them. Edit / Bash always go through full approval, unless an allow rule exists or permissive mode is enabled.
Ways to expand the trust scope:
Method
Persistence
--add-dir <path> startup parameter
Process level
/add-dir command within a session
Session level
Add directory via Web UI (/api/v1/workspace-dirs)
Process level (frontend persistence)
permissions.additionalDirectories configuration item
Persistence
permissions.trustedDirectories configuration item
Persistence
The final effective trusted directories = workspace root + settings.trustedDirectories + directories added via --add-dir at startup / /add-dir during a session / the Web UI.
Note:
--add-dir and permissions.additionalDirectories only grant file access. They do not make CodeBuddy load the .codebuddy/ configuration in these directories. agents, hooks, and settings still follow the startup directory.

Project Directory Trust Toggle

Whether a repository directory is explicitly trusted by you also affects the trust level of allow rules. When a directory is not trusted:
allow rules in <repo>/.codebuddy/settings.json and .codebuddy/settings.local.json are classified into the untrusted tier (Phase 6) and cannot bypass command security checks.
After the user confirms trust in the interactive interface, project-level rules are promoted to the Phase 2 trusted tier.
The purpose is to mitigate the lateral risk that arises when a repository is cloned and then run immediately.

Protected Files / Paths

In any mode, CodeBuddy adds extra protection to a set of critical paths, consistent with the permission mode:
The repository itself: .git, .gitconfig, .gitmodules
shell configuration: .bashrc / .zshrc / .envrc, and so on.
Package management: .npmrc / .yarnrc / bunfig.toml, and so on.
IDE tools: .vscode / .idea / .husky / .devcontainer
CodeBuddy itself: .codebuddy (except .codebuddy/worktrees)
MCP / configuration: .mcp.json / .codebuddy.json
The bypassPermissions mode still allows most of them to pass, but catastrophic commands such as rm -rf / / rm -rf ~ are forcibly prompted for confirmation.

Extending Permissions with Hooks

The PreToolUse hook of the Hooks System runs before the permission approval prompt and can programmatically allow / deny / rewrite the input.
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [{ "type": "command", "command": "/path/to/bash-policy.sh" }]
}
]
}
}
Hook exit code semantics:
Exit Code
Action
0 + JSON decision
Execute according to the permissionDecision (allow / ask / deny) in the JSON.
2
Block (stderr content is fed back to the model)
Other non-zero values
Non-blocking error (prompt but allow)
Note:
The structured permissionDecision from PreToolUse takes effect before regular permission rules: allow / deny / ask directly permit, deny, or force a prompt, respectively.
Blocking hooks (exit code 2) can also short-circuit before regular allow rules, so you can "allow all Bash commands first, but use hooks to intercept a few specific commands separately."
If an unconditional hard boundary is required, it is still recommended to prioritize permissions.deny for unified auditing in /permissions and settings.

Collaboration with Sandboxes

Permission rules and the Bash sandbox are complementary layers:
Rule layer: constrains whether CodeBuddy "wants to use" a tool or access a path.
Sandbox layer: constrains whether a Bash subprocess can actually access a resource at the OS level.
Typical combinations for defense in depth:
The deny rule prevents CodeBuddy from proactively attempting to use restricted tools.
The sandbox blocks all Bash subprocesses from accessing files / networks outside the allowlist, even if prompt injection makes CodeBuddy attempt to bypass it.
Both the domain: allow rule for WebFetch and the sandbox allowedDomains take effect, and the final boundary is the intersection of the two.

Settings Priority

Permission rules inherit the general Settings priority:
flagSettings / cliArg / session > userSettings > policySettings >
projectSettings > localSettings > command/sandbox sources
However, the evaluation order is more important than the settings priority:
The deny arrays are merged from all scopes, and a deny in any scope results in denial.
The allow arrays are merged twice based on "trusted / untrusted": in the trusted merge, user / cli / flag / session / policy are always included, while project / local are considered trusted only when the directory is trusted.
disableBypassPermissionsMode takes effect when any of the four layers—user, project, local, or CLI startup parameters—is set to "disable".

Sample Configuration

Minimizing Trust: Allowing Only npm Tests + Reading Files Within the Project

{
"permissions": {
"defaultMode": "default",
"allow": [
"Bash(npm test)",
"Bash(npm run lint)",
"Read(/src/**)",
"Read(/test/**)"
],
"deny": [
"Bash(rm:*)",
"Bash(curl:*)",
"Bash(wget:*)",
"Edit(.git/**)",
"Edit(/.codebuddy/**)"
]
}
}

CI / Pipeline Scenarios: Skipping Approval + Strong deny

{
"permissions": {
"defaultMode": "bypassPermissions",
"deny": [
"Bash(rm -rf /:*)",
"Bash(sudo:*)",
"Bash(curl * -o /etc/*)",
"WebFetch(domain:internal-corp.example)"
]
}
}

Team Sharing + Personal Relaxation

<repo>/.codebuddy/settings.json (committed to git):
{
"permissions": {
"deny": ["Bash(rm:*)", "Edit(.git/**)"]
}
}
~/.codebuddy/settings.json (user-level, private):
{
"permissions": {
"defaultMode": "acceptEdits",
"allow": ["Bash(git:*)", "Bash(npm:*)"]
}
}

Relevant Resources

Permission modes: default / acceptEdits / plan / bypassPermissions / delegate, and other modes.
Settings Configuration: Complete configuration fields, scopes, and merge rules.
Hooks System: Use hooks for programmatic permission decisions.
Bash Sandboxing: OS-level isolation for Bash commands.
CLI Reference: Startup parameters such as --allowedTools / --disallowedTools / --add-dir.
Security: Overall security model and practical tutorials.
IAM Identity and Access: Organization-level identity authentication and permission control.


Help and Support

Was this page helpful?

Help us improve! Rate your documentation experience in 5 mins.

Feedback