diff --git a/bin/agent-hook-pre-bash b/bin/agent-hook-pre-bash index adb0e1e..451d919 100755 --- a/bin/agent-hook-pre-bash +++ b/bin/agent-hook-pre-bash @@ -513,6 +513,13 @@ _hook_run_guards() { _GUARD_GIT_PUSH_FORCE=1 break } ;; + +?*) + # A refspec that leads with `+` (e.g. `+main`, `+HEAD:main`, + # `+refs/heads/x:y`) forces the push without `--force`/`-f`, so it + # must be caught too. --force-with-lease stays allowed above. + _GUARD_GIT_PUSH_FORCE=1 + break + ;; esac ((i++)) done diff --git a/test/suites/agent-hook-bash-guards-test b/test/suites/agent-hook-bash-guards-test index e0e91cf..2ab6a04 100755 --- a/test/suites/agent-hook-bash-guards-test +++ b/test/suites/agent-hook-bash-guards-test @@ -150,11 +150,27 @@ _assert_not_contains "git push --force-with-lease=ref: no BLOCKED" "BLOCKED" "$H _run_hook "$PRE_BASH" '{"tool_input":{"command":"git -C /tmp/repo push -f"}}' _assert_eq "git -C push -f: blocked" "2" "$HOOK_EXIT" +# `+` forces the push without --force/-f and must also be blocked. +_run_hook "$PRE_BASH" '{"tool_input":{"command":"git push origin +main"}}' +_assert_eq "git push origin +main: blocked" "2" "$HOOK_EXIT" +_assert_contains "git push origin +main: BLOCKED msg" "BLOCKED" "$HOOK_STDERR" + +_run_hook "$PRE_BASH" '{"tool_input":{"command":"git push origin +HEAD:main"}}' +_assert_eq "git push origin +HEAD:main: blocked" "2" "$HOOK_EXIT" + +_run_hook "$PRE_BASH" '{"tool_input":{"command":"git push origin +refs/heads/x:refs/heads/y"}}' +_assert_eq "git push origin +refspec: blocked" "2" "$HOOK_EXIT" + # normal push is fine _run_hook "$PRE_BASH" '{"tool_input":{"command":"git push origin main"}}' _assert_eq "git push (no force): allowed" "0" "$HOOK_EXIT" _assert_not_contains "git push (no force): no BLOCKED" "BLOCKED" "$HOOK_STDERR" +# a non-force src:dst refspec (no leading +) must NOT be flagged as force +_run_hook "$PRE_BASH" '{"tool_input":{"command":"git push origin HEAD:main"}}' +_assert_eq "git push src:dst (no force): allowed" "0" "$HOOK_EXIT" +_assert_not_contains "git push src:dst: no BLOCKED" "BLOCKED" "$HOOK_STDERR" + _run_hook "$PRE_BASH" '{"tool_input":{"command":"git push -u origin feat/foo"}}' _assert_eq "git push -u: allowed" "0" "$HOOK_EXIT"