Injected-instruction detection

Published because it has to be. §19 refuses a safety score whose methodology is not published, on the grounds that a rating nobody can check is a rating nobody should believe. The same standard applies to our own detector: a publisher who fails this gate must be able to see what they tripped and disagree with it.

Implemented by @runbooks/lint; patterns are data in packages/lint/src/injection-patterns.ts and every one has a test.

What is forbidden, and what is not

A runbook is made of imperatives. §18.6 requires a step title to be an imperative verb phrase — "Restart the consumer group", not "Lag problem" — so a detector that keys on the imperative mood would block the catalog's own house style.

What is forbidden is addressing the reader. Every pattern keys on the model as addressee:

Class What it catches Severity
instruction-override overriding or discarding whatever instructions the reader already has error
role-assignment assigning the reader a role or persona error
system-prompt-mimicry text shaped like a conversation turn or a prompt boundary error
output-coercion dictating how the reader should answer, or what to conceal warning
tool-coercion telling the reader to skip an approval — the one thing a runbook may never say error
exfiltration sending credentials somewhere error
hidden-content text a human reviewer does not see and a parser does warning

The distinction is testable, and it is tested: every class ships with the malicious form and the legitimate phrasing it is most easily confused with. "Ignore all previous instructions" fires; "Ignore the stale replica and read from the primary" does not.

Obfuscation

Text is normalized before matching, and each transformation is applied as an additional view rather than a replacement, so a match reports how it was hiding:

Obfuscation raises the finding rather than evading it. Ordinary prose does not arrive in base64 with zero-width padding, so hiding a phrase is itself the strongest signal available.

A finding never quotes the payload

Not for the reason a secret is withheld, but a sharper one: this gate's output is read in a CI log, and a CI log is often read by an agent. Quoting "ignore previous instructions" into it would make the detector a delivery mechanism for the thing it detects.

A finding therefore carries the class, the pattern id, the JSON Pointer, and whether it was obfuscated. That is enough to find and fix it, and enough to argue with.

Limits

Stated rather than implied, per §13.5's standard: