How the OS-Level Sandbox Works in Claude Code Telegram: sandbox_enabled and sandbox_excluded_commands Explained
The OS-level sandbox confines Bash commands to the APPROVED_DIRECTORY using the sandbox_enabled setting, while sandbox_excluded_commands designates specific tools like git and npm to run directly on the host OS with full system access.
The claude-code-telegram bot implements a defense-in-depth security model that isolates file-system operations through OS-level sandboxing. This mechanism is controlled by two configuration fields in src/config/settings.py that determine whether Bash tools run in a restricted environment or with unrestricted host access. Understanding the interaction between sandbox_enabled and sandbox_excluded_commands is essential for securing deployments while accommodating tools that require system-wide visibility.
Where Sandbox Settings Are Defined
The security configuration resides in src/config/settings.py, where Pydantic fields declare the sandbox behavior:
sandbox_enabled: bool = Field(
True,
description="Enable OS-level bash sandboxing for approved dir",
)
sandbox_excluded_commands: Optional[List[str]] = Field(
default=["git", "npm", "pip", "poetry", "make", "docker"],
description="Commands that run outside the sandbox (need system access)",
)
Source: lines 114-120 [settings.py]
When sandbox_enabled is True, the system activates OS-level isolation for all Bash commands. The sandbox_excluded_commands list identifies command names that bypass these restrictions, defaulting to common development utilities that require access to global configuration files and system-wide package repositories.
How the Sandbox Is Applied to Claude SDK Requests
The configuration propagates from settings into the Claude runtime via src/claude/sdk_integration.py. The ClaudeSDKManager constructs a ClaudeAgentOptions object that embeds the sandbox dictionary:
options = ClaudeAgentOptions(
...,
sandbox={
"enabled": self.config.sandbox_enabled,
"autoAllowBashIfSandboxed": True,
"excludedCommands": self.config.sandbox_excluded_commands or [],
},
...
)
Source: lines 176-182 [sdk_integration.py]
This dictionary instructs the Claude Code runtime to wrap Bash tools in a restricted environment when enabled is True. The excludedCommands array ensures listed tools execute directly on the host OS without directory boundary checks. Even when sandbox_enabled is False, the SDK receives the sandbox configuration with "enabled": False, effectively disabling isolation.
Unit tests in tests/unit/test_claude/test_sdk_integration.py verify this propagation, ensuring the ClaudeAgentOptions.sandbox dict receives the correct flags and excluded commands (lines 271-307).
Runtime Enforcement and Directory Boundary Checks
Beyond the SDK-level sandbox, src/claude/monitor.py implements secondary validation through the check_bash_directory_boundary function. This Python-based defense parses Bash commands and validates file-system operations remain within the approved_directory:
- Parse the command with
shlex.split - Identify the base command (
mkdir,rm, etc.) - Skip read-only commands that do not modify the file system
- For filesystem-modifying commands, resolve each path against the current working directory
- Reject any path that resolves outside the absolute
approved_directoryusingPath.relative_to
Source: check_bash_directory_boundary lines 70-130 [monitor.py]
The monitor validates Bash tool calls when the bot operates in classic (non-agentic) mode:
if tool_name in ["bash", "shell", "Bash"] and not self.agentic_mode:
valid, error = check_bash_directory_boundary(
command, working_directory, self.config.approved_directory
)
Source: lines 240-292 [monitor.py]
In agentic mode (AGENTIC_MODE=true), the monitor skips these checks because Claude Code's native OS sandbox handles enforcement at the system level. The test suite in tests/unit/test_claude/test_monitor.py validates this behavior, including handling of malformed quoting and dangerous patterns (line 113).
Implications of sandbox_enabled versus sandbox_excluded_commands
Understanding the distinction between these two settings is critical for secure deployment:
sandbox_enabled
- Controls the global OS-level sandbox state for all Bash tools
- When
True: Commands run in a restricted environment confined toAPPROVED_DIRECTORY - When
False: Commands execute with full host access, bypassing both SDK sandboxing and monitor directory checks (dangerous for production)
sandbox_excluded_commands
- Specifies command names that execute outside the sandbox even when
sandbox_enabledisTrue - Default entries include
git,npm,pip,poetry,make, anddocker - Commands in this list bypass
check_bash_directory_boundarybut remain subject to tool name validation unlessDISABLE_TOOL_VALIDATIONis set
If a command appears in sandbox_excluded_commands, it receives direct host execution without directory isolation. However, the monitor still validates the command name against allow-lists unless tool validation is explicitly disabled via environment variables.
Practical Configuration Example
To configure a secure environment that allows version control but restricts file modifications:
# src/config/settings.py
sandbox_enabled: bool = Field(
True, # Maintain OS-level isolation
description="Enable OS-level bash sandboxing for approved dir",
)
sandbox_excluded_commands: Optional[List[str]] = Field(
default=["git", "npm"], # Allow system-wide operations
description="Commands that run outside the sandbox",
)
When executing through ClaudeSDKManager:
from src.config.settings import Settings
from src.claude.sdk_integration import ClaudeSDKManager
from pathlib import Path
cfg = Settings() # sandbox_enabled=True, excluded=["git", "npm"]
sdk = ClaudeSDKManager(config=cfg)
# git runs unsandboxed; mkdir runs sandboxed
response = await sdk.execute_command(
prompt="git status && mkdir new_folder",
working_directory=Path("/app/projects"),
)
In this execution, git status operates with full system access while mkdir is confined to the approved directory. Setting sandbox_enabled = False would remove all protections, exposing the host file system to arbitrary modifications.
Summary
- The OS-level sandbox is configured in
src/config/settings.pythroughsandbox_enabledandsandbox_excluded_commands - sandbox_enabled activates SDK-level isolation for Bash commands, restricting file access to
APPROVED_DIRECTORY - sandbox_excluded_commands allows specific tools to bypass sandbox restrictions and run directly on the host OS
- The Claude SDK receives these settings via
ClaudeAgentOptionsinsrc/claude/sdk_integration.py - Secondary validation occurs in
src/claude/monitor.pythroughcheck_bash_directory_boundaryfor non-agentic mode - Excluded commands bypass directory boundary checks but remain subject to tool validation unless disabled
Frequently Asked Questions
What happens if I set sandbox_enabled to False?
Setting sandbox_enabled to False disables the OS-level sandbox entirely. The ClaudeAgentOptions still transmits the configuration with "enabled": False, but no isolation occurs. Bash commands execute with full host file system access, bypassing both the SDK sandbox wrapping and the directory boundary checks in monitor.py. This configuration is not recommended for production deployments as it removes the primary security boundary protecting the host from unintended file modifications.
Why are git and npm excluded from the sandbox by default?
These commands require system-wide access to function properly. Git accesses global configuration files and multiple repository locations, while package managers like npm and pip install dependencies across the system. Confining these tools to APPROVED_DIRECTORY would prevent normal operation. The sandbox_excluded_commands list ensures these trusted utilities can access the entire file system while maintaining restrictions on potentially dangerous commands like rm or curl.
Does monitor.py validation apply to excluded commands?
No. Commands listed in sandbox_excluded_commands bypass the check_bash_directory_boundary validation in src/claude/monitor.py. However, they remain subject to tool name validation against allow-lists and disallowed patterns unless you set DISABLE_TOOL_VALIDATION in the environment. This means excluded commands receive direct host execution without directory boundary checks but still undergo basic command validation.
How does agentic mode affect sandbox behavior?
When running in agentic mode (AGENTIC_MODE=true), the bot skips the monitor.py directory boundary checks because Claude Code's native OS sandbox handles enforcement at the system level. The SDK still respects the sandbox_enabled and sandbox_excluded_commands settings passed via ClaudeAgentOptions, but the secondary Python-based validation in monitor.py is not invoked. This delegation relies on Claude Code's built-in sandbox to catch malicious commands that might escape directory boundaries.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →