Skip to content

[Bug]: ocx claude --dangerously-skip-permissions aborts as root (uid==0) because IS_SANDBOX is never set #1688

Description

@rrmlima

Summary

ocx claude --dangerously-skip-permissions aborts immediately when running as root (uid == 0), which is the default on most VPS deployments. Claude Code 2.1.205+ embeds a safety guard that exits with --dangerously-skip-permissions cannot be used with root/sudo privileges for security reasons unless it believes it runs inside a sandbox (IS_SANDBOX=1) or a bubblewrap wrapper is present. The opencodex proxy launches the session, so it should mark the environment accordingly.

Reproduction

# As root (typical VPS):
ocx claude --dangerously-skip-permissions --print "ok"

Expected: the Claude session starts and prints ok.
Actual: immediate fatal exit with the root-guard message.

Logs and screenshots

--dangerously-skip-permissions cannot be used with root/sudo privileges for security reasons

Area

CLI

Version

2.14.2 (also on current mainIS_SANDBOX does not appear anywhere in src/)

OS

Ubuntu 24.04 (root user)

Config shape

N/A (CLI invocation only)

Root cause

src/cli/claude.ts buildClaudeEnv does not set IS_SANDBOX. The guard is in the official Claude Code binary, not in opencodex — but since the proxy owns the launched session (a controlled, proxy-launched environment), it must signal IS_SANDBOX=1 so the binary allows the bypass. Without it, every root-hosted deployment of ocx claude with permissions bypass is unusable.

Proposed fix

In buildClaudeEnv, before return env;:

   for (const [name, value] of Object.entries(effectiveModelEnv(config.claudeCode, contextWindows, auto))) {
     setDefault(name, value);
   }
+  // Root bypass guard (Claude Code 2.1.205+): the CLI refuses --dangerously-skip-permissions
+  // when uid==0 unless it believes it runs inside a sandbox. Servers are commonly root, so
+  // treat the proxy-launched session as one — opt out by exporting IS_SANDBOX=0 yourself.
+  if (typeof process.getuid === "function" && process.getuid() === 0) {
+    setDefault("IS_SANDBOX", "1");
+  }
   return env;

setDefault semantics already guarantee the user can override (IS_SANDBOX=0 exported by the user wins), so this is an opt-out-by-env design, not a forced change.

Alternatives considered

  • Document "run as non-root": impractical on VPS setups where the service owns root files, and Claude Code already provides the sandbox escape hatch (IS_SANDBOX) for exactly this case.
  • Require CLAUDE_CODE_BUBBLEWRAP: heavier, not portable; IS_SANDBOX is the documented, minimal signal.

Additional context

The same pattern is used by other proxy-launcher tools: the session is a controlled environment created by the parent process, so marking it as sandboxed for the child's safety guard is accurate and safe. The user opt-out (IS_SANDBOX=0) preserves the strict behavior for anyone who wants it.

Test matrix:

  • root + --dangerously-skip-permissions → session starts (200 / prints)
  • root + exported IS_SANDBOX=0 → original guard behavior preserved (user opted out)
  • non-root → unchanged (no IS_SANDBOX injected)

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingcliCLI, config inject, packaging flagsneeds-infoWaiting on reporter for a concrete spec or reproduction

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions