Skip to content

fix(setup): let sandboxed git see the whole-user hook dir - #1364

Merged
potiuk merged 2 commits into
apache:mainfrom
potiuk:fix/whole-user-hooks-sandbox-read
Sep 23, 2026
Merged

potiuk merged 2 commits into
apache:mainfrom
potiuk:fix/whole-user-hooks-sandbox-read

Conversation

@potiuk

@potiuk potiuk commented Sep 23, 2026

Copy link
Copy Markdown
Member

Summary

  • The bug: whole-user scope sets core.hooksPath to ~/.claude/git-hooks, but nothing grants the sandbox read access to that directory. Git inside the sandbox sees no hook directory and treats that as "no hooks". Every commit an agent makes skips pre-commit (and so prek), commit-msg, pre-push and the rest without a warning, and CI is the first place the skipped checks fail.
  • Install Step P.3-whole-user gains a step proposing a read-only user-scope allowRead grant for ~/.claude/git-hooks/, plus ~/.claude-config/git-hooks/ when the hooks are symlinked from the sync repo, because the sandbox checks the resolved path.
  • Docs: secure-agent-setup.md explains the grant next to the whole-user trade-offs. sandbox-troubleshooting.md catalogues the silent skip, quoting the errors exactly as printed.
  • setup-isolated-setup-verify check 8 now probes the hook directory from inside the sandbox and reports an unreadable one as ✗.

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

  • Reproduced on Linux (bubblewrap, Claude Code 2.1.280, whole-user dispatcher flavour):
    • Inside the sandbox, git hook run pre-commit fails with error: cannot find a hook named pre-commit, and ls ~/.claude/git-hooks fails with No such file or directory.
    • Outside the sandbox the same commands find the dispatcher.
  • prek run on the PR's diff passes, and so do the check-doc-sync and skill-token-count hooks tree-wide (rebased onto main at feat(setup): probe prek and uv in the sandbox doctor #1362).
  • For skill changes: eval suites run with magpie-run-evals.sh (claude -p).
    • setup-isolated-setup-install: 13/13.
    • setup-isolated-setup-verify: the new case passes. step-1 case-7 and step-2 case-3 / case-5 fail identically on main. step-1 case-8 and step-2 case-4 failed once on grader wording and passed on rerun.
  • For skill behaviour changes: new fixture step-1-classify/case-9-whole-user-hooks-unreadable (check 8 ✗). Caveat: it also passes against main's conditional-checks.md, because the fixture's evidence is explicit enough that the model marks it ✗ without the new rule. It guards against regressions rather than proving the new rule is needed.
  • Other:

RFC-AI-0004 compliance

  • Sandbox — the grant is read-only and limited to the hook directory the global git config already points every repo at; nothing becomes writable. Without it, the sandbox silently disables a quality gate rather than containing anything.
  • HITL — install proposes the settings diff and waits for the operator; verify only reports.

Linked issues

Notes for reviewers (optional)

  • No error-hint rule: git prints nothing when it can't see core.hooksPath, so sandbox-error-hint.sh has nothing to match. The verify probe is where this surfaces.
  • Doctor probe is a follow-up: a probe for this entry could run the same sandboxed test -r as check 8, now that probe 7 (feat(setup): probe prek and uv in the sandbox doctor #1362) has landed.
  • Restart note: the troubleshooting entry says a new directory under ~/.claude/ may stay hidden until Claude Code restarts. That's what was observed: grants for ~/.local/bin / ~/.cache took effect on the next command, but ~/.claude/git-hooks did not appear in the sandbox's view of ~/.claude/ during the session that added it.

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

🤖 Generated with Claude Code

Whole-user scope sets core.hooksPath to ~/.claude/git-hooks, but
nothing granted the sandbox read access to it. Git inside the sandbox
then sees no hook directory and treats that as "no hooks": every
commit the agent makes skips pre-commit (prek included), commit-msg
and the rest without a warning, and CI is the first to notice.

- Install Step P.3-whole-user gains a step proposing the read-only
  user-scope allowRead grant for ~/.claude/git-hooks/ (and
  ~/.claude-config/git-hooks/ when the hooks are symlinked from the
  sync repo).
- secure-agent-setup.md explains the grant beside the whole-user
  trade-offs, and sandbox-troubleshooting.md catalogues the silent
  skip.
- setup-isolated-setup-verify check 8 probes the hook dir from inside
  the sandbox and reports an unreadable one as a failure, with a new
  step-1 fixture.

Generated-by: Claude Code (Opus 5)
@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
The doctor's probes follow the troubleshooting catalogue, and the
previous commit adds the "git hooks silently skipped" entry. Git
prints nothing when it cannot see core.hooksPath, so the error-hint
hook cannot catch it; a probe that looks from inside the sandbox can.

Probe 8 (probe-8-git-hooks.sh) reports skip when there is no global
core.hooksPath, fail when the hook dir or a hook's symlink target is
unreadable inside the sandbox, warn when the dir holds none of the
common hooks, and pass with the hooks it can see. The doctor now
counts eight probes, and the interpret-probes eval gains a
git_hooks_status field and a case-17 fixture.

Generated-by: Claude Code (Opus 5)
@potiuk
potiuk merged commit 695d8c6 into apache:main Sep 23, 2026
10 checks passed
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