You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
A Codex red-team (cross-model, after the 0.1.5 Opus reviews) caught a config-provenance
class the Opus reviews missed — verified against research/_results_published/:
- Cross-source: lead the SHIPPED 0.5B fixed config (mean AUROC 0.980; deepset 0.933,
safeguard 0.999, spml 0.990, jayavibhav 1.000 vs TF-IDF 0.914). The 0.984 is a nested-CV
research upper bound that is free to pick a larger 1.5B sensor per fold (deepset+spml
folds picked 1.5B) — now labeled as such, not as the shipped product number.
- Minpairs within-distribution: use the SHIPPED 0.5B (probe ~0.74 vs TF-IDF ~0.82 — a text
classifier slightly wins), not the 1.5B-selected ~0.79 "tie".
- Stop implying a win over named incumbents (ProtectAI DeBERTa, Meta Prompt Guard); our
only JSON-backed comparison is the same-data TF-IDF baseline. Removed the head-to-head
-vs-DeBERTa contradiction in COMPETITIVE_LANDSCAPE.
- Soften absolutes: "100% local, any CPU" -> "runs locally, CPU-only after one-time model
download, nothing uploaded"; "only shipped tool" -> "we have not found another";
"every dataset public / run them yourself" -> scripts+result JSONs committed, datasets
download from their original sources.
Applied across README, llms.txt, llms-full.txt, COMPETITIVE_LANDSCAPE, FAQ, REDDIT_LAUNCH,
ERRATUM. Tests: 12 passed. Bump 0.1.5 -> 0.1.6.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Copy file name to clipboardExpand all lines: README.md
+41-35Lines changed: 41 additions & 35 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -32,9 +32,9 @@ recall collapses. The probe holds up better across sources, because it keys off
32
32
internally represents the input rather than the exact words.
33
33
34
34
This is a **research preview**: a local, single-pass, registration-time review signal, not a hard
35
-
security boundary. Runs 100% local, any CPU, nothing uploaded. To our knowledge it is the only shipped
36
-
tool in this exact deployment shape — installable, scanning standalone tool/skill/MCP *descriptions*
37
-
before install, on model activations. It is **not** the first probe-based detector; there is a
35
+
security boundary. Runs locally (CPU-only, after a one-time ~1 GB model download); scan inputs and
36
+
results are never uploaded. We have not found another shipped tool in this exact deployment shape —
37
+
installable, scanning standalone tool/skill/MCP *descriptions*before install, on model activations. It is **not** the first probe-based detector; there is a
38
38
substantial body of prior and parallel work (see [Competitive landscape](#competitive-landscape)).
39
39
40
40
## Install in one command
@@ -114,8 +114,11 @@ judge; the deterministic label baseline flagged every clean curated item as pois
114
114
115
115
## Benchmarks
116
116
117
-
Everything here is reproducible from `research/`, on the **shipped Qwen2.5-0.5B** artifact. The point is
118
-
generalization to attacks it never trained on; the curated cross-source result backs it up with CIs.
117
+
Reproducible from `research/`: the experiment scripts and result JSONs are committed; the PI datasets are
118
+
downloaded from their original public sources (deepset, SafeGuard, SPML, jayavibhav, HackAPrompt on
119
+
Hugging Face). The point is generalization to attacks the probe never trained on. The HackAPrompt headline
120
+
runs on the shipped Qwen2.5-0.5B; the cross-source section below also reports a research upper bound that
121
+
lets the loop pick a larger 1.5B sensor.
119
122
120
123
**1. Generalization to unseen attacks: HackAPrompt (n=3,866 real attacks, a source neither detector trained on)**
121
124
@@ -139,32 +142,33 @@ instead, so it holds up. At the stricter 1% setting the gap is wider still (88%
139
142
so this is recall at a matched FPR set on the training clean data, not a full AUROC; the sample is
140
143
uniform-random over the corpus, not an exhaustive panel.
141
144
142
-
**2. Curated cross-source generalization: leave-one-source-out, nested CV, 4 real PI datasets**
145
+
**2. Curated cross-source generalization: leave-one-source-out, 4 real PI datasets**
143
146
144
147
Train on three of {deepset, safeguard, spml, jayavibhav}, test on the held-out fourth, repeat for each.
145
-
Model and layer are chosen inside a nested cross-validation loop, never on the held-out source. 95%
146
-
bootstrap CIs on the probe-minus-TF-IDF difference.
148
+
The **shipped fixed config** (Qwen2.5-0.5B, mean-pooled concat L13-15, no per-input picking) is the
@@ -182,20 +186,21 @@ The cross-source advantage extends to tool poisoning, but only partially — and
182
186
MCPTox is a clear win. Our own synthetic minimal-pairs set is out of distribution for both detectors,
183
187
and both sit at chance on it.
184
188
185
-
**Within-distribution, the text baseline is not blind.** On matched-vocabulary minimal pairs drawn from
186
-
the same distribution the probe was trained on, the probe **ties** TF-IDF (roughly 0.79 vs 0.82). The
187
-
edge is in generalizing to new sources and new vocabulary, not in same-vocabulary detection inside one
188
-
distribution.
189
+
**Within-distribution, the text baseline is not blind — it wins.** On matched-vocabulary minimal pairs
190
+
from the distribution the probe was trained on, the shipped 0.5B probe scores AUROC ~0.74 vs TF-IDF
191
+
~0.82 — a text classifier is slightly **better** there. (A nested CV free to pick a 1.5B sensor closes
192
+
it to roughly a tie, ~0.79 vs ~0.82, but that is not the shipped config.) The edge is generalizing to
193
+
new sources and new vocabulary, not same-vocabulary detection inside one distribution.
189
194
190
195
## Competitive landscape
191
196
192
197
| Type | Who | How they scan | How IntentProbe differs |
193
198
|---|---|---|---|
194
199
| **MCP scanner** | Snyk Agent Scan (formerly Invariant MCP-Scan), Cisco AI Defense, NVIDIA SkillSpector | Static rules, AST, YARA signatures, LLM-as-judge | Adds a model-internal **activation** signal; static keywords still corroborate the block tier |
195
-
| **Text classifier** | ProtectAI DeBERTa (used by Invariant/Snyk/Lakera/promptfoo), Meta Prompt Guard | Classify text as injection / jailbreak | Keys off model activations rather than surface vocabulary, so it transfers better to attack sources it never trained on |
200
+
| **Text classifier** | ProtectAI DeBERTa (used by Invariant/Snyk/Lakera/promptfoo), Meta Prompt Guard | Classify text as injection / jailbreak | Keys off model activations rather than surface vocabulary; **measured against our same-data TF-IDF baseline** (not these products), it transfers better to attack sources it never trained on |
196
201
| **Probe-based** | PIShield, TaskTracker (research code); RouteGuard, MindGuard (papers); frontier-lab production probes (e.g. Google Gemini) | Linear probe / classifier on model internals | Same family of method — IntentProbe is **not** first or only on the technique. The only-one-we-found niche is the deployment shape: installable, pre-install, scans the tool *description*, on activations |
197
202
| **LLM-as-judge** | NeMo, OpenAI Guardrails, Promptfoo | Ask another LLM "is this poisoned?" | Deterministic, local, no API call; scores state not the verbal answer |
198
-
| **Enterprise cloud** | Lakera, Azure, Google Model Armor, AWS Bedrock | Ship content to a vendor cloud | 100% local; every benchmark, artifact, and dataset is public |
203
+
| **Enterprise cloud** | Lakera, Azure, Google Model Armor, AWS Bedrock | Ship content to a vendor cloud | Runs locally; benchmarks, scripts, and the probe artifact are public (datasets from their original sources) |
199
204
200
205
Full source-backed comparison: [docs/COMPETITIVE_LANDSCAPE.md](docs/COMPETITIVE_LANDSCAPE.md).
201
206
@@ -268,9 +273,10 @@ and replay why a tool call was allowed, warned, or blocked. Full event schema:
268
273
269
274
```
270
275
a text classifier does well when an attack reuses wording it has seen — that is
271
-
pattern-matching, not intent, and it ties or beats the probe there (same-vocabulary
272
-
minimal pairs ~0.79 vs ~0.82; or a new source whose vocabulary overlaps training).
273
-
the probe's value is the attacks worded in ways it never saw.
276
+
pattern-matching, not intent, and it ties or beats the probe there (on the shipped
277
+
config, same-vocabulary minimal pairs run ~0.74 probe vs ~0.82 TF-IDF — text wins; or a
278
+
new source whose vocabulary overlaps training). the probe's value is the attacks worded
279
+
in ways it never saw.
274
280
275
281
the probe needs the frozen 0.5B host model to run, so inference is HEAVIER than a
276
282
standalone text classifier. the ~22 KB size is a train/store advantage only.
@@ -299,8 +305,8 @@ and replay why a tool call was allowed, warned, or blocked. Full event schema:
299
305
> different model from the shipped product. Read it for the original motivation, but treat the
300
306
> benchmarks above (Qwen2.5-0.5B, real data, cross-source) as the current evidence. On the synthetic
301
307
> minimal-pairs set both the probe and TF-IDF sit at chance (it is out of distribution), and
302
-
> within-distribution the probe ties TF-IDF. Probe weights and all benchmark scripts are in `research/`.
303
-
> Run them yourself.
308
+
> within-distribution a text classifier is comparable or slightly better. Probe weights, scripts, and
309
+
> result JSONs are in `research/`; the PI datasets download from their original sources. Run the scripts yourself.
304
310
>
305
311
> A published **[erratum](docs/ERRATUM.md)** corrects the paper's preliminary numbers (pair leakage in
306
312
> the matched-pair headline, the GPT-2-research vs shipped-product mix-up, and dataset counts).
0 commit comments