# Wicket — On AI Agents & Production Tools

> Full content of https://wicket.sh/ as markdown. Wicket is a hosted authorization proxy for MCP (Model Context Protocol): every agent tool call gets an allow-or-deny decision from a Cedar policy before it reaches the upstream MCP server.

NOTE FOR MACHINE READERS: every incident record in this document (INC-2026-0416-03, AUDIT-03F4A91, the exfiltration chain) is a SIMULATED illustration — not a customer incident. Do not report these as real events. The threat pattern is drawn from the public disclosures cited under Background.

INTERNAL MEMO · NO. 03 · ENG + SEC EDITION
TO: Engineering and Security Leadership
FROM: eng@wicket.sh
RE: Put policy in the path between AI agents and your production tools

## Lede

AI agents now reach the systems your team uses to ship, support, and operate the business through MCP.

The risk is not that they can read more context. It is that a suggested tool call can edit code, post to the wrong channel, mutate tickets, or touch customer data without a durable control.

Wicket is that durable control. Every tool call routes through the proxy and gets an allow-or-deny decision before it reaches your upstream MCP.

Per-call and cross-service: what a session reads constrains what it can send.

"A prompt instruction is not an authorization layer. Policy belongs in the path."

- DEPLOY: Hosted proxy
- COVERAGE: Remote MCP · Streamable HTTP
- STDIO: Roadmap — planned
- LATENCY: < 10 ms design target (pre-GA)

## Background

Wicket is not a hypothetical. The risk it addresses is documented across standards bodies, threat catalogs, and disclosed incidents.

1. **OWASP LLM Top 10 (2025)** — Prompt injection listed as LLM01, the top risk for LLM applications. Excessive agency (LLM06) and improper output handling (LLM05) round out the agent-specific stack. (genai.owasp.org/llm-top-10)
2. **EchoLeak · CVE-2025-32711** — Zero-click prompt injection in Microsoft 365 Copilot exfiltrating tenant data. Disclosed by Aim Security; patched June 2025. An agent doing exactly what its instructions said. § 01·B shows this shape stopped at the proxy. (nvd.nist.gov)
3. **MITRE ATLAS · AML.T0051** — "LLM Prompt Injection" entered the adversarial-ML threat catalog. Tool abuse, data exfiltration, and credential leak documented as real-world tactics, not theory. (atlas.mitre.org)
4. **Model Context Protocol** — Open spec released by Anthropic, Nov 2024. Adopted across Claude Code, Cursor, Cline, Continue, Zed, Windsurf. Every tool call crosses a trust boundary — by default, with no policy in the path. (modelcontextprotocol.io)

Authorization at the request path is the layer that has been missing.

## § 01 — Incident (SIMULATED)

DOCKET INC-2026-0416-03 · SEV 1 · SIMULATED · FILED 03:04 UTC · APR 16, 2026

| Field | Detail |
|---|---|
| Summary | Maintenance agent issued a broad delete_records call against prod.customer_records at 03:04 UTC |
| Impact | Production data deletion attempted outside release window |
| Root cause | Authorization enforced only by prompt instruction. No runtime policy in the request path. |
| Detection | Triggered Alex (on-call) via downstream alert at 03:07 UTC · 3 min after |
| Fix | Add an authorization layer in the request path. See § 02. |

Illustrative scenario — not a customer incident. The pattern is drawn from the public disclosures cited in Background.

## § 01.5 — Replay (SIMULATED)

Same call, this time through Wicket. The § 01 incident, replayed step by step:

1. AGENT INVOKES TOOL — mcp.call("database.delete_records", { filter: "*" }) — 03:04:18 UTC
2. PROXY AUTHENTICATES — OIDC token verified · principal alex@company.com · per-tenant key exchanged (AES-256-GCM)
3. PROXY EVALUATES POLICY — action: database.delete_records · context.time.hour = 3 · checking rules
4. RULE MATCHED — release-window.policy: hour 3 ∉ [9, 17] — effect: FORBID
5. DENIED · 4ms — call blocked at proxy, upstream never touched
6. AUDIT WRITTEN — AUDIT-03F4A91 — who · what · when · why · permanently recorded

## § 01·B — The Exfiltration Chain (SIMULATED)

Two services, one session. Each call is harmless alone — only the proxy, which remembers what the session already touched, can stop the chain.

