PostHog / PostHog/wizard

Refactor PostToolUse hook scaffold to centralize fail-closed policy

Open
#532 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

wizard-pain
Dominant language
TypeScript
Stars
197
Forks
51
Avg merge
1d 23h
Merged PRs (30d)
94

Description

Why

The PostToolUse handlers in `src/lib/yara-hooks.ts` (Write/Edit, Read/Grep, skill install) and the PreToolUse Bash handler all repeat the same scaffold:

  1. typeof-narrow `tool_name`
  2. extract a string field from `tool_input` or `tool_response`
  3. `recordScan()`
  4. `await scanAndTriage(...)`
  5. early-return if no matches
  6. `highestSeverityMatch` + `recordMatch` + return-or-onTerminate
  7. an outer `try/catch` that fails closed

Each of the four handlers has its own copy of step 7 — the fail-closed catch block. Three of them call `onTerminate?.()`; the fourth (Write/Edit) used to return `additionalContext` until very recently. The "fail closed on scanner error" invariant is enforced by reviewer discipline, not by a wrapper or a type.

A future handler (e.g. NotebookEdit, MCP tool output) is one easy mistake away from forgetting the fail-closed return entirely — at which point a scanner crash silently lets the violation through with no test or type to catch it.

Proposal

Extract a `withScanHook` higher-order helper:

```ts
function withScanHook(opts: {
extractContent: (input: HookInput) => string | null;
ctx: ScanContext;
llmProvider: LLMProvider | undefined;
onMatches: (matches: ScanMatch[], input: HookInput) => TResponse;
onScannerError: () => TResponse; // fail-closed response, typed
}): (input: HookInput) => Promise;
```

Each hook becomes a small declaration that only describes:

  • how to extract content for THIS surface
  • what to do when matches survive triage

The fail-closed try/catch lives in one place. The "this is the fail-closed response" decision is forced to be explicit at the type level.

Why this is its own ticket (not bundled with the YARA-X migration)

The refactor crosses every security path in the file. Doing it in the same PR as the warlock migration mixes two reasons to change one file. Better to land warlock first, lock in the test surface, then refactor under green tests.

🤖 Generated with Claude Code

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in src/lib/yara-hooks.ts and read the four PostToolUse and PreToolUse handlers, especially their repeated fail-closed catch blocks and the existing scan flow. Implement the shared withScanHook scaffold after the warlock migration is complete, then verify that each handler declares its content extraction, match response, and typed scanner-error response while the existing tests remain green.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
security
Issue type
Refactor
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
55/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.