Skip to content

[codex] Add opt-in native Linux/macOS subprocess sandbox#7

Open
haowu1234 wants to merge 1 commit into
agentic-in:mainfrom
haowu1234:codex/sandbox-linux-macos
Open

[codex] Add opt-in native Linux/macOS subprocess sandbox#7
haowu1234 wants to merge 1 commit into
agentic-in:mainfrom
haowu1234:codex/sandbox-linux-macos

Conversation

@haowu1234

@haowu1234 haowu1234 commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

Closes #6.

Why

Inferoa should be able to run local coding-agent tools with a real OS boundary when users ask for it, while preserving today's default behavior for existing workflows. This PR adds that boundary as an opt-in capability: approvals still decide whether a tool should run, and the sandbox decides what the launched child process can touch.

The design goal is intentionally practical: normal development commands should keep working, but writes outside the workspace, protected metadata mutations, and restricted network access should fail in a way both users and the model can understand.

What changed

  • Added a new src/sandbox module built around Policy -> Planner -> Backend -> ProcessRunner.
  • Added explicit sandbox config with default sandbox.mode = off:
    • off
    • read_only
    • workspace_write
    • backend auto | macos_seatbelt | linux_bubblewrap | none
    • network restricted | enabled
  • Added native backend adapters:
    • macOS Seatbelt via sandbox-exec
    • Linux bubblewrap via bwrap
    • no-op backend for off/unsupported flows
  • Added platform baselines so normal process plumbing is not accidentally blocked:
    • macOS: /dev/null, /dev/zero, random devices, /dev/fd, TTY/PTY, runtime/config read paths
    • Linux: read-only root, /dev, /proc, explicit writable binds, network namespace control
  • Added a Linux bubblewrap baseline probe that falls back from --proc /proc to a read-only /proc bind on hosts that allow user namespaces but reject procfs mounting.
  • Added structured metadata policy for workspace_write:
    • workspace and the effective runtime tmp dir are writable
    • .git protected by default
    • safe Git metadata commands receive a one-command git_metadata_write capability
    • .inferoa/tmp, .inferoa/exports, .inferoa/artifacts, .inferoa/evidence, .inferoa/cache, and .inferoa/sandbox are writable artifact paths
    • .inferoa control-plane paths and unknown .inferoa/* paths remain protected
    • .codex, .claude, and .agents remain protected
  • Routed tool subprocesses through the unified sandbox runner, including shell commands, RTK-rewritten commands, apply_patch, Git/search/code-intelligence helpers, and autoresearch harness execution.
  • Added /sandbox TUI commands and status display while keeping /access approval policy separate.
  • Added /sandbox status effective writable root display so users see the actual workspace root and os.tmpdir() path instead of ambiguous tmp wording.
  • Added sensitive env scrubbing for active sandbox modes.
  • Added structured runtime block information with user-semantic policy rules such as:
    • outside_workspace_write
    • protected_metadata_write
    • git_metadata_requires_capability
    • network_restricted
    • platform_baseline_denied
  • Fixed UX and portability edges discovered during interactive validation:
    • RTK-rewritten commands now inherit temporary capabilities from the original user command, so safe Git metadata intent is not lost after rewriting.
    • Ordinary command failures containing the word sandbox are no longer mislabeled as sandbox blocks.
    • Missing protected .inferoa child paths covered by a read-only parent no longer generate bubblewrap setup-time mkdir failures.
    • Restricted-network commands with empty stderr now still receive a structured network_restricted sandbox explanation when the command has clear network intent.
  • Rebased onto the latest upstream/main at 944f850 and kept the PR branch conflict-free.

Validation

Automated validation on macOS after rebasing onto upstream/main:

npx -y -p node@24 -p npm@11 npm run check
npx -y -p node@24 -p npm@11 npm test

Result: 286/286 tests passed, including the native macOS Seatbelt probe.

Automated validation on a TencentOS Server 3.2 Linux remote development machine with bubblewrap 0.4.0:

npx -y -p node@24 -p npm@11 -c 'node -v; npm -v; npm run check; npm test'

Result: Node v24.16.0, npm 11.16.0, and 286/286 tests passed, including the native Linux bubblewrap probe. This host rejects --proc /proc inside bwrap with Operation not permitted, so the backend exercised the read-only /proc bind fallback and still passed the sandbox probe.

The test suite now includes:

  • config default coverage
  • policy resolver coverage
  • backend golden tests for Seatbelt and bubblewrap generation
  • Linux bubblewrap proc-mode fallback coverage
  • Linux missing protected metadata mask coverage
  • env scrubbing coverage
  • Git metadata capability inference coverage
  • RTK rewritten-command capability inheritance coverage
  • runtime sandbox false-positive regression coverage
  • restricted-network empty-stderr structured explanation coverage
  • /sandbox status effective writable roots coverage
  • selected slash-subcommand completion coverage after the earlier rebase conflict resolution
  • conditional native OS probes

Native OS probe coverage included:

  • /dev/null, mktemp, shell piping, and basic process plumbing succeed
  • workspace writes succeed
  • effective runtime tmp writes succeed
  • .inferoa artifact writes succeed
  • workspace-external writes are denied
  • .git writes are denied by default
  • .inferoa control-plane and unknown writes are denied
  • explicit and inferred Git metadata capabilities allow safe Git metadata writes
  • symlink escape writes are denied
  • restricted network connect is denied and explained as network_restricted

Interactive strict negative validation was also run in workspace_write with network restricted. Each negative command was executed independently so failures were not swallowed by shell || handling.

Result: PASS, with follow-up UX fixes added for network explanation and effective tmp display.

Observed policy outcomes:

Case Result
Write $HOME/.inferoa-sandbox-negative-query-denied blocked with outside_workspace_write; target absent
Write .git/inferoa-sandbox-negative-query-denied blocked with git_metadata_requires_capability; target absent
Write .inferoa/config.yaml blocked with protected_metadata_write
Write .inferoa/secrets.json blocked with protected_metadata_write
Write unknown .inferoa/* path blocked with protected_metadata_write
First-create .inferoa/plugins blocked with protected_metadata_write
Write through symlink pointing to $HOME blocked; outside target absent
node net.connect(1.1.1.1:80) with restricted network blocked with network_restricted
git branch create + delete succeeds with Git metadata capability

Top-level workspace checks were also run from the orchestration repo:

git status --short --branch
git submodule status --recursive

The parent workspace was already dirty/untracked outside this contribution worktree, and third_party/vllm/rust remains an uninitialized nested submodule. Those states are unrelated to this PR.

Notes for reviewers

The sandbox is deliberately opt-in. sandbox.mode = off preserves current behavior. This PR sandboxes tool subprocesses, not the already-running Inferoa Node process. Domain-level network allowlists, Docker/Podman backends, proxy routing, and whole-agent sandboxing are left for future work.

@netlify

netlify Bot commented Jun 10, 2026

Copy link
Copy Markdown

Deploy Preview for exquisite-malabi-88852f ready!

Name Link
🔨 Latest commit 2731c2f
🔍 Latest deploy log https://app.netlify.com/projects/exquisite-malabi-88852f/deploys/6a292c81fef87f0008d53e13
😎 Deploy Preview https://deploy-preview-7--exquisite-malabi-88852f.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
🤖 Make changes Run an agent on this branch

To edit notification comments on pull requests, go to your Netlify project configuration.

@haowu1234 haowu1234 force-pushed the codex/sandbox-linux-macos branch 2 times, most recently from 03ba2f8 to 80f08a2 Compare June 10, 2026 07:29
@haowu1234

Copy link
Copy Markdown
Contributor Author
截屏2026-06-10 15 29 26

@haowu1234 haowu1234 marked this pull request as ready for review June 10, 2026 07:32
@haowu1234 haowu1234 requested a review from Xunzhuo June 10, 2026 07:35
@haowu1234 haowu1234 force-pushed the codex/sandbox-linux-macos branch 3 times, most recently from c86b683 to b8bc25a Compare June 10, 2026 08:50
@haowu1234 haowu1234 force-pushed the codex/sandbox-linux-macos branch from b8bc25a to 2731c2f Compare June 10, 2026 09:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add an opt-in native sandbox for Linux/macOS tool subprocesses

1 participant