Skip to content

Commit 858ea71

Browse files
ithiria894claude
andcommitted
honest fix-forward (0.1.6): Codex cross-model red-team corrections
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>
1 parent 4be5eaf commit 858ea71

9 files changed

Lines changed: 255 additions & 188 deletions

File tree

README.md

Lines changed: 41 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,9 @@ recall collapses. The probe holds up better across sources, because it keys off
3232
internally represents the input rather than the exact words.
3333

3434
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
3838
substantial body of prior and parallel work (see [Competitive landscape](#competitive-landscape)).
3939

4040
## Install in one command
@@ -114,8 +114,11 @@ judge; the deterministic label baseline flagged every clean curated item as pois
114114

115115
## Benchmarks
116116

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.
119122

120123
**1. Generalization to unseen attacks: HackAPrompt (n=3,866 real attacks, a source neither detector trained on)**
121124

@@ -139,32 +142,33 @@ instead, so it holds up. At the stricter 1% setting the gap is wider still (88%
139142
so this is recall at a matched FPR set on the training clean data, not a full AUROC; the sample is
140143
uniform-random over the corpus, not an exhaustive panel.
141144
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**
143146
144147
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
149+
product number:
147150
148151
```
149-
held-out source probe AUROC TF-IDF AUROC difference (95% CI)
150-
─────────────── ─────────── ──────────── ──────────────────
151-
deepset 0.941 0.732 +0.209 [0.168, 0.250] significant
152-
spml 0.995 0.935 +0.059 [0.044, 0.077] significant
153-
safeguard 0.999 0.993 +0.006 [0.002, 0.011] significant (at ceiling)
154-
jayavibhav 1.000 0.997 +0.002 [0.000, 0.005] tie (CI touches 0)
155-
─────────────── ─────────── ──────────── ──────────────────
156-
mean 0.984 0.914 +0.070
152+
held-out source probe (shipped 0.5B) TF-IDF (same data)
153+
─────────────── ──────────────────── ──────────────────
154+
deepset 0.933 0.732
155+
safeguard 0.999 0.993
156+
spml 0.990 0.935
157+
jayavibhav 1.000 0.997
158+
─────────────── ──────────────────── ──────────────────
159+
mean 0.980 0.914
157160
```
158161
159-
deepset is where the gap is widest: TF-IDF's vocabulary does not transfer to the held-out source and it
160-
drops to 0.732, while the probe holds at 0.941. The other three are near ceiling, so there is less room
161-
to separate.
162+
deepset is where the gap is widest: TF-IDF's vocabulary does not transfer to the held-out source
163+
(0.732) while the probe holds (0.933). The other three are near ceiling, so there is less room to
164+
separate.
162165
163-
**Deployable, not a search artifact.** The single **shipped fixed config** (Qwen2.5-0.5B, mean-pooled
164-
concat L13-15, no per-input layer picking) gets a mean AUROC of **0.980** across the same held-out
165-
sources (deepset 0.933), still well above TF-IDF's 0.914. An exhaustive search over single and paired
166-
layers tops out around 0.982, and combining layers gives no gain over one good mid-layer. The advantage
167-
is robust to the layer choice, not balanced on one lucky setting.
166+
A nested cross-validation that is additionally free to pick a **larger 1.5B sensor** per fold (model +
167+
layer selected on the training sources only, never the held-out one) reaches mean **0.984**, with 95%
168+
bootstrap CIs on the probe-minus-TF-IDF difference: deepset +0.209 [0.168, 0.250], spml +0.059 [0.044,
169+
0.077], safeguard +0.006, jayavibhav +0.002 (3/4 significant). That is a research upper bound, not the
170+
shipped 0.5B artifact. An exhaustive single+pair search tops out around 0.982; combining layers gives no
171+
gain over one good mid-layer.
168172
169173
**3. Tool poisoning: partial, leave-one-corpus-out**
170174
@@ -182,20 +186,21 @@ The cross-source advantage extends to tool poisoning, but only partially — and
182186
MCPTox is a clear win. Our own synthetic minimal-pairs set is out of distribution for both detectors,
183187
and both sit at chance on it.
184188
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.
189194
190195
## Competitive landscape
191196
192197
| Type | Who | How they scan | How IntentProbe differs |
193198
|---|---|---|---|
194199
| **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 |
196201
| **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 |
197202
| **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) |
199204
200205
Full source-backed comparison: [docs/COMPETITIVE_LANDSCAPE.md](docs/COMPETITIVE_LANDSCAPE.md).
201206
@@ -268,9 +273,10 @@ and replay why a tool call was allowed, warned, or blocked. Full event schema:
268273

269274
```
270275
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.
274280
275281
the probe needs the frozen 0.5B host model to run, so inference is HEAVIER than a
276282
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:
299305
> different model from the shipped product. Read it for the original motivation, but treat the
300306
> benchmarks above (Qwen2.5-0.5B, real data, cross-source) as the current evidence. On the synthetic
301307
> 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.
304310
>
305311
> A published **[erratum](docs/ERRATUM.md)** corrects the paper's preliminary numbers (pair leakage in
306312
> the matched-pair headline, the GPT-2-research vs shipped-product mix-up, and dataset counts).

0 commit comments

Comments
 (0)