Sandbox silently disabled when ripgrep not installed — no warning to user
Bug Description
When sandbox.enabled: true is configured in settings, if ripgrep (rg) is not installed on the system, the sandbox silently fails to activate with no warning, no error, and no indication to the user. All bash commands run completely unsandboxed while the user believes they are protected.
Security Impact
High. Users who configure sandbox expect OS-level filesystem and network isolation. Without any warning that sandbox is inactive, users have a false sense of security. Commands can write anywhere on the filesystem, exfiltrate data to any host, etc. — all while the configuration explicitly says "sandbox": { "enabled": true }.
Steps to Reproduce
- Ensure
ripgrepis NOT installed (brew uninstall ripgrepor a fresh machine without it) - Configure sandbox in
.claude/settings.json:
{
"sandbox": {
"enabled": true,
"filesystem": {
"allowWrite": ["/Users/me/projects/"],
"denyWrite": ["//Users/me/Downloads"]
}
}
}
- Start Claude Code:
claude - Run
/sandbox— shows dependencies as "installed" (bubblewrap, socat, seccomp listed even on macOS), no mode toggle appears - Run
/config— no sandbox status line shown - Run a bash command that writes outside allowed paths:
echo "test" > ~/Downloads/should-be-blocked.txt
python3 -c "open('/Users/me/Downloads/test.txt', 'w').write('test')"
- Both succeed. No sandbox enforcement at all.
Root Cause
Found by reverse-engineering the binary (v2.1.71). The startup flow is:
// Startup calls:
if (dT.isSandboxingEnabled())
await dT.initialize(...)
// isSandboxingEnabled (Yzq) checks:
function Yzq() {
if (!K38()) return false; // isSupportedPlatform — passes on macOS
if (T38().errors.length > 0) // checkDependencies — FAILS here
return false;
if (!hUT()) return false; // isPlatformInEnabledList — passes
return kUT(); // isSandboxEnabledInSettings — passes
}
// checkDependencies (ecT) on ALL platforms checks ripgrep:
function ecT(_) {
// ...
if (vF(K.command) === null) // vF = which(rg)
q.push(`ripgrep (${K.command}) not found`);
// ...
}
When rg is not found, checkDependencies returns an error, isSandboxingEnabled() returns false, and initialize() is never called. No error is logged, no warning is shown.
Additional Issues Found
/sandboxUI shows wrong dependencies on macOS: Lists "bubblewrap (bwrap): installed, socat: installed, seccomp filter: installed" — these are Linux dependencies. On macOS it should show Seatbelt/sandbox-exec status and ripgrep./sandboxUI has no mode toggle: When dependencies fail, the mode tab doesn't appear, but there's no indication WHY. User sees "Dependencies: all installed" but can't enable sandbox./configoutput shows no sandbox status: Even withsandbox.enabled: truein settings,/configdoesn't display sandbox status. Should show "Sandbox: enabled (active)" or "Sandbox: enabled (INACTIVE — missing: rg)".- Process tree confirms no sandboxing:
psshowsTerminal → zsh → claude → zshwith nosandbox-execwrapper.
Expected Behavior
- Startup warning: If sandbox is configured but can't activate, show a clear warning:
⚠️ Sandbox enabled in settings but cannot activate: ripgrep (rg) not found. Install with: brew install ripgrep /sandboxshould show accurate dependencies: On macOS, show ripgrep + sandbox-exec status, not Linux deps/configshould show sandbox status:Sandbox: disabled (missing dependencies)orSandbox: active (auto-allow mode)- Consider bundling ripgrep: Claude Code already uses ripgrep for search — if it's bundled internally, the sandbox dependency check should use the bundled version
Fix
Installing ripgrep (brew install ripgrep) immediately fixes the issue — sandbox activates correctly with Seatbelt enforcement.
Environment
- Claude Code: v2.1.71 (latest as of March 9, 2026)
- OS: macOS 26.1 Tahoe (Darwin 25.1.0, arm64)
- Machine: Apple Silicon (M1 Pro)
- Terminal: Terminal.app
- Login: Claude Max Account
🤖 Generated with Claude Code
This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