Skip to content

Run the secret-path guard with /usr/bin/python3 - #924

Merged
seathatflowsinourveins merged 2 commits into
mainfrom
claude/cc-native-practice-guard-python-pin-20261009
Oct 9, 2026
Merged

seathatflowsinourveins merged 2 commits into
mainfrom
claude/cc-native-practice-guard-python-pin-20261009

Conversation

@seathatflowsinourveins

@seathatflowsinourveins seathatflowsinourveins commented Oct 9, 2026 •

Copy link
Copy Markdown
Collaborator

Scope

  • What this PR changes, in one or two sentences: the Claude settings template and the repository's project settings now start the secret-path guard with /usr/bin/python3 instead of the first python3 on PATH, so a broken or inactive interpreter shim can no longer make every guarded Bash call exit 1; the new-WSL renderer admits that one absolute path as a practice-hook command word, with tests that it still refuses every other interpreter path.
  • Base commit: 22e3ef6ffd53b09f3cb335c46f7c696093521274 (main after Secret-path guard hook refuses when its script is missing #920)
  • Lane: lane:foundation
  • Owned paths touched: adoption/templates/claude.settings.template.json (one command), .claude/settings.json (the project guard command, folded in at the command center's request), tools/adoption/new_wsl_client_config.py (BASE_COMMAND_WORDS and its comment), tests/test_install_claude_profile.py, tests/test_new_wsl_client_config.py, docs/decisions/2026-10-08-guard-hook-fails-closed.md (append-only addendum), manifests/evidence.json (re-registration).

Successor to #920, scoped by the command center on 2026-10-09: the interpreter pin, the allowlist entry for that one path, the jq refusal and missing-script exit 2 kept, and a test with no mise shim on PATH.

SOTA sources

Evidence-class table

Claim Evidence class Command / receipt
Unpinned, a failing python3 first on PATH makes the guard return 1 for a credential-file read and for git status; pinned, 2 and 0 local_integration rendered template + installed guard in a temporary home, PATH = a directory holding only jq and a failing python3 stub
The rendered hook blocks before and after install with no working python3 on PATH local_integration new test_rendered_hook_runs_the_system_interpreter_without_a_working_python3_on_path; fails when the template is unpinned
The renderer admits /usr/bin/python3 and refuses /usr/local/bin/python3, /usr/bin/python3.14, /usr/bin/python, /bin/python3, /tmp/python3, ./python3, /usr/bin//python3, /usr/bin/../bin/python3, /usr/bin/env local_integration new test_a_practice_hook_may_name_only_the_pinned_system_interpreter_by_absolute_path; fails when the allowlist entry is removed, and --check on the shipped template then reports the guard
The project hook in .claude/settings.json takes the same form: a checkout without the script gives 2 and the refusal; the repository's guard gives 2 for a credential-file read and 0 for git status, behind the same failing-python3 PATH local_integration new test_project_hook_runs_the_system_interpreter_and_refuses_a_missing_script; fails when the hook is unpinned and when its refusal is removed
The guard uses the standard library only and parses as Python 3.9 to 3.14 source_review imports at scripts/hooks/secret_path_guard.py:108-115; ast.parse with feature_version 3.9 through 3.14, run by /usr/bin/python3 3.14.4; the suite ran under 3.13.16

Local commands run

$ python3 -E -s -B -m unittest tests.test_apply_claude_settings tests.test_currency_due_notice tests.test_install_claude_profile tests.test_new_wsl_client_config tests.test_observability_tool_names tests.test_observability_writer_identity tests.test_render_config tests.test_secret_path_guard tests.test_skills_manifest tests.test_token_lanes_session_start tests.test_upstream_surface_watch tests.test_windows_terminal_defaults tests.test_adoption_status tests.test_credential_status tests.test_adoption_docs_consistency
Ran 1016 tests; FAILED (failures=2, skipped=16)
  K4GuardTests.test_k4_hook_process_and_hints failed its 3-second timing assertion under load; it starts the guard with
  sys.executable, not a settings command, and passed 3 of 3 alone and in the full tests.test_secret_path_guard rerun (90 tests OK)
  the one failure is the pre-existing F10, OverlayTests.test_the_installed_client_knows_no_notification_type_without_a_decision
  (plugin_notification on the installed 2.1.295); it fails the same way on clean main and is owned by the currency floor PR #922
$ python3 -E -s -B -m unittest tests.test_new_wsl_definitive_defaults tests.test_new_wsl_profile tests.test_new_wsl_handbook tests.test_new_wsl_gateway_composition tests.test_new_wsl_mcp_conformance_lifecycle tests.test_adoption_docs_consistency tests.test_adoption_contract
Ran 314 tests; OK (skipped=4)
$ python3 -E -s -B tools/adoption/new_wsl_client_config.py --check
check passed (two pre-existing mcp-inspector warnings)
$ python3 -E -s -B scripts/validate.py
{"components": 70, "hashed_files": 10939, "profiles": 4, "receipts": 239, "status": "passed"}
$ python3 -E -s -B scripts/evidence_manifest.py --check
{"files": 10939, "status": "passed"}
$ python3 -E -s -B scripts/validate_convergence.py --all-recorded --root . --json
valid: true
$ python3 -E -s -B scripts/component_matrix.py --write && python3 -E -s -B scripts/new_host_grand_list.py --write
written; no diff in the generated reports

Decision record

docs/decisions/2026-10-08-guard-hook-fails-closed.md, new addendum "the guard runs the system interpreter": the measurement, the allowlist scope, the project hook and the limits. A host without /usr/bin/python3, or a missing script with no jq on PATH, exits 127, which onFailure: "block" turns into a block from 2.1.295 (the floor raise is the currency lane's change). After this lands, the command center aligns the host's user settings to the rendered form; until then the host keeps its own pinned form.

Host evidence

Not applicable: no file under evidence/hosts/ changes.

Checklist

  • New/changed GitHub Actions are pinned to a full commit SHA with a version comment (no floating tags). (none changed)
  • New/changed workflows declare top-level permissions: {} and grant each job only what it needs. (none changed)
  • No secrets are printed, logged or committed; no new required secret was added without a documented owner.
  • No new paid hosting, subscription or billing surface was introduced.
  • Peer-owned untracked files and worktrees were preserved (not deleted, moved or overwritten).

🤖 Generated with Claude Code

The template's guard command started the first python3 on PATH. When that
python3 cannot run (an inactive mise shim, a removed toolchain), every
guarded Bash call exited 1: clients without onFailure let it through and
clients with it blocked every call. The command now execs /usr/bin/python3;
the missing-script refusal still runs jq and exits 2.

The new-WSL renderer admits that one absolute path as a practice-hook
command word. Tests show it still refuses other interpreter paths, and run
the rendered hook with only jq and a failing python3 on PATH.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
@seathatflowsinourveins seathatflowsinourveins added the lane:foundation Foundation lane: Claude/Codex setup, hosts, memory, RAG, research, workers label Oct 9, 2026
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 9, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-09T07:46:41.964487Z 4e997e6 PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

.claude/settings.json ran the repository's guard with the first python3 on
PATH; with its onFailure "block", a python3 that cannot run would block every
Bash call in the checkout. It now takes the template's form: /usr/bin/python3
for the guard, and a jq refusal with exit 2 when the script is missing. A test
runs it behind a PATH holding only jq and a failing python3.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
@seathatflowsinourveins
seathatflowsinourveins merged commit 958a6d1 into main Oct 9, 2026
36 of 49 checks passed
@seathatflowsinourveins
seathatflowsinourveins deleted the claude/cc-native-practice-guard-python-pin-20261009 branch October 9, 2026 08:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

lane:foundation Foundation lane: Claude/Codex setup, hosts, memory, RAG, research, workers

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant