response#
Detection library for prompt-injection compromise of LLMs that consume web-tool output.
Part of badger — pairs with badger-fetch (prevention) and the runtime adapters response-claude / response-opencode (host integration).
Install#
pnpm add response
Usage#
import { detectCompromise, consoleReporter } from "response";
const findings = detectCompromise({
assistantMessage: response.choices[0].message, // the LLM turn under examination
history: request.messages, // OpenRouter-shaped ChatMessage[] (incl. tool results)
watchedTools: ["fetch"], // optional: restrict echo detection
});
consoleReporter.report(findings);
Detectors#
| Function | Returns | What it answers |
|---|---|---|
detectCompromise(input) |
CompromiseFinding[] |
Did the assistant get compromised by a tool result? (echo correlation) |
detectInjection(text) |
InjectionFinding[] |
Does this text contain a known injection, and how was it hidden? |
detectObfuscation(text) |
ObfuscationFinding[] |
Is this text suspiciously obfuscated at all? (presence-based) |
detectExfiltration(text) |
ExfiltrationFinding[] |
Does this content try to leak data outward? (e.g. external <img> beacons) |
detectInjection owns one validated rule set (named Rule[]) and matches through layered, evasion-aware
views — each InjectionFinding carries a patternId, a category (raw/despace/zero_width/nfkc/
homoglyph/base64/hex/typoglycemia), the matched span, and the decoded payload when relevant. It is the
single source of truth shared by badger-fetch. Severity is left to a separate scoring layer. See
../../CONTEXT.md for the domain model.
Compromise categories#
| Category | Severity | Signal |
|---|---|---|
literal_injection_marker |
high | Assistant emits a known injection-success marker (marker list is eval-derived; empty in v1) |
echoed_injection_payload |
medium | Assistant repeats an injection pattern that was present in a tool result |
Planned (see docs/plans/monorepo-and-response.md):
off_task_tool_call, credential_in_proposed_url, prompt_revealed. (url_exfiltration is now served by
detectExfiltration.)
Reporters#
| Reporter | What it does |
|---|---|
consoleReporter |
One stderr line per finding |
fileReporter(path?) |
Append JSONL to file (default: ~/.response/findings.jsonl) |
silentReporter |
No-op; used in tests and for callers that only consume the return value |
All implement the Reporter interface, so callers can write custom ones (Slack webhook, telemetry sink, etc.).