mirror of
https://github.com/trailofbits/skills.git
synced 2026-09-27 09:29:06 +00:00
fp-check: Stop/SubagentStop prompt hooks block every non-fp-check session ("approve" has no mapping to the ok schema) #342
Labels
No labels
blocked:CLA-unsigned
blocked ❌
bug 🐛
claude-code-assisted
component:CI/CD 🤖
component:documentation 📖
component:tests 🧪
dependencies
duplicate 👯
enhancement ✨
github_actions
good first issue
help wanted
invalid
no-version-bump
platform:linux 🐧
platform:macos 🍎
platform:windows 🪟
priority:high
priority:low
priority:medium
python
question ❓
security ⚠️
upstream 🔼
waiting-on-reporter 🕐
wontfix
No milestone
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
skills/trailofbits-skills#342
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Title: fp-check: Stop/SubagentStop prompt hooks block every non-fp-check session ("approve" has no mapping to the
okschema)Plugin:
fp-check@trailofbits1.0.0,plugins/fp-check/hooks/hooks.jsonWhat happens
With fp-check installed at user scope, the
Stophook fires in every Claude Code session ("matcher": "*"). In sessions that have nothing to do with fp-check, it blocks the agent from stopping. The hook's own reasoning says the session should be approved:It still returns a blocking result. I saw this 6+ times in a single session on a non-security task. Each block forces the agent into another turn.
Cause
The prompts tell the evaluating model to "return 'approve'" or "return 'block'". A
type: "prompt"hook's response, though, must be{"ok": boolean, "reason": string}. Nothing tells the model how "approve" maps onto that shape, so it often returnsok: falsewith "approve" written inreason, which blocks.SubagentStophas the same wording ("If the agent is not an fp-check agent, return 'approve'").Suggested fix
Replace the last three lines of each prompt with explicit
okvalues, and put the not-fp-check case first. The checklists above them stay unchanged.Worth considering
Because the matcher is
*, every stop in every session pays for a model call (30 s timeout). The hook could run only while fp-check is actually in use, for example with a marker file the skill writes and acommandhook that exits 0 immediately when the marker is absent. That would remove the cost as well as the false blocks.