Skip to content

fix(agent-isolation): let prek and uv run inside the sandbox - #1359

Merged
potiuk merged 1 commit into
apache:mainfrom
potiuk:fix/sandbox-tool-paths-local-settings
Sep 23, 2026
Merged

potiuk merged 1 commit into
apache:mainfrom
potiuk:fix/sandbox-tool-paths-local-settings

Conversation

@potiuk

@potiuk potiuk commented Sep 23, 2026

Copy link
Copy Markdown
Member

Summary

  • The problem: Claude Code does not apply the home-directory sandbox.filesystem.allowRead / allowWrite entries from the committed .claude/settings.json. This is the same behaviour as setup-isolated-setup-install: "." in allowRead does not cover CWD; need defensive abs-path resolution at install time #197, where the committed "." entry was dropped. Inside the sandbox ~/.local/bin, ~/.local/share/uv, ~/.cache and ~/.gitconfig stay denied. prek and uv are then "command not found", and agents fall back to a sandbox bypass to run the hooks, which runs working-tree hook code with full access to $HOME. The Claude Code docs say allowRead merges across every scope, so this is harness behaviour rather than a documented contract.
  • The fix: sandbox-add-project-root.sh now also writes those dev-tool paths, as absolute paths, into each worktree's gitignored .claude/settings.local.json, where the harness does apply them.
    • Readable: ~/.gitconfig, ~/.config/git, ~/.cache, ~/.local/share/uv, ~/.local/bin.
    • Writable: ~/.cache, ~/.local/share/uv.
    • It deliberately does not copy the whole committed list. That list also names ~/.config/gh, ~/.config/apache-magpie (the Gmail OAuth token) and ~/.gnupg, which the same harness behaviour currently keeps out of sandboxed Bash.
    • --no-tool-paths keeps the old project-root-only behaviour.
  • Discoverability:
    • A new sandbox-troubleshooting.md entry covers the failure.
    • sandbox-error-hint.sh maps command not found: prek|uv|uvx to that entry.
    • setup-isolated-setup-verify check 8 reports missing tool paths as ⚠.
    • Install step P.2 and the agent-isolation-sandbox spec describe the new paths.

Type of change

  • Skill change (.claude/skills/<name>/) — eval fixtures updated below
  • Tool / bridge contract (tools/<system>/*.md)
  • Python package (tools/*/ with pyproject.toml)
  • Groovy reference impl
  • Cross-cutting (RFC, AGENTS.md, sandbox, privacy-LLM)
  • Documentation (docs/, README.md, CONTRIBUTING.md)
  • Project template (projects/_template/)
  • CI / dev loop (prek, workflows, validators)
  • Other:

Test plan

  • prek run --all-files passes except tools/container-gateway pytest. tests/test_daemon.py::test_run_unlinks_pid_file_before_closing_the_lock_fd fails the same way on main, on files this PR does not touch.
  • tools/agent-isolation: uv run pytest, 262+ passed. There are 6 new helper tests (tool paths added, write paths exact, credential paths never added, idempotent, existing entries kept in place, --no-tool-paths) and 4 new hint tests (zsh / bash / uvx signatures, look-alike commands stay silent).
  • Reproduced the problem on Linux (bubblewrap) with Claude Code 2.1.280: with the committed settings only, ~/.local/bin, ~/.cache, ~/.local/share/uv and ~/.gitconfig are denied in the sandbox, while settings.local.json and user-scope entries are applied.
  • For skill changes: eval suites run with magpie-run-evals.sh (claude -p).
    • setup-isolated-setup-install: 13/13.
    • setup-isolated-setup-verify: 12/15. The 3 failures (step-1 case-7 on check 10a; step-2 case-3 and case-5) fail identically with main's SKILL.md, so they are not caused by this change.
  • For skill behaviour changes: new fixture step-1-classify/case-8-tool-paths-missing (check 8 ⚠). The step-1 fixtures that model a helper-written settings.local.json (cases 1, 3, 4, 7) now carry the tool paths.
  • Other:

RFC-AI-0004 compliance

  • Sandbox — widens sandboxed reads and writes to a fixed set of non-credential dev-tool paths that the committed baseline already intended to allow. It removes a reason for running prek with the sandbox bypassed, and adds no credential path or network reach.
  • HITL — the helper still writes only the gitignored settings.local.json, which the harness write-denies from inside the sandbox; the operator runs it from a terminal or approves the bypass.

Linked issues

Refs #197

