From 2391b4daef330b937322c9b2dbe08522eeb75841 Mon Sep 17 00:00:00 2001 From: deveshu Date: Tue, 13 Oct 2026 10:33:15 +0530 Subject: [PATCH 1/2] Stop claiming PostToolUse blocks --- __tests__/e2e/helpers/hook-runner.ts | 2 +- .../fixtures/two-tier/unconfigured-golden.json | 14 +++++++------- __tests__/hooks/policy-evaluator.test.ts | 4 ++-- src/hooks/policy-evaluator.ts | 11 +++++++---- 4 files changed, 17 insertions(+), 14 deletions(-) diff --git a/__tests__/e2e/helpers/hook-runner.ts b/__tests__/e2e/helpers/hook-runner.ts index 7252ebf43..6e98c26ad 100644 --- a/__tests__/e2e/helpers/hook-runner.ts +++ b/__tests__/e2e/helpers/hook-runner.ts @@ -104,7 +104,7 @@ export function assertPermissionRequestDeny(result: HookRunResult): void { export function assertPostToolUseDeny(result: HookRunResult): void { expect(result.exitCode).toBe(0); const output = result.parsed?.hookSpecificOutput as Record | undefined; - expect(output?.additionalContext).toMatch(/Blocked/i); + expect(output?.additionalContext).toMatch(/Flagged/i); } /** diff --git a/__tests__/fixtures/two-tier/unconfigured-golden.json b/__tests__/fixtures/two-tier/unconfigured-golden.json index fa808d859..d29567daf 100644 --- a/__tests__/fixtures/two-tier/unconfigured-golden.json +++ b/__tests__/fixtures/two-tier/unconfigured-golden.json @@ -75,7 +75,7 @@ "{\"exitCode\":0,\"stdout\":\"{\\\"decision\\\":\\\"continue\\\",\\\"reason\\\":\\\"MANDATORY ACTION REQUIRED from failproofai (policies: failproofai/p-inst, custom/p-inst2): do x first\\\\nand y\\\\n\\\\nYou MUST complete the above action(s) NOW. Do NOT ask the user for confirmation \u2014 execute the required action(s), then attempt to finish your task again.\\\"}\",\"stderr\":\"\",\"policyName\":\"failproofai/p-inst\",\"policyNames\":[\"failproofai/p-inst\",\"custom/p-inst2\"],\"reason\":\"do x first\\nand y\",\"decision\":\"instruct\"}", "{\"exitCode\":0,\"stdout\":\"{\\\"hookSpecificOutput\\\":{\\\"hookEventName\\\":\\\"PreToolUse\\\",\\\"permissionDecision\\\":\\\"deny\\\",\\\"permissionDecisionReason\\\":\\\"Blocked Bash by failproofai because: not allowed, as per the policy configured by the user\\\"}}\",\"stderr\":\"\",\"policyName\":\"failproofai/p-deny\",\"reason\":\"not allowed\",\"decision\":\"deny\"}", "{\"exitCode\":0,\"stdout\":\"{\\\"hookSpecificOutput\\\":{\\\"hookEventName\\\":\\\"PermissionRequest\\\",\\\"decision\\\":{\\\"behavior\\\":\\\"deny\\\",\\\"message\\\":\\\"Blocked Bash by failproofai because: not allowed, as per the policy configured by the user\\\"}}}\",\"stderr\":\"\",\"policyName\":\"failproofai/p-deny\",\"reason\":\"not allowed\",\"decision\":\"deny\"}", - "{\"exitCode\":0,\"stdout\":\"{\\\"hookSpecificOutput\\\":{\\\"hookEventName\\\":\\\"PostToolUse\\\",\\\"additionalContext\\\":\\\"Blocked Bash by failproofai because: not allowed, as per the policy configured by the user\\\"}}\",\"stderr\":\"\",\"policyName\":\"failproofai/p-deny\",\"reason\":\"not allowed\",\"decision\":\"deny\"}", + "{\"exitCode\":0,\"stdout\":\"{\\\"hookSpecificOutput\\\":{\\\"hookEventName\\\":\\\"PostToolUse\\\",\\\"additionalContext\\\":\\\"Flagged Bash output by failproofai because: not allowed, as per the policy configured by the user\\\"}}\",\"stderr\":\"\",\"policyName\":\"failproofai/p-deny\",\"reason\":\"not allowed\",\"decision\":\"deny\"}", "{\"exitCode\":2,\"stdout\":\"\",\"stderr\":\"not allowed\",\"policyName\":\"failproofai/p-deny\",\"reason\":\"not allowed\",\"decision\":\"deny\"}", "{\"exitCode\":2,\"stdout\":\"\",\"stderr\":\"MANDATORY ACTION REQUIRED from failproofai (policy: failproofai/p-deny): not allowed\\n\\nYou MUST complete the above action NOW. Do NOT ask the user for confirmation \u2014 execute the required action, then attempt to finish your task again.\",\"policyName\":\"failproofai/p-deny\",\"reason\":\"not allowed\",\"decision\":\"deny\"}", "{\"exitCode\":0,\"stdout\":\"{\\\"decision\\\":\\\"block\\\",\\\"reason\\\":\\\"Blocked Bash by failproofai because: not allowed, as per the policy configured by the user\\\"}\",\"stderr\":\"\",\"policyName\":\"failproofai/p-deny\",\"reason\":\"not allowed\",\"decision\":\"deny\"}", @@ -107,7 +107,7 @@ "{\"exitCode\":0,\"stdout\":\"{\\\"decision\\\":\\\"deny\\\",\\\"reason\\\":\\\"Blocked session start by failproofai because: not allowed, as per the policy configured by the user\\\"}\",\"stderr\":\"\",\"policyName\":\"failproofai/p-deny\",\"reason\":\"not allowed\",\"decision\":\"deny\"}", "{\"exitCode\":0,\"stdout\":\"{\\\"hookSpecificOutput\\\":{\\\"hookEventName\\\":\\\"PreToolUse\\\",\\\"permissionDecision\\\":\\\"deny\\\",\\\"permissionDecisionReason\\\":\\\"Blocked Bash by failproofai because: Blocked by policy: failproofai/p-deny, as per the policy configured by the user\\\"}}\",\"stderr\":\"\",\"policyName\":\"failproofai/p-deny\",\"reason\":\"Blocked by policy: failproofai/p-deny\",\"decision\":\"deny\"}", "{\"exitCode\":0,\"stdout\":\"{\\\"hookSpecificOutput\\\":{\\\"hookEventName\\\":\\\"PermissionRequest\\\",\\\"decision\\\":{\\\"behavior\\\":\\\"deny\\\",\\\"message\\\":\\\"Blocked Bash by failproofai because: Blocked by policy: failproofai/p-deny, as per the policy configured by the user\\\"}}}\",\"stderr\":\"\",\"policyName\":\"failproofai/p-deny\",\"reason\":\"Blocked by policy: failproofai/p-deny\",\"decision\":\"deny\"}", - "{\"exitCode\":0,\"stdout\":\"{\\\"hookSpecificOutput\\\":{\\\"hookEventName\\\":\\\"PostToolUse\\\",\\\"additionalContext\\\":\\\"Blocked Bash by failproofai because: Blocked by policy: failproofai/p-deny, as per the policy configured by the user\\\"}}\",\"stderr\":\"\",\"policyName\":\"failproofai/p-deny\",\"reason\":\"Blocked by policy: failproofai/p-deny\",\"decision\":\"deny\"}", + "{\"exitCode\":0,\"stdout\":\"{\\\"hookSpecificOutput\\\":{\\\"hookEventName\\\":\\\"PostToolUse\\\",\\\"additionalContext\\\":\\\"Flagged Bash output by failproofai because: Blocked by policy: failproofai/p-deny, as per the policy configured by the user\\\"}}\",\"stderr\":\"\",\"policyName\":\"failproofai/p-deny\",\"reason\":\"Blocked by policy: failproofai/p-deny\",\"decision\":\"deny\"}", "{\"exitCode\":2,\"stdout\":\"\",\"stderr\":\"Blocked by policy: failproofai/p-deny\",\"policyName\":\"failproofai/p-deny\",\"reason\":\"Blocked by policy: failproofai/p-deny\",\"decision\":\"deny\"}", "{\"exitCode\":2,\"stdout\":\"\",\"stderr\":\"MANDATORY ACTION REQUIRED from failproofai (policy: failproofai/p-deny): Blocked by policy: failproofai/p-deny\\n\\nYou MUST complete the above action NOW. Do NOT ask the user for confirmation \u2014 execute the required action, then attempt to finish your task again.\",\"policyName\":\"failproofai/p-deny\",\"reason\":\"Blocked by policy: failproofai/p-deny\",\"decision\":\"deny\"}", "{\"exitCode\":0,\"stdout\":\"{\\\"decision\\\":\\\"block\\\",\\\"reason\\\":\\\"Blocked Bash by failproofai because: Blocked by policy: failproofai/p-deny, as per the policy configured by the user\\\"}\",\"stderr\":\"\",\"policyName\":\"failproofai/p-deny\",\"reason\":\"Blocked by policy: failproofai/p-deny\",\"decision\":\"deny\"}", @@ -139,7 +139,7 @@ "{\"exitCode\":0,\"stdout\":\"{\\\"decision\\\":\\\"deny\\\",\\\"reason\\\":\\\"Blocked session start by failproofai because: Blocked by policy: failproofai/p-deny, as per the policy configured by the user\\\"}\",\"stderr\":\"\",\"policyName\":\"failproofai/p-deny\",\"reason\":\"Blocked by policy: failproofai/p-deny\",\"decision\":\"deny\"}", "{\"exitCode\":0,\"stdout\":\"{\\\"hookSpecificOutput\\\":{\\\"hookEventName\\\":\\\"PreToolUse\\\",\\\"permissionDecision\\\":\\\"deny\\\",\\\"permissionDecisionReason\\\":\\\"Blocked Bash by failproofai because: first, as per the policy configured by the user\\\"}}\",\"stderr\":\"\",\"policyName\":\"failproofai/p-deny\",\"reason\":\"first\",\"decision\":\"deny\"}", "{\"exitCode\":0,\"stdout\":\"{\\\"hookSpecificOutput\\\":{\\\"hookEventName\\\":\\\"PermissionRequest\\\",\\\"decision\\\":{\\\"behavior\\\":\\\"deny\\\",\\\"message\\\":\\\"Blocked Bash by failproofai because: first, as per the policy configured by the user\\\"}}}\",\"stderr\":\"\",\"policyName\":\"failproofai/p-deny\",\"reason\":\"first\",\"decision\":\"deny\"}", - "{\"exitCode\":0,\"stdout\":\"{\\\"hookSpecificOutput\\\":{\\\"hookEventName\\\":\\\"PostToolUse\\\",\\\"additionalContext\\\":\\\"Blocked Bash by failproofai because: first, as per the policy configured by the user\\\"}}\",\"stderr\":\"\",\"policyName\":\"failproofai/p-deny\",\"reason\":\"first\",\"decision\":\"deny\"}", + "{\"exitCode\":0,\"stdout\":\"{\\\"hookSpecificOutput\\\":{\\\"hookEventName\\\":\\\"PostToolUse\\\",\\\"additionalContext\\\":\\\"Flagged Bash output by failproofai because: first, as per the policy configured by the user\\\"}}\",\"stderr\":\"\",\"policyName\":\"failproofai/p-deny\",\"reason\":\"first\",\"decision\":\"deny\"}", "{\"exitCode\":2,\"stdout\":\"\",\"stderr\":\"first\",\"policyName\":\"failproofai/p-deny\",\"reason\":\"first\",\"decision\":\"deny\"}", "{\"exitCode\":2,\"stdout\":\"\",\"stderr\":\"MANDATORY ACTION REQUIRED from failproofai (policy: failproofai/p-deny): first\\n\\nYou MUST complete the above action NOW. Do NOT ask the user for confirmation \u2014 execute the required action, then attempt to finish your task again.\",\"policyName\":\"failproofai/p-deny\",\"reason\":\"first\",\"decision\":\"deny\"}", "{\"exitCode\":0,\"stdout\":\"{\\\"decision\\\":\\\"block\\\",\\\"reason\\\":\\\"Blocked Bash by failproofai because: first, as per the policy configured by the user\\\"}\",\"stderr\":\"\",\"policyName\":\"failproofai/p-deny\",\"reason\":\"first\",\"decision\":\"deny\"}", @@ -190,7 +190,7 @@ "{\"exitCode\":0,\"stdout\":\"{\\\"decision\\\":\\\"continue\\\",\\\"reason\\\":\\\"MANDATORY ACTION REQUIRED from failproofai (policy: custom/p-inst): after a crash\\\\n\\\\nYou MUST complete the above action(s) NOW. Do NOT ask the user for confirmation \u2014 execute the required action(s), then attempt to finish your task again.\\\"}\",\"stderr\":\"\",\"policyName\":\"custom/p-inst\",\"policyNames\":[\"custom/p-inst\"],\"reason\":\"after a crash\",\"decision\":\"instruct\"}", "{\"exitCode\":0,\"stdout\":\"{\\\"hookSpecificOutput\\\":{\\\"hookEventName\\\":\\\"PreToolUse\\\",\\\"permissionDecision\\\":\\\"deny\\\",\\\"permissionDecisionReason\\\":\\\"Blocked Bash by failproofai because: not allowed. use the staging db, as per the policy configured by the user\\\"}}\",\"stderr\":\"\",\"policyName\":\"failproofai/p-deny\",\"reason\":\"not allowed. use the staging db\",\"decision\":\"deny\"}", "{\"exitCode\":0,\"stdout\":\"{\\\"hookSpecificOutput\\\":{\\\"hookEventName\\\":\\\"PermissionRequest\\\",\\\"decision\\\":{\\\"behavior\\\":\\\"deny\\\",\\\"message\\\":\\\"Blocked Bash by failproofai because: not allowed. use the staging db, as per the policy configured by the user\\\"}}}\",\"stderr\":\"\",\"policyName\":\"failproofai/p-deny\",\"reason\":\"not allowed. use the staging db\",\"decision\":\"deny\"}", - "{\"exitCode\":0,\"stdout\":\"{\\\"hookSpecificOutput\\\":{\\\"hookEventName\\\":\\\"PostToolUse\\\",\\\"additionalContext\\\":\\\"Blocked Bash by failproofai because: not allowed. use the staging db, as per the policy configured by the user\\\"}}\",\"stderr\":\"\",\"policyName\":\"failproofai/p-deny\",\"reason\":\"not allowed. use the staging db\",\"decision\":\"deny\"}", + "{\"exitCode\":0,\"stdout\":\"{\\\"hookSpecificOutput\\\":{\\\"hookEventName\\\":\\\"PostToolUse\\\",\\\"additionalContext\\\":\\\"Flagged Bash output by failproofai because: not allowed. use the staging db, as per the policy configured by the user\\\"}}\",\"stderr\":\"\",\"policyName\":\"failproofai/p-deny\",\"reason\":\"not allowed. use the staging db\",\"decision\":\"deny\"}", "{\"exitCode\":2,\"stdout\":\"\",\"stderr\":\"not allowed. use the staging db\",\"policyName\":\"failproofai/p-deny\",\"reason\":\"not allowed. use the staging db\",\"decision\":\"deny\"}", "{\"exitCode\":2,\"stdout\":\"\",\"stderr\":\"MANDATORY ACTION REQUIRED from failproofai (policy: failproofai/p-deny): not allowed. use the staging db\\n\\nYou MUST complete the above action NOW. Do NOT ask the user for confirmation \u2014 execute the required action, then attempt to finish your task again.\",\"policyName\":\"failproofai/p-deny\",\"reason\":\"not allowed. use the staging db\",\"decision\":\"deny\"}", "{\"exitCode\":0,\"stdout\":\"{\\\"decision\\\":\\\"block\\\",\\\"reason\\\":\\\"Blocked Bash by failproofai because: not allowed. use the staging db, as per the policy configured by the user\\\"}\",\"stderr\":\"\",\"policyName\":\"failproofai/p-deny\",\"reason\":\"not allowed. use the staging db\",\"decision\":\"deny\"}", @@ -276,9 +276,9 @@ "{\"exitCode\":0,\"stdout\":\"\",\"stderr\":\"\",\"evaluation\":{\"decision\":\"allow\",\"policyName\":null,\"policyNames\":[],\"reason\":null,\"matchedPolicies\":\"4ee41d5ded79645ec5b432eb\",\"toolName\":\"mcp__github__delete_repo\"}}", "{\"exitCode\":0,\"stdout\":\"{\\\"hookSpecificOutput\\\":{\\\"hookEventName\\\":\\\"PermissionRequest\\\",\\\"decision\\\":{\\\"behavior\\\":\\\"deny\\\",\\\"message\\\":\\\"Blocked Bash by failproofai because: sudo commands are blocked, as per the policy configured by the user\\\"}}}\",\"stderr\":\"\",\"evaluation\":{\"decision\":\"deny\",\"policyName\":\"failproofai/block-sudo\",\"policyNames\":[\"failproofai/block-sudo\"],\"reason\":\"sudo commands are blocked\",\"matchedPolicies\":\"a37448f70f44189f727efb05\",\"toolName\":\"Bash\"}}", "{\"exitCode\":0,\"stdout\":\"\",\"stderr\":\"\",\"evaluation\":{\"decision\":\"allow\",\"policyName\":null,\"policyNames\":[],\"reason\":null,\"matchedPolicies\":\"a37448f70f44189f727efb05\",\"toolName\":\"Bash\"}}", - "{\"exitCode\":0,\"stdout\":\"{\\\"hookSpecificOutput\\\":{\\\"hookEventName\\\":\\\"PostToolUse\\\",\\\"additionalContext\\\":\\\"Blocked Bash by failproofai because: JWT token detected in tool output, as per the policy configured by the user\\\"}}\",\"stderr\":\"\",\"evaluation\":{\"decision\":\"deny\",\"policyName\":\"failproofai/sanitize-jwt\",\"policyNames\":[\"failproofai/sanitize-jwt\"],\"reason\":\"JWT token detected in tool output\",\"matchedPolicies\":\"f631901f4dafea29cc21aefa\",\"toolName\":\"Bash\"}}", - "{\"exitCode\":0,\"stdout\":\"{\\\"hookSpecificOutput\\\":{\\\"hookEventName\\\":\\\"PostToolUse\\\",\\\"additionalContext\\\":\\\"Blocked Bash by failproofai because: Private key content detected in tool output, as per the policy configured by the user\\\"}}\",\"stderr\":\"\",\"evaluation\":{\"decision\":\"deny\",\"policyName\":\"failproofai/sanitize-private-key-content\",\"policyNames\":[\"failproofai/sanitize-private-key-content\"],\"reason\":\"Private key content detected in tool output\",\"matchedPolicies\":\"f631901f4dafea29cc21aefa\",\"toolName\":\"Bash\"}}", - "{\"exitCode\":0,\"stdout\":\"{\\\"hookSpecificOutput\\\":{\\\"hookEventName\\\":\\\"PostToolUse\\\",\\\"additionalContext\\\":\\\"Blocked Bash by failproofai because: Database connection string with credentials detected in tool output, as per the policy configured by the user\\\"}}\",\"stderr\":\"\",\"evaluation\":{\"decision\":\"deny\",\"policyName\":\"failproofai/sanitize-connection-strings\",\"policyNames\":[\"failproofai/sanitize-connection-strings\"],\"reason\":\"Database connection string with credentials detected in tool output\",\"matchedPolicies\":\"f631901f4dafea29cc21aefa\",\"toolName\":\"Bash\"}}", + "{\"exitCode\":0,\"stdout\":\"{\\\"hookSpecificOutput\\\":{\\\"hookEventName\\\":\\\"PostToolUse\\\",\\\"additionalContext\\\":\\\"Flagged Bash output by failproofai because: JWT token detected in tool output, as per the policy configured by the user\\\"}}\",\"stderr\":\"\",\"evaluation\":{\"decision\":\"deny\",\"policyName\":\"failproofai/sanitize-jwt\",\"policyNames\":[\"failproofai/sanitize-jwt\"],\"reason\":\"JWT token detected in tool output\",\"matchedPolicies\":\"f631901f4dafea29cc21aefa\",\"toolName\":\"Bash\"}}", + "{\"exitCode\":0,\"stdout\":\"{\\\"hookSpecificOutput\\\":{\\\"hookEventName\\\":\\\"PostToolUse\\\",\\\"additionalContext\\\":\\\"Flagged Bash output by failproofai because: Private key content detected in tool output, as per the policy configured by the user\\\"}}\",\"stderr\":\"\",\"evaluation\":{\"decision\":\"deny\",\"policyName\":\"failproofai/sanitize-private-key-content\",\"policyNames\":[\"failproofai/sanitize-private-key-content\"],\"reason\":\"Private key content detected in tool output\",\"matchedPolicies\":\"f631901f4dafea29cc21aefa\",\"toolName\":\"Bash\"}}", + "{\"exitCode\":0,\"stdout\":\"{\\\"hookSpecificOutput\\\":{\\\"hookEventName\\\":\\\"PostToolUse\\\",\\\"additionalContext\\\":\\\"Flagged Bash output by failproofai because: Database connection string with credentials detected in tool output, as per the policy configured by the user\\\"}}\",\"stderr\":\"\",\"evaluation\":{\"decision\":\"deny\",\"policyName\":\"failproofai/sanitize-connection-strings\",\"policyNames\":[\"failproofai/sanitize-connection-strings\"],\"reason\":\"Database connection string with credentials detected in tool output\",\"matchedPolicies\":\"f631901f4dafea29cc21aefa\",\"toolName\":\"Bash\"}}", "{\"exitCode\":0,\"stdout\":\"\",\"stderr\":\"\",\"evaluation\":{\"decision\":\"allow\",\"policyName\":null,\"policyNames\":[],\"reason\":null,\"matchedPolicies\":\"f631901f4dafea29cc21aefa\",\"toolName\":\"Bash\"}}", "{\"exitCode\":0,\"stdout\":\"\",\"stderr\":\"\",\"evaluation\":{\"decision\":\"allow\",\"policyName\":null,\"policyNames\":[],\"reason\":null,\"matchedPolicies\":\"4f53cda18c2baa0c0354bb5f\",\"toolName\":null}}", "{\"exitCode\":0,\"stdout\":\"{\\\"decision\\\":\\\"block\\\",\\\"reason\\\":\\\"Blocked Bash by failproofai because: JWT token detected in tool output, as per the policy configured by the user\\\"}\",\"stderr\":\"\",\"evaluation\":{\"decision\":\"deny\",\"policyName\":\"failproofai/sanitize-jwt\",\"policyNames\":[\"failproofai/sanitize-jwt\"],\"reason\":\"JWT token detected in tool output\",\"matchedPolicies\":\"f631901f4dafea29cc21aefa\",\"toolName\":\"Bash\"}}", diff --git a/__tests__/hooks/policy-evaluator.test.ts b/__tests__/hooks/policy-evaluator.test.ts index f5a2586a3..c9e5af3fe 100644 --- a/__tests__/hooks/policy-evaluator.test.ts +++ b/__tests__/hooks/policy-evaluator.test.ts @@ -65,7 +65,7 @@ describe("hooks/policy-evaluator", () => { const parsed = JSON.parse(result.stdout); expect(parsed.hookSpecificOutput.hookEventName).toBe("PostToolUse"); expect(parsed.hookSpecificOutput.additionalContext).toBe( - "Blocked Read by failproofai because: JWT found, as per the policy configured by the user", + "Flagged Read output by failproofai because: JWT found, as per the policy configured by the user", ); expect(result.policyName).toBe("failproofai/jwt-scrub"); expect(result.reason).toBe("JWT found"); @@ -120,7 +120,7 @@ describe("hooks/policy-evaluator", () => { expect(parsed.decision).toBeUndefined(); expect( (parsed.hookSpecificOutput as Record).additionalContext, - ).toBe("Blocked Read by failproofai because: JWT found, as per the policy configured by the user"); + ).toBe("Flagged Read output by failproofai because: JWT found, as per the policy configured by the user"); }); it("other event types use exit 2 for deny", async () => { diff --git a/src/hooks/policy-evaluator.ts b/src/hooks/policy-evaluator.ts index 1e7cccf00..2387c9e43 100644 --- a/src/hooks/policy-evaluator.ts +++ b/src/hooks/policy-evaluator.ts @@ -412,9 +412,10 @@ function formatDeny( displayTool = "operation"; } // Jev's reason is its own sentences, ending in "."; no user configured the check. - const blockedMessage = byJev - ? `Blocked ${displayTool} by failproofai because: ${reason.replace(/[.\s]+$/, "")}, as flagged by Jev semantic review` - : `Blocked ${displayTool} by failproofai because: ${reason}, as per the policy configured by the user`; + const because = byJev + ? `because: ${reason.replace(/[.\s]+$/, "")}, as flagged by Jev semantic review` + : `because: ${reason}, as per the policy configured by the user`; + const blockedMessage = `Blocked ${displayTool} by failproofai ${because}`; // Cursor's hook protocol expects a flat `{permission, user_message, // agent_message}` shape for any blocking decision, regardless of which @@ -797,10 +798,12 @@ function formatDeny( decision: "deny", }; } + // additionalContext only adds a note: the output has already reached the + // model, so do not tell it the call was blocked. const response = { hookSpecificOutput: { hookEventName: eventType, - additionalContext: blockedMessage, + additionalContext: `Flagged ${displayTool} output by failproofai ${because}`, }, }; return { From 1eb8f7daa83390123aaf1e1b46b310004d64c7c6 Mon Sep 17 00:00:00 2001 From: deveshu Date: Tue, 13 Oct 2026 10:34:14 +0530 Subject: [PATCH 2/2] Add changelog entry --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e1576b070..fe6955448 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## 1.0.11-beta.0 — 2026-10-13 + +### Fixes + +- A PostToolUse deny on Claude Code and OpenCode now tells the model the output was flagged, not that the call was blocked: the tool had already run and its output had already reached the model (#882) + ## 1.0.10 — 2026-10-05 Action needed if you use `instruct` policies with Hermes: an `instruct` no longer stops the call it reminds about. The call runs and the reminder is placed first in its result, so a policy written to prevent an action (for example, a direct API write that should go through an approved script) must become a `deny` before you upgrade. Hermes 0.20.0 is supported again: on 1.0.9 the plugin loaded there with no hooks and every tool call ran unchecked. After upgrading, run `failproofai update` and restart each Hermes gateway profile by name. Collects 1.0.10-beta.0 to beta.1 below.