Sandbox silently disabled when ripgrep not installed — no warning to user

Resolved 💬 3 comments Opened Mar 9, 2026 by jmmgreg Closed Mar 12, 2026

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

  1. Ensure ripgrep is NOT installed (brew uninstall ripgrep or a fresh machine without it)
  2. Configure sandbox in .claude/settings.json:
{
  "sandbox": {
    "enabled": true,
    "filesystem": {
      "allowWrite": ["/Users/me/projects/"],
      "denyWrite": ["//Users/me/Downloads"]
    }
  }
}
  1. Start Claude Code: claude
  2. Run /sandbox — shows dependencies as "installed" (bubblewrap, socat, seccomp listed even on macOS), no mode toggle appears
  3. Run /configno sandbox status line shown
  4. 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')"
  1. 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

  1. /sandbox UI 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.
  2. /sandbox UI 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.
  3. /config output shows no sandbox status: Even with sandbox.enabled: true in settings, /config doesn't display sandbox status. Should show "Sandbox: enabled (active)" or "Sandbox: enabled (INACTIVE — missing: rg)".
  4. Process tree confirms no sandboxing: ps shows Terminal → zsh → claude → zsh with no sandbox-exec wrapper.

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
  • /sandbox should show accurate dependencies: On macOS, show ripgrep + sandbox-exec status, not Linux deps
  • /config should show sandbox status: Sandbox: disabled (missing dependencies) or Sandbox: 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

View original on GitHub ↗

This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