| Hook | Fires on | The one question |
|---|---|---|
dependency-guard | PreToolUse on a shell call, and on Edit/Write to a manifest | Is the dependency about to land acceptable under this repository’s Safe Harbour policy? |
change-guard | PreToolUse on git commit and git push | Does the change about to be recorded carry a credential? |
session-context | SessionStart, and UserPromptSubmit | What did the last scan find, and does the CVE you just named reach this repository? |
One command, every agent
All three are vulnetix agent hook, reading the host’s payload on stdin and
writing the host’s response on stdout. One implementation serves Claude Code and
Codex alike, and it runs on native Windows — which the fifteen bash scripts it
replaced never did.
Wire it up with:
vulnetix agent install
The response contract
Measured against claude and codex directly, because the docs disagreed with
themselves. Exactly two shapes are portable, and only these two are emitted:
// inform, without interrupting
{"hookSpecificOutput":{"hookEventName":"PreToolUse","additionalContext":"…"}}
// block, with a reason the model can act on
{"hookSpecificOutput":{"hookEventName":"PreToolUse",
"permissionDecision":"deny","permissionDecisionReason":"…"}}
permissionDecision: "allow" is never emitted. Codex fails the hook on it,
and omitting the field is the honest spelling anyway: the hook is not granting
permission, it is adding what it knows.
systemMessage is not used either. It surfaces to the user, not into the
model’s context — so an implementation built on it never tells the one actor that
could act on the finding.
Never blocks on not knowing
An unparseable manifest, an unreachable API, a missing credential, a timeout: all of these produce silence, not a refusal. Absence of an answer is not a verdict.
dependency-guard
Fires on: PreToolUse on a shell call, and on Edit/Write to a manifest
Answers: Is the dependency about to land acceptable under this repository’s Safe Harbour policy?
Computes the Safe Harbour target for the package under the configured strategy (safest, stable or latest). If what is about to land is at or better than that target it prints nothing at all — silence when the policy is satisfied is what makes a guard liveable. Otherwise it reports the verdict into the agent’s context, and blocks only for what is never the right call: a known-malicious package, or a critical advisory being exploited in the wild.
change-guard
Fires on: PreToolUse on git commit and git push
Answers: Does the change about to be recorded carry a credential?
Reads only what the command would actually record — the index, plus the working tree for git commit -a, or the commits a push has not sent — so a pre-existing finding is not re-reported on every commit. Detection is the same secret rules vulnetix secrets runs, so the two cannot disagree about the same file.
session-context
Fires on: SessionStart, and UserPromptSubmit
Answers: What did the last scan find, and does the CVE you just named reach this repository?
Reads the recorded scan rather than scanning now, because this runs before the turn and the budget is a person waiting at a prompt. It says it is a snapshot rather than implying freshness it did not pay for, and it answers “not in this repository’s last scan” out loud — silence there would read as “not affected”, which is a much stronger claim.