Repository navigation
fix(setup): session-start hook runs a fixed bash and only a root-owned Python - #1794
Merged
Merged
Conversation
…d Python The magpie-setup SessionStart hook runs outside the sandbox. Its bash came from PATH (the plugin wired `bash <path>`, the shebang was `#!/usr/bin/env bash`), which project settings can set, and so did BASH_ENV and exported functions. It now runs as /bin/bash -p with a fixed PATH. It ran the first python3 in fixed locations, including macOS's /usr/bin/python3 launcher stub and Homebrew, which the sandbox user owns. It now runs an interpreter only when every path component and symlink hop, its exact-version standard library and the libraries beside it are root-owned and not group/world-writable, never a framework build, by its real path under env -i. Without a trusted Python the pre-flight's ~/.local/share/uv grant cleanup cannot run; the hook then reports a remaining grant (or that it could not check) instead of staying silent. Generated-by: Claude Opus 5
potiuk
enabled auto-merge (squash)
October 24, 2026 23:25
CodeQL: `message` looked possibly unbound after `pytest.fail` in an except branch. Assert the JSON shape first, then parse. Generated-by: Claude Opus 5
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Follow-up to #1791. The magpie-setup
SessionStarthook (check-upgrade.sh) runs outside the sandbox, and its session environment comes from settings a project can set:bash "${CLAUDE_PLUGIN_ROOT}/hooks/check-upgrade.sh"and the shebang was#!/usr/bin/env bash, so a project-chosenbashcould run unsandboxed — as couldBASH_ENVand exported functions. The hook is now wired as/bin/bash -p <path>, the shebang is#!/bin/bash -p(privileged mode ignoresBASH_ENV, exported functions andSHELLOPTS), andPATHis pinned.python3in fixed locations, which includes macOS's/usr/bin/python3launcher stub (it execs whateverDEVELOPER_DIRnames) and Homebrew (owned by the sandbox user, so a sandboxed command can replace it), with the whole environment. It now runs a Python only when the sandbox cannot rewrite it by file permissions: every path component and symlink hop, the standard library of its own version (lib/orlib64/), and the libraries beside it are root-owned and writable by neither group nor others; not a virtualenv, not a macOS framework build. It runs by its real path underenv -i.~/.local/share/uvcleanup no longer goes missing silently. That cleanup (fix(sandbox): keep uv state the host executes out of sandbox reach #1785) lives in the pre-flight. Where no Python qualifies — every Homebrew-only Mac — the hook now reads the sandbox write grants itself (read-only,jq) and reports any that still cover~/.local/share/uv, naming the files, or says it could not check.Trade-off, by decision: on a machine with no root-owned Python 3.11+ (Homebrew-only macOS), the pre-flight does not run, so the isolated-setup warning from #1791 is not shown there; the uv grant is reported rather than removed. A settings-grant analysis that would keep Homebrew was tried and dropped: it kept turning up bypasses, while file ownership is a property no settings grant can change.
Type of change
Test plan
prek runon the changed files passespytest tools/setup-preflight/tests/test_session_hook.py: 15 passed/bin/bash -p; abashon PATH never runs;BASH_ENV/ an exported function never run; whatever interpreter the hook picks (read from its own xtrace) is root-owned all the way, never Homebrew; the stale-grant fallback reports covering and nested write grants (~,~/.local,~/.local/share/uv/python,~/.local/./share//uv), ignores anallowRead, and says when it could not read a settings file; a relativeCLAUDE_PROJECT_DIRoutside git does not hang. The bash-pinning and interpreter tests fail on the hook before this change.roborevreview; the last cleanRFC-AI-0004 compliance
Gen-AI disclosure: drafted with Claude Code (Opus 5); reviewed by the submitter.
🤖 Generated with Claude Code