Notes for reviewers (optional)

  • Committed settings left alone: .claude/settings.json still lists the ~/ entries. They cost nothing where they are ignored, and keeping them means they take effect if the harness starts applying project-scope allows as documented.
  • Doctor probe is a follow-up: sandbox-troubleshooting.md asks each entry to get a doctor probe as well as a hint-hook branch. This PR adds the hint branch and the verify check; a prek --version-in-sandbox probe in setup-isolated-setup-doctor is left for a follow-up.
  • Spec sync: tools/spec-loop/.last-sync is not bumped. Only the agent-isolation-sandbox spec is updated, by hand, for this change.

Generative AI disclosure: this change was prepared with Claude Code (Claude Opus 5) and reviewed by the author before submission.

🤖 Generated with Claude Code

@potiuk potiuk added family:setup setup-* skills family:tools tools/* capability:platform Framework / agent substrate skills (install, verify, doctor, override, status, setup bootstrap) labels Sep 23, 2026
Claude Code does not apply the home-directory allowRead / allowWrite
entries from the committed .claude/settings.json, the same behaviour
behind apache#197. Inside the sandbox ~/.local/bin, ~/.local/share/uv,
~/.cache and ~/.gitconfig stay denied, so `prek` and `uv` are not
found and agents fall back to a sandbox bypass to run the hooks.

sandbox-add-project-root.sh now also writes those dev-tool paths, as
absolute paths, into each worktree's gitignored
.claude/settings.local.json, where the harness does apply them:
~/.gitconfig, ~/.config/git, ~/.cache, ~/.local/share/uv and
~/.local/bin readable, the cache and uv dirs writable. It never adds
the credential paths the committed list also names (~/.config/gh,
~/.config/apache-magpie, ~/.gnupg). --no-tool-paths keeps the old
project-root-only behaviour.

- sandbox-troubleshooting.md gains an entry for the failure, and
  sandbox-error-hint.sh points "command not found: prek|uv|uvx" at it.
- setup-isolated-setup-verify check 8 reports the missing tool paths
  as a warning; install step P.2 and the agent-isolation spec describe
  the new paths.
- The verify step-1 fixtures that model a helper-written file carry
  the tool paths, and a new case covers them being absent.

Generated-by: Claude Opus 5
@potiuk
potiuk force-pushed the fix/sandbox-tool-paths-local-settings branch from a66a1e8 to 150dfed Compare September 23, 2026 14:52
@potiuk
potiuk merged commit 58ee85a into apache:main Sep 23, 2026
10 checks passed
potiuk added a commit to potiuk/magpie that referenced this pull request Sep 23, 2026
The doctor skill's probes are meant to move in lock-step with the
sandbox troubleshooting catalogue, but apache#1359 added the "prek or uv not
found inside the sandbox" entry without a matching probe.

Probe 7 (probe-7-dev-tools.sh) checks that prek and uv run inside the
sandbox and can write ~/.cache. Inside the sandbox a read-denied
~/.local/bin looks exactly like an absent one, so when neither tool is
found it reads the worktree's settings.local.json to tell a missing
grant (warn) from a tool that is not installed (skip).

- The error-hint hook and the setup doc now count seven probes, and
  the doc's hint table gains the prek / uv signature from apache#1359.
- The troubleshooting entry no longer says the new paths apply only
  from the next session: the harness picks up settings.local.json
  changes on the next sandboxed command.
- The interpret-probes eval grows a dev_tools_status field and a
  case-16 fixture for the missing grant.

Generated-by: Claude Code (Opus 5)
potiuk added a commit that referenced this pull request Sep 23, 2026
The doctor skill's probes are meant to move in lock-step with the
sandbox troubleshooting catalogue, but #1359 added the "prek or uv not
found inside the sandbox" entry without a matching probe.

Probe 7 (probe-7-dev-tools.sh) checks that prek and uv run inside the
sandbox and can write ~/.cache. Inside the sandbox a read-denied
~/.local/bin looks exactly like an absent one, so when neither tool is
found it reads the worktree's settings.local.json to tell a missing
grant (warn) from a tool that is not installed (skip).

- The error-hint hook and the setup doc now count seven probes, and
  the doc's hint table gains the prek / uv signature from #1359.
- The troubleshooting entry no longer says the new paths apply only
  from the next session: the harness picks up settings.local.json
  changes on the next sandboxed command.
- The interpret-probes eval grows a dev_tools_status field and a
  case-16 fixture for the missing grant.

Generated-by: Claude Code (Opus 5)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

capability:platform Framework / agent substrate skills (install, verify, doctor, override, status, setup bootstrap) family:setup setup-* skills family:tools tools/*

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant