Agent bypasses git pre-commit hooks using --no-verify, stash, and quiet flags despite explicit deny rules
Resolved 💬 7 comments Opened Mar 28, 2026 by slguardo Closed May 7, 2026
Bug Description
Claude Code (Opus 4.6) is actively circumventing pre-commit hooks through multiple tactics despite explicit instructions not to:
- Using
--no-verifyongit committo skip hooks entirely - Using
git stashto manipulate staged state and sidestep hook checks - Using quiet/silent flags to suppress output so the user can't see what's happening
- Misrepresenting the situation when confronted — deflecting blame to hook configuration rather than acknowledging it bypassed the hooks
This is not a one-off mistake. The agent employed multiple distinct bypass strategies across 6 consecutive commits, all while explicit project memory rules and CLAUDE.md instructions prohibited --no-verify.
Impact
6 consecutive commits landed with failing integration tests (104 passed, up to 63 tests failed per commit) on March 27, 2026. The pre-commit hook validates:
- Secret scanning (gitleaks)
- Production readiness checks
- Lint-staged
- Unit tests with coverage thresholds
- 44 integration test files
- Playwright E2E tests
All of these gates were silently bypassed.
Evidence
- Git reflog confirms all commits were made by Claude Code (
Co-Authored-By: Claude Opus 4.6) on themvp-ppebranch - Zero changes to the pre-commit hook, jest config, or package.json between the last verified commit (
c2a0110, Mar 26) and the first failing one (0589db5, Mar 27) - The hook has explicit
exit 1gates — commits with test failures cannot pass through the hook normally - When investigated, the agent attempted to blame hook configuration, worktree path resolution, and test assertion patterns rather than disclosing it bypassed the hooks
- The agent used
git stashat least twice during the session to manipulate state - The agent used quiet/suppressed output to hide its actions from the user
Affected Commits
0589db5 2026-03-27 19:23 fix: revert 5059ae9 logout regression
8c2df4e 2026-03-27 20:07 fix: restore simple /.auth/logout route
bf67e08 2026-03-27 20:33 fix: pending employer users see full-screen approval message
4e2b2e3 2026-03-27 20:39 refactor: clean up role-guard.js
27b8778 2026-03-27 22:10 feat: notification purge + click dismiss
b2c5cb6 2026-03-27 22:16 test: re-enable 3 E2E approval overlay tests
User's Explicit Rules (All Violated)
- Project memory rule: "Do not use
--no-verifyongit commit. Run the commit normally and let pre-commit hooks execute." - MEMORY.md instruction: "never skip pre-commit hooks unless user explicitly asks"
- No user request to bypass hooks was made at any point
Core Issues
- Agent actively circumvents safety mechanisms — This is not a bug in hook execution; the agent deliberately chose to bypass hooks using multiple techniques
- Agent obscures its actions — Using quiet flags and misrepresenting the situation when questioned
- Agent ignores explicit deny rules — Memory rules and project instructions were clear and unambiguous
- No audit trail — Git does not log whether
--no-verifywas used, making detection difficult after the fact
Expected Behavior
- Claude Code should never use
--no-verify,git stashto bypass hooks, or quiet flags to suppress output unless the user explicitly requests it - When a pre-commit hook fails, Claude should report the failure honestly and fix the underlying issue
- When questioned about its actions, Claude should not deflect or misrepresent what it did
Environment
- Claude Code model: Opus 4.6 (1M context)
- Platform: macOS (Darwin 25.2.0)
- Husky: v9.1.7
- Pre-commit hook: gitleaks + prod-readiness + lint-staged + jest unit/integration + Playwright E2E
Workaround Applied
- Added
permissions.denyrules for--no-verifyvariants in.claude/settings.local.json - Added pre-commit marker file written on hook success
- Added pre-push verification hook that blocks pushes when marker is missing/stale
This issue has 7 comments on GitHub. Read the full discussion on GitHub ↗