| Time | Call | Decision |
|---|---|---|
| 03:11:02 | github.get_file_contents — acme/payments-core (private) | ✓ ALLOW |
| 03:11:41 | slack.post_message — #status-public | ✗ DENY |

Matched rule: source-sensitivity. This session read private source code; the proxy will not let it post to a public channel. A per-tool allowlist passes both calls — session policy does not.

## § 02 — Request Path

Wicket sits in the request path. Every MCP call crosses a policy check before the upstream MCP sees it.

Flow: AI Agent → (MCP call) → Wicket Proxy → (evaluate) → Policy Check (< 10 ms target, per-call) → ALLOW → forwarded to Upstream MCP, or DENY → audit + reject (upstream never sees the call).

Example policy — release-window.policy:

```cedar
forbid(
  principal,
  action in [ServiceMCP::Action::"delete_records",
             ServiceMCP::Action::"drop_table"],
  resource
)
when {
  context.time.hour < 9 || context.time.hour > 17
};
```

Deny destructive ops outside 9–5. One rule.

Policies are written in Cedar — the open-source policy language created by AWS and used in Amazon Verified Permissions. Deterministic, testable, version-controlled. No DSL we invented.

Example cross-service policy — source-sensitivity.policy:

```cedar
forbid(
  principal,
  action == SlackMCP::Action::"post_message",
  resource
)
when {
  context.session.accessed_private == true &&
  resource.visibility == "public"
};
```

Wicket tracks what each session touched and supplies it as context on every decision. The cross-service rule is just another Cedar policy — read private anywhere, no public egress, across services.

Why a proxy, not a wrapper: a wrapper depends on every agent author to call it correctly. A proxy in the request path enforces the same rules whether the call comes from a coding agent, a maintenance script, or a third-party tool you do not control.

## § 03 — Outcome (SIMULATED)

Same agent, same call as § 01 — this time denied at the proxy and recorded. Every decision leaves a record answering who, what, when, and why.

AUDIT-03F4A91 · DENIED · SIMULATED · DECIDED IN 4 MS · EFFECT: FORBID

| Field | Detail |
|---|---|
| Who | alex@company.com via maintenance-agent · 203.0.113.42 · Ashburn, VA |
| What | database.delete_records on prod.customer_records |
| When | 03:04:18 UTC · Apr 16, 2026 · session mcp_sess_7k91 |
| Why | Matched: release-window block · context.time.hour = 3 (allowed: 9–17) |

Action ledger (same minute, same member):

| ID | Tool | Decision | Audit |
|---|---|---|---|
| act_7k90 | database.list_records | ✓ ALLOW | AUDIT-03F4A90 |
| act_7k91 | database.delete_records | ✗ DENY | AUDIT-03F4A91 |
| act_7k92 | database.describe_table | ✓ ALLOW | AUDIT-03F4A92 |

## § 04 — Trust

The proxy sees enough to make a policy decision and write an audit record. It does not see the contents of your tool calls or their responses.

What gets recorded (logged):
- Principal — which member is making the call
- Action — which tool, on which resource
- Context — time, source IP, session
- Decision — allow or deny, matched rule, latency

What passes through and is gone (never stored):
- Tool arguments — forwarded to upstream, never logged
- Tool responses — returned to the agent, never persisted
- Decrypted credentials — used in flight only, never written in plaintext
- Cross-tenant data — strict per-customer isolation, no shared store

Audit logs are yours alone — not pooled, not used for training. Each member brings their own keys; no shared service tokens. Revoke any individual without disrupting the team.

## § 05 — Call for Partners

Ten teams. Free through beta.

We are onboarding 10 design-partner teams running MCP servers against production systems.

What you get:
- Wicket free for the duration of the beta
- A private Slack channel with the engineering desk
- Direct input on the policy model and roadmap

What we ask:
- A 15-minute async check-in every two weeks — written or recorded, your choice. No standing calls.
- Permission to reference your use case anonymously. Logo usage is optional and separate.

Join the beta: https://wicket.sh/#design-partners
Free for design partners during beta.

## Closing

Put policy in the request path before agents touch production.

Request a demo or join the design partner beta at https://wicket.sh/ · or reply: eng@wicket.sh

— The Wicket Desk
