diff --git a/src/agent/__tests__/hooks.test.ts b/src/agent/__tests__/hooks.test.ts index 05e42ee..bd01c5d 100644 --- a/src/agent/__tests__/hooks.test.ts +++ b/src/agent/__tests__/hooks.test.ts @@ -109,6 +109,59 @@ describe("createDangerousCommandBlocker", () => { expect(result).toHaveProperty("decision", "block"); }); + test("blocks git push -f short flag", async () => { + const hook = createDangerousCommandBlocker(); + const callback = hook.hooks[0]; + + const result = await callback( + makeHookInput({ + hook_event_name: "PreToolUse", + tool_name: "Bash", + tool_input: { command: "git push -f origin main" }, + }), + undefined, + { signal: new AbortController().signal }, + ); + + expect(result).toHaveProperty("decision", "block"); + }); + + test("blocks git push with +refspec prefix", async () => { + const hook = createDangerousCommandBlocker(); + const callback = hook.hooks[0]; + + const result = await callback( + makeHookInput({ + hook_event_name: "PreToolUse", + tool_name: "Bash", + tool_input: { command: "git push origin +main:main" }, + }), + undefined, + { signal: new AbortController().signal }, + ); + + expect(result).toHaveProperty("decision", "block"); + }); + + test("blocks git push with quoted +refspec prefix", async () => { + const hook = createDangerousCommandBlocker(); + const callback = hook.hooks[0]; + + const result = await callback( + makeHookInput({ + hook_event_name: "PreToolUse", + tool_name: "Bash", + tool_input: { + command: 'git push origin "+HEAD:refs/heads/main"', + }, + }), + undefined, + { signal: new AbortController().signal }, + ); + + expect(result).toHaveProperty("decision", "block"); + }); + test("blocks docker system prune", async () => { const hook = createDangerousCommandBlocker(); const callback = hook.hooks[0]; diff --git a/src/agent/hooks.ts b/src/agent/hooks.ts index 2d1460f..45b96c5 100644 --- a/src/agent/hooks.ts +++ b/src/agent/hooks.ts @@ -14,6 +14,8 @@ const DANGEROUS_COMMANDS: { pattern: RegExp; label: string }[] = [ { pattern: /docker\s+volume\s+prune/, label: "docker volume prune" }, { pattern: /docker\s+system\s+prune/, label: "docker system prune" }, { pattern: /git\s+push\s+.*--force/, label: "git push --force" }, + { pattern: /git\s+push\s+.*-f(?:\s|$)/, label: "git push -f" }, + { pattern: /git\s+push\s+.*\s["']?\+\S/, label: "git push +refspec" }, { pattern: /git\s+reset\s+--hard/, label: "git reset --hard" }, { pattern: /rm\s+-rf\s+\/(\s|$)/, label: "rm -rf /" }, { pattern: /rm\s+-rf\s+\/home(\s|$)/, label: "rm -rf /home" },