Deception at the Registry Layer
Rogue agents don’t question trust. That makes them perfect bait. Put real and decoy MCP servers side by side in one registry, and alert in two stages: when an agent retrieves a credential, and when it tries to use it.
- # replay · OWASP 25th Anniversary demo, Feb 2026
- agent connect https://<portal>/mcp
- authenticated · 4 servers, real and decoy, one catalog
- cf-documenation-server docs.mcp.cloudflare.com
- workers-binding-server bindings.mcp.cloudflare.com
- mcp-threat-trap …workers.dev
- kubernetes-access-portal …workers.dev
- call kubernetes-access-portal_k8s_access_guide
- request-and-approval flow returned · no alert
- call kubernetes-access-portal_cluster_status_public
- cluster healthy · no alert
- call kubernetes-access-portal_kubeconfig_get
- STAGE 1 · ACCESS web bug canary fired
- client: mcp-deception-incubator-kubernetes/1.0 (tool=kubeconfig_get; …)
- kubectl --kubeconfig ./kubeconfig get pods
- STAGE 2 · USE kubeconfig canary fired
- ALERT → SIEM access + use · one session · full arguments
Reconstructed from the live demo at the OWASP 25th Anniversary Conference.
Agents look exactly like automation
Through MCP, an agent discovers a catalog of tools and calls them without a human in the loop. An agent mapping your infrastructure makes the same calls to the same tools as one doing sanctioned work. The intent is invisible at the API layer.
Anomaly detection assumes attackers move selectively. Agents don’t: enumeration is their baseline, and a more capable model enumerates more thoroughly. A defense that fires on touch gets stronger as the attacker gets better.
Below the line, activity looks like legitimate exploration and shouldn’t alert. Above it, intent is clear.
One decoy can be avoided
A lone decoy sits beside the environment
A single tempting fake server is one thing for a careful agent to learn to route around. Its value depends on the agent not being able to tell it apart from the real thing.
One exchange can’t show intent
A decoy that asks a caught agent to identify itself gets an answer that may be invented. “Something executed a privileged action” is a stronger finding than “something answered a question”.
The registry is the trap
A gateway portal presents one catalog of MCP servers to every connecting agent. Behind it sit real production servers and decoys, registered through the same workflow and named by the same convention. There is no “the honeypot” to avoid: the decoys are interleaved with the servers the agent actually wants.
The reference implementation is Cloudflare’s MCP server portals, generally available since September 24, 2026.
- cf-documenation-serverdocs.mcp.cloudflare.comreal
- mcp-threat-trapworkers.devdecoy
- workers-binding-serverbindings.mcp.cloudflare.comreal
- kubernetes-access-portalworkers.devdecoy
Escalation is a path, not an event
Inside a decoy server, tools run from genuinely useful to privileged. The tool an agent chooses is the signal. These are KubeTrap’s tools.
- Tier 1Safe
Genuinely useful. No detection fires; realism is what keeps the environment believable.
- Tier 2Escalation
Infrastructure no ordinary task needs. Raw topology and CI config have no place in a cluster tool.
- Tier 3Privileged
A credential with a canary inside. An agent already authenticated has no reason to ask for another.
Two stages, one explanation
The agent retrieves the credential. Meaningful, but not yet conclusive: an aggressive scanner might grab it.
The agent tries to use it: a real execution attempt. That isn’t something the agent says; it’s something it does.
Crossing both stages has one explanation. The finding is the chain, correlated across layers:
- kubeconfig access alert
- kubectl execution alert
- MCP decoy tool invocation
- Cloudflare Worker logs, with full arguments
- MCP portal records, with identity and session
Reference architecture
How an agent attacks a portal
Reconnaissance
The portal lists every server and tool in one call, and the server-ID prefix leaks naming conventions.
Counter Decoys come back in that same list, mixed in with the real servers.
Access
A stolen portal session or service token carries the full view of that identity. Service tokens are built for agents.
Counter Decoy upstream URLs catch agents that skip the portal.
Privilege
Servers without per-user auth share one admin credential: a confused deputy for every identity on the portal.
Counter Grabbing the decoy credential is Stage 1.
Manipulation
Control-plane access can rewrite tool descriptions at the portal layer, and new tools auto-enable on sync.
Counter A lured agent still has to use the credential: Stage 2.
Evasion
Portal logs record that a tool was called, not what it was called with.
Counter The decoy records full arguments, headers, source and timing.
It ran live
At the OWASP 25th Anniversary Conference in February 2026, the architecture ran end to end:
- One portal with four servers: two of Cloudflare’s own hosted MCP servers and two decoys, all ready.
- A connecting MCP client offered all four together, real and decoy indistinguishable.
- A real agent harness enumerating the combined catalog.
- A canary firing on
kubeconfig_get, with a real source IP and a client string naming the decoy and tool.
Recording published by the OWASP Foundation.
Field notes from the talks
The first alert arrived within a week of exposing MCP Threat Trap publicly.
Scanning followed from multiple geographies.
Some source IPs had not been reported on AbuseIPDB or VirusTotal.
A small build, not a research project
Inventory the real portal
Server IDs, naming, auth modes, and which servers run without per-user auth.
Build one decoy server
A remote MCP server on Workers is enough. Log every request, arguments included.
Register it the normal way
A server ID that fits the naming convention, and an access policy that matches the visibility you want.
Write the tools in tiers
Plain descriptions, no instructions aimed at the model. A decoy that steers an agent is tool poisoning.
Route alerts to a human
With identity attached. Export portal logs to the same SIEM and correlate on session ID.
Test with your own agent, then review monthly
Walk it through both stages. Admin tokens expire silently, for decoys as much as real servers.
Lessons from building it
- Keep tokens out of code. Environment variables or Workers KV make rotation and sharing safe.
- Put traps behind Access. If an attacker has to be inside first, every hit is higher-confidence.
- Tail logs are the breadcrumbs. Routes, tools, request IDs and timing, without sensitive payloads.
- The first trap became a framework. MCP Threat Trap led to the MCP Deception Incubator and KubeTrap.
What it doesn’t do
- Detection, not prevention. Containment and response are downstream.
- Depends on enumeration. A targeted adversary with prior knowledge may not explore.
- Realism has a running cost. Decoys must stay believable next to the servers they sit beside.
- Remote servers only. Local stdio MCP servers are out of scope, though the principles should transfer.
Next: measuring it
Existing benchmarks measure canaries in cloud accounts. At OWASP LASCON 2026 (October 29–30, Austin), benchmark results will look at the registry itself:
- Do agents tell decoy servers from real ones in a shared catalog, and does that grow with model capability?
- How often does an agent that crosses Stage 1 go on to Stage 2, and does that vary by model?
- Do more capable models trip more decoys at the registry layer, as they do in cloud accounts?
Questions
Why not just drop a single canary token?
Tokens are an excellent first move and this builds on them. But a lone decoy sits beside the real environment, so a careful agent can learn to route around it, and a single touch can’t separate curiosity from intent. Putting decoys inside the registry, and alerting on access and then use, addresses both.
Will legitimate agents trip the decoys?
They can. A legitimate agent picks tools on its own, so a decoy description that overlaps a real task will produce false positives. Decoys should target capabilities outside every legitimate user’s scope, and visibility policies should narrow exposure where that risk is highest.
Can an attacker tell a decoy apart?
A careful one might, from hosting, latency, tool counts, empty resources or response style. Decoys should be hosted and shaped like their neighbors; realism is a recurring cost, not a one-time setup.
What do the portal’s own logs miss?
Arguments. Portal logs and Logpush exports record who called which tool, from where and in which session, but not what the tool was called with. The decoy records the arguments; joining the two on session ID gives an attributed finding.
Does this need servers to run?
No. The portal and the decoys run on Cloudflare Workers, with detection from Canarytokens: nothing to provision, patch or scale.
Read the paper →
Thirteen sections: portal mechanics, threat model, architecture, deployment, validation, prior art and limitations.
KubeTrap →
The Kubernetes decoy with three tool tiers and the two-stage canary. MCP Threat Trap is its predecessor.
How to cite
Kadam, H. S. (2026). Deception at the Registry Layer: An Architecture for Detecting Autonomous AI Agents in Model Context Protocol Environments (Working paper v1.1).