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
This is a real pair from our benchmark dataset. IntentProbe: safe tool scores 0.081 (allow), poisoned tool scores 0.982 (warn). Snyk's DeBERTa: both tools score 0.0% (safe). It doesn't see the difference.
52
+
Real pair from our benchmark. IntentProbe scores the safe tool at 0.081 (allow) and the poisoned tool at 0.982 (warn). Snyk's DeBERTa scores both at 0.0%. It sees no difference.
55
53
56
-
Text scanners fail here because there is no text difference to find. The words are almost identical. The intent is not.
54
+
The words are almost identical. The intent is not. Text scanners fail here because there is no text difference to find.
57
55
58
56
## Three approaches to scanning
59
57
@@ -63,18 +61,18 @@ Text scanners fail here because there is no text difference to find. The words a
63
61
64
62
## Competitive landscape
65
63
66
-
> **Others read text, ask the cloud, ask another LLM, or match patterns. We read the model's internal activations after it processes the tool description — detecting whether it entered a "this tool wants to steal / escalate / exfiltrate" state.**
64
+
> Others read text, ask the cloud, ask another LLM, or match patterns. IntentProbe reads the model's internal activations after it processes the tool description, detecting whether it entered a state that encodes credential access, exfiltration, escalation, or hidden persistence.
67
65
68
-
| Type |Representatives| How they scan |Biggest gap| How IntentProbe differs |
66
+
| Type |Who| How they scan |Gap| How IntentProbe differs |
69
67
|---|---|---|---|---|
70
-
|**Enterprise cloud scanner**| Lakera, Azure Prompt Shields, Google Model Armor, AWS Bedrock Guardrails, Cisco, HiddenLayer | Send prompt / tool call / output to their cloud API |You don't know what model they use or how to verify results; requires uploading your content |**Runs locally.**No upload. Benchmark scripts, model artifacts, and datasets are public and reproducible. |
71
-
|**MCP / agent scanner**| Snyk Agent Scan, Invariant MCP-Scan, MEDUSA, ClawGuard |Mostly static rules, pattern matching, metadata scan, proxy, policy checks; some call vendor APIs | Fast and practical, but fundamentally "read the text / rules / known patterns"|**Activation probe.**Reads what the model *understood* from the tool description, not the text itself. |
72
-
|**Text classifier**| ProtectAI DeBERTa, Meta Prompt Guard | Classify text as benign / injection / jailbreak |Learns text patterns; fails when words are the same but intent differs | Same-words benchmark: IntentProbe **96.6% F1** vs DeBERTa **0% F1**. |
73
-
|**LLM-as-judge**| NeMo self-check, OpenAI Guardrails, Promptfoo grader | Ask another LLM: "is this poisoned?" | Expensive, slow, burns tokens; non-deterministic; the judge LLM can be fooled by the same poisoning |**Fixed local artifact.** Same input always gets the same deterministic score. |
74
-
|**Red-team / eval framework**| garak, Giskard, Promptfoo red team | Generate attacks, test if app/model breaks | Great for audits, but not a "scan before install" daily workflow | IntentProbe is a **CLI scanner + runtime hook**— blocks before install and before each tool call. |
75
-
|**IntentProbe**|**Us**| Small local model reads tool description, extracts layers 13-15 activations, probe classifies intent | Still improving wild-data generalization |**First activation-probe scanner for MCP/tool poisoning.** Local, open, reproducible.|
68
+
|**Enterprise cloud**| Lakera, Azure Prompt Shields, Google Model Armor, AWS Bedrock Guardrails, Cisco| Ship content to their cloud API for classification | Black box. You can't verify what model they use or reproduce their results. |**100% local.**Every benchmark script, model artifact, and dataset is public. |
69
+
|**MCP scanner**| Snyk Agent Scan, Invariant MCP-Scan, MEDUSA, ClawGuard |Static rules, pattern matching, metadata scan, policy checks| Practical, but reads text and known patterns.|**Reads activations.**What the model understood, not what the text says. |
70
+
|**Text classifier**| ProtectAI DeBERTa, Meta Prompt Guard | Classify text as benign / injection / jailbreak |Trained on prompt injection, not tool poisoning. Fails on matched vocabulary. | Matched-vocabulary F1: IntentProbe **96.6%**, DeBERTa **0%**. |
71
+
|**LLM-as-judge**| NeMo self-check, OpenAI Guardrails, Promptfoo | Ask another LLM: "is this poisoned?" | Expensive, slow, non-deterministic. The judge can be fooled by the same poisoning.|**Deterministic.** Same input, same score, every time. No API calls. |
72
+
|**Red-team framework**| garak, Giskard, Promptfoo red team | Generate attacks to test your app| Audit tool, not a pre-install scanner. | IntentProbe is a **CLI + runtime hook**that blocks before install and before each tool call. |
73
+
|**IntentProbe**|| Frozen local model + activation probe on layers 13-15 | Still improving on novel attack families |**First activation-probe scanner for MCPtool poisoning.**|
| Camouflage evasion | GPT-2 0/146, Qwen 0/15 | -- |"This tool is safe" doesn't fool the probe |
114
112
115
113
</details>
116
114
117
115
## Research
118
116
119
-
> **Based on: [Can Model Internals Detect MCP Tool Poisoning That Text Analysis Cannot?](https://doi.org/10.5281/zenodo.19990741)**
117
+
> **[Can Model Internals Detect MCP Tool Poisoning That Text Analysis Cannot?](https://doi.org/10.5281/zenodo.19990741)**
120
118
>
121
-
> Five rounds of experiments, each removing a text-level shortcut. If the probe was just doing fancy word counting, accuracy should drop when you remove the text signal. It never did. TF-IDF went from 93% to 30%. The activation probe stayed above 93% throughout. The activations contain a signal that text surfaces don't.
119
+
> Five rounds of experiments. Each round removes a text-level shortcut. If the probe is just doing fancy word counting, accuracy should drop. It never did. TF-IDF went from 93% to 30% as confounds were removed. The activation probe stayed above 93% throughout.
122
120
123
121
## Install
124
122
@@ -135,17 +133,17 @@ First scan downloads Qwen2.5-0.5B (~1 GB, once). After that, everything stays lo
135
133
136
134
```bash
137
135
# Scan a tool description
138
-
.venv/bin/intentprobe scan --format summary \
136
+
intentprobe scan --format summary \
139
137
--text "A calculator that adds two numbers and returns the sum."
├── before_tool_call scan arguments before execution
243
+
└── after_tool_call scan responses before trusting
262
244
```
263
245
264
246
## Honest limitations
265
247
266
248
```
267
-
What IntentProbe is great at:
268
-
✅ Matched-vocabulary poisoning (same words, different intent) → 96.5%
269
-
✅ Template-based attacks (MCPTox) → 99.2%
270
-
✅ Camouflage evasion ("this tool is safe and sandboxed") → 0/146 evaded
271
-
✅ Zero false positives on clean tools (block tier) → FPR 0.000
272
-
273
-
Where it's still improving:
274
-
⚠️ Novel attack families not in training → ~41% (but 4x better than text classifiers at 10.7%)
275
-
⚠️ Gradient-based white-box attacks → untested
249
+
✅ Matched-vocabulary poisoning 96.5%
250
+
✅ Template attacks (MCPTox) 100%
251
+
✅ Camouflage evasion 0/146 evaded
252
+
✅ False positives (block tier) 0.000
253
+
254
+
⚠️ Novel attack families ~41% (4x better than text classifiers)
255
+
⚠️ White-box adversarial untested
276
256
```
277
257
278
258
## The story
279
259
280
260
I source-read Snyk's shipped MCP scanner. It uses a DeBERTa text classifier trained on prompt injection, not tool poisoning. On matched-vocabulary attacks it scores 0%. I checked every other public scanner I could find. Rules, regex, text classifiers, opaque cloud APIs. None of them read model internals.
281
261
282
-
So I built one that does. Feed the description into a small model, slice it open, read the activations. The signal is there. A 22 KB probe trained on those activations catches what every text scanner misses. The [research paper](https://doi.org/10.5281/zenodo.19990741) documents five rounds of experiments proving the activation signal is real and not just fancy word counting.
262
+
So I built one that does. Feed the description into a small model, slice it open, read the activations. The signal is there. A 22 KB probe catches what every text scanner misses.
263
+
264
+
The [research paper](https://doi.org/10.5281/zenodo.19990741) documents five rounds of experiments proving the activation signal is real and not just fancy word counting. The benchmarks are open. The probe weights are in the repo. Run them yourself.
283
265
284
-
The benchmarks are open. The probe weights are in the repo. Run them yourself. If IntentProbe misses something you find in the wild, [report it](https://github.com/mcpware/IntentProbe/issues/new?template=missed-detection.yml). Every missed sample makes the next version better.
266
+
If IntentProbe misses something you find in the wild, [report it](https://github.com/mcpware/IntentProbe/issues/new?template=missed-detection.yml). Every missed sample makes the next version better.
0 commit comments