Repository navigation
chore: refuse a push to main in every spelling with a pre-call hook - #38
Merged
Merged
Conversation
settings.json's deny rules match spellings, so a bare git push on main, git push origin HEAD, an alias or a shell within a shell got through to GitHub's ruleset. The push guard from the owner's other repositories now reads every Bash and PowerShell command first and refuses a push that would land on main or a tag, a force push, git tag, gh release, gh pr merge --auto or --admin, and a write through gh api to releases or refs; what it cannot read and mentions one of those, it refuses too. Its own cases run from the container suite; the killed-git case needs an executable temporary directory and is skipped where /tmp is noexec.
The review found AGENTS.md and CLAUDE.md promising that the hook refuses a push in every spelling; it does not open script files or other programs, by design, so they now say so and name the ruleset on main as the guard.
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.
Why
.claude/settings.jsondenies the usual spellings of a push tomain, but a pattern list cannot cover every one: a baregit pushwhilemainis checked out,git push origin HEADonmain, an alias or a shell within a shell reached GitHub's ruleset instead of the hook layer. Closes #25. The ruleset onmain(pull request required, merge only,deterministicrequired) stays the real guard; this is defence in depth, the same hook the owner's other repositories carry.What changed
.claude/hooks/push-guard.sh: verbatim copy of adanext-exec's pre-call hook. It reads every Bash and PowerShell command and refuses a push that would land onmainor a tag in the spellings it can read, a force push,git tag,gh release,gh pr merge --autoor--admin, and writes throughgh apito releases or refs; a command it cannot read that mentions one of those is refused too. Script files and other programs are not read..claude/hooks/push-guard.test.sh: its case list, verbatim except one block: the killed-git case executes a shim from the temp dir, and the test containers mount/tmpnoexec, so it runs only where a probe script in the temp dir can execute and prints a skip line otherwise..claude/settings.json: the hook underhooks.PreToolUseforBash|PowerShell, same shape as the existing post-edit hook.tests/python/test_push_guard_hook.py: both scripts exist and are LF, the settings wiring parsed as JSON, and a run of the case list assertingok (N cases), so the container suite and CI run the guard's cases.AGENTS.md,CLAUDE.md,.claude/skills/check/SKILL.md,docs/testing.md: the hook, what it does not read, where its cases run, and the Python test count (139; main said 127, stale since chore: add the agent setup (AGENTS.md, CLAUDE.md, .claude) #24 added nine).Tests run
docker compose -f docker/compose.yaml run --rm --no-deps python-tests: 139 tests OK on both commits, about 12 s, the guard's cases included (the killed-git case skipped there).sh .claude/hooks/push-guard.test.shon the Windows host under Git Bash: ok (223 cases), with the killed-git case included, 6 min 23 s.diffagainst adanext-exec: the hook is identical; the test script differs only in the probe/skip block.Review
Independent review of 0634885: nothing blocking. It verified the verbatim copy, the LF attributes, the wiring, the test count, the ruleset on
main, and traced this repository's own allowed commands through the hook (compose commands,gh pr merge <n> --merge --delete-branch --match-head-commit,gh workflow run,gh variable delete,gh issue create --body-file): none misfires. Non-blocking: AGENTS.md and CLAUDE.md overstated the hook ("every spelling"); fixed in e1ad78a since this branch wrote those lines. Filed as issues: the hook's cost and 20 s timeout on Windows are unmeasured on a large PR body; the fail-closed case never runs in CI.