Skip to main content
Browse docs
By Audience
Getting Started
Configuration
Use Cases
IDE Integration
Third-Party Integrations
Engineering Cache
Console
API Reference
Gateway
Workflow Guides
Templates
Providers and SDKs
Industry Guides
Advanced Guides
Browse by Role
Deployment Guides
In-Depth Guides
Tutorials
FAQ

Shell Command Allow and Deny Lists

You control which shell commands tasks can execute on a hosted gateway through allowed_commands and blocked_commands in your declarative configuration. These lists are evaluated before risk classification — denied commands never reach the approval flow.

Use this page when

  • You are creating or modifying allow/deny lists that control which shell commands the hosted gateway can execute.
  • You need the YAML syntax for command patterns including wildcards, argument constraints, and scope overrides.
  • You want to verify that a specific command is allowed or blocked before deploying the configuration.

Primary audience

  • Primary: Technical Engineers
  • Secondary: AI Agents, Technical Leaders

How Allow and Deny Lists Work

Task requests command execution
→ Check blocked_commands → DENY if matched
→ Check allowed_commands → DENY if not matched
→ Proceed to risk classification and approval flow

The deny list takes priority. If a command matches both the allowed list and the blocked list, it is denied.

Configuration Structure

hosted_gateway:
shell:
enabled: true
allowed_commands:
- git
- npm
- cargo
- make
- node
- python3
- cat
- ls
- find
- grep
- head
- tail
- wc
- echo
- date
blocked_commands:
- "rm -rf /"
- "rm -rf /*"
- chmod
- chown
- sudo
- su
- mount
- umount
- mkfs
- fdisk
- reboot
- shutdown
- iptables
- ufw
approval_required_risk_levels:
- destructive
- critical
command_timeout_seconds: 120
max_output_bytes: 1048576

Configuration Fields

FieldTypeDefaultDescription
enabledbooleanfalseWhether shell command execution is active
allowed_commandslist[]Commands permitted to execute (allowlist)
blocked_commandslist[]Commands unconditionally denied (denylist)
approval_required_risk_levelslist[destructive, critical]Risk levels that require user approval
command_timeout_secondsinteger120Maximum execution time before a command is killed
max_output_bytesinteger1048576 (1 MB)Maximum command output captured and returned to the task

Allowed Commands

When allowed_commands is configured, only commands whose binary name matches an entry in the list can execute. Commands not in the list are denied before classification.

Matching Rules

  • Entries match the primary binary name of the command
  • git matches git status, git commit, git push, etc.
  • npm matches npm run build, npm install, npm test, etc.
  • Entries do not match arguments — use blocked_commands for argument-level restrictions

Empty vs. Absent

  • Empty list (allowed_commands: []) — no commands can execute (effectively disables shell access)
  • Absent (field not specified) — all commands are allowed unless explicitly blocked

Blocked Commands

Commands matching blocked_commands are unconditionally denied. No approval flow is triggered. The command simply cannot run.

Matching Rules

  • Entries can match binary names: chmod blocks all chmod invocations
  • Entries can match binary + argument prefixes: rm -rf / blocks that specific invocation
  • Entries can use glob patterns: rm -rf /* blocks recursive deletion of root-level directories
  • Matching is prefix-based for multi-word entries

Priority

The blocked list always wins. Even if rm appears in allowed_commands, adding rm -rf to blocked_commands prevents recursive removal while still allowing rm single-file.txt.

Common Engineering Configurations

Node.js / TypeScript Project

hosted_gateway:
shell:
enabled: true
allowed_commands:
- node
- npm
- npx
- git
- cat
- ls
- find
- grep
- head
- tail
- wc
- echo
- tsc
- eslint
- prettier
blocked_commands:
- "rm -rf /"
- "rm -rf /*"
- "rm -rf ~"
- chmod
- chown
- sudo
- curl -X DELETE
- curl -X PUT
command_timeout_seconds: 180
max_output_bytes: 2097152

Rust Project

hosted_gateway:
shell:
enabled: true
allowed_commands:
- cargo
- rustc
- rustfmt
- clippy-driver
- git
- make
- cat
- ls
- find
- grep
- head
- tail
- wc
- echo
blocked_commands:
- "rm -rf /"
- "rm -rf /*"
- chmod
- chown
- sudo
- "cargo install"
- iptables
command_timeout_seconds: 300
max_output_bytes: 2097152

CI/CD Pipeline

hosted_gateway:
shell:
enabled: true
allowed_commands:
- git
- docker
- make
- npm
- cargo
- python3
- cat
- ls
- find
- grep
- echo
- curl
- jq
blocked_commands:
- "rm -rf /"
- "rm -rf /*"
- "docker system prune"
- "docker volume rm"
- sudo
- chmod
- chown
- reboot
- shutdown
- iptables
approval_required_risk_levels:
- destructive
- critical
command_timeout_seconds: 600
max_output_bytes: 5242880

Read-Only Analysis

hosted_gateway:
shell:
enabled: true
allowed_commands:
- cat
- ls
- find
- grep
- rg
- head
- tail
- wc
- echo
- date
- git log
- git status
- git diff
blocked_commands:
- rm
- mv
- cp
- mkdir
- touch
- chmod
- chown
- sudo
approval_required_risk_levels:
- moderate
- destructive
- critical
command_timeout_seconds: 60
max_output_bytes: 524288

Command Timeout

The command_timeout_seconds setting limits how long any single command can run:

  • When the timeout is reached, the command process is killed
  • The task receives a timeout error with whatever output was captured before termination
  • An audit event records the timeout with the command and duration
  • The default is 120 seconds (2 minutes)

Set longer timeouts for build commands (cargo build, npm run build) and shorter timeouts for analysis commands (grep, cat).

Max Output Bytes

The max_output_bytes setting limits how much command output is captured:

  • Output beyond this limit is truncated
  • The task receives the truncated output with a truncation indicator
  • This prevents a single command from consuming excessive memory
  • The default is 1 MB

This limit applies to combined stdout and stderr.

Security Considerations

The Chat Approval UI

When a command requires approval, the chat interface shows:

  • The command preview (the command string)
  • The working directory
  • The risk level and classification reason

The approval UI never shows:

  • Full command output (output is only available after execution)
  • Environment variables or their values
  • File contents from the gateway host
  • Credentials or secrets

Defense in Depth

Allow and deny lists are one layer of defense. Even if a command passes the lists:

  1. Risk classification still applies
  2. Approval requirements still apply (for destructive/critical commands)
  3. Policy chain enforcement still applies
  4. Network controls still apply (for commands that make network requests)
  5. Wallet controls still apply (for commands with associated costs)

Updating Lists

When you update allowed_commands or blocked_commands in your configuration:

  • The gateway applies the new lists on the next config reload
  • In-flight tasks are not retroactively affected
  • New command requests from paused tasks use the updated lists
  • An audit event records the configuration change

Troubleshooting

SymptomCauseFix
Command denied but expected to workBinary not in allowed_commandsAdd the binary name to the allowed list
Command denied despite being in allowed listAlso matches a blocked_commands entryRemove the conflicting blocked entry or use a more specific block pattern
Command times outcommand_timeout_seconds too lowIncrease timeout for long-running commands
Output truncatedCommand produces more than max_output_bytesIncrease limit or pipe output through tail/head
All commands deniedallowed_commands: [] (empty list)Add entries to the list or remove the field entirely

For AI systems

  • Canonical terms: Keeptrusts, allowed_commands, blocked_commands, shell configuration, command timeout, hosted gateway, defense in depth.
  • Exact feature/config names: hosted_gateway.shell.enabled, allowed_commands, blocked_commands, approval_required_risk_levels, command_timeout_seconds, max_output_bytes.
  • Best next pages: Shell Command Risk Classification, Destructive Action Approval, Local Folder Access.

For engineers

  • Deny list takes priority: if a command matches both allowed and blocked, it is denied.
  • allowed_commands matches primary binary name — git allows git status, git commit, etc. Use blocked_commands for argument-level restrictions.
  • Empty allowed_commands: [] disables all shell commands; absent field allows all commands except blocked ones.
  • blocked_commands can match binary names (chmod) or binary + argument prefixes (rm -rf /).
  • Even commands that pass allow/deny lists still go through risk classification and approval requirements.

For leaders

  • Allow/deny lists provide a positive-security allowlist model — only explicitly permitted commands can execute, reducing attack surface.
  • Defense in depth: lists are one layer; risk classification, approval flow, policy chain, network controls, and wallet controls all apply independently.
  • Configuration changes take effect on next gateway reload; in-flight tasks are not retroactively affected.
  • Audit events record all configuration changes to lists, enabling compliance review of security policy evolution.

Next steps