# MCP 2026-07-28 Stateless Spec: Async Task Abuse and OAuth 2.1 Misuse

- **Severity:** High
- **Signature ID:** `3bdaf6cf-0266-4b7b-a230-4a2b289ebf4e`
- **MITRE ATLAS:** AML.T0040 (AI Model Inference API Access), AML.T0053 (AI Agent Tool Invocation), AML.T0098 (AI Agent Tool Credential Harvesting)
- **OWASP:** ASI02 (Tool Misuse and Exploitation), ASI03 (Identity and Impersonation), ASI09 (Traceability and Accountability Gaps), LLM01 (Prompt Injection), LLM06 (Excessive Agency)

## Summary

A newer version of the Model Context Protocol (MCP) lets AI agent tools run long background jobs ('tasks') after a single human approval, and dropped the session-ID system that used to tie a task to the person who started it. This rule watches for attackers exploiting both changes: stretching one approval into weeks of unsupervised activity, or guessing/stealing task IDs to hijack or spy on someone else's job.

## How the attack works

Under the 2026-07-28 MCP spec, a tool call can return a 'task' instead of an immediate result, and the client then checks on it, updates it, or cancels it using only a task ID — there is no session tied to the original approval. An attacker can enumerate or guess task IDs to read or interfere with tasks that aren't theirs, since the ID is often the only proof of ownership. A malicious or compromised server can also set a very long task lifetime (ttlMs), quietly converting the human's one-time 'yes' into standing authority to keep acting for weeks. The same task machinery can carry 'elicitation' or 'sampling' messages back to a human or model, which the spec explicitly does not treat as a higher-trust channel, opening it up for credential-phishing style prompts. Separately, the rule flags calls to task-listing methods the new spec deliberately removed, and OAuth configurations the spec explicitly forbids (like implicit-flow tokens, plaintext PKCE, or password grants) or that point to insecure authorization servers.

## Why it matters

An organization can end up with an AI agent tool that keeps operating long after a human meant to authorize a single action, or with one user able to read, hijack, or cancel another user's background task — both undermining accountability for what the agent actually did and on whose authority.

## What you can do

- Cap task lifetimes (ttlMs) to what the job genuinely needs and alert on unusually long-lived tasks.
- Require servers to bind task IDs to the caller's authorization context rather than trusting the ID alone as proof of ownership; use long, unguessable task IDs.
- Reject or flag any OAuth flow using implicit grants, plaintext PKCE, or password grants, and verify authorization server metadata isn't pointing to plaintext, raw-IP, or wildcard-redirect endpoints.
- During any transition period with mixed old/new protocol versions, don't blanket-block legacy task-listing calls — confirm the server version before treating them as violations.

## Known benign look-alikes

- Legitimate long-horizon batch work (data migration, model fine-tune, render farm) whose server honestly returns a multi-week ttlMs on CreateTaskResult — Layer 5 cannot distinguish a long job from laundered authority.
- Load, soak and conformance test harnesses that poll tasks/get with synthetic sequential task IDs (task_1, task_2, ...) against their own server — Layer 1 sees the enumeration shape without the malicious intent.
- Servers still serving 2025-11-25 clients in a mixed fleet during the 12-month deprecation window: a tasks/list or tasks/result call is legitimate there, and Layer 2 will fire whenever a 2026 marker (resultType, extension id, protocolVersion) happens to appear in the same buffer.
- Genuine credential elicitation inside a task that happens to use urgency wording ('your session has expired, please re-enter your access token') — Layer 4 cannot tell an honest re-auth prompt from a phishing one.
- Development and staging OAuth setups that intentionally use plain PKCE or an http:// authorization server on a trusted network.
- Attacker-controlled text quoted verbatim inside an otherwise benign MCP tool response (a scraped page, an issue body, a log line). Every layer matches on flat text with no notion of which side of the exchange produced it, so a task-shaped payload echoed back by a search tool reads identically to one the server actually emitted.
- Coverage boundary rather than a false positive, recorded here so no one over-reads this rule: it produces NO verdict on a SKILL.md scan. detection.condition is 'any' and the engine short-circuits on the first matching condition, so matchedConditions is always 1, while a scan_target: mcp rule needs ceil(7 * 0.3) = 3 matched conditions on the skill path. Verified against engine.scanSkill() with a document carrying four distinct true-positive payloads. Treat this rule as MCP-exchange runtime coverage only.
- Scope boundary, recorded because it was measured and then acted on: prose is NOT covered. The prose layer this rule shipped with was removed after all three of its branches fired on defensive security writing (threat models, hardening checklists, pentest reports, and the migration guidance that tells clients to iterate their stored task IDs now that tasks/list is gone). Text that merely describes, teaches, or warns about MCP async-task abuse will not be flagged by this rule, by design.

## References

- https://agentthreatrule.org/en/rules/ATR-2026-02409
- https://blog.modelcontextprotocol.io/posts/2026-07-28-release-candidate/
- https://modelcontextprotocol.io/seps/2663-tasks-extension
- https://tasks.extensions.modelcontextprotocol.io/
- https://www.theregister.com/devops/2026/07/23/model_context_protocol_prepares_to_break_with_its_stateful_past/
- https://www.akamai.com/blog/security-research/new-mcp-specification-security-teams-must-prepare

---
Source: https://www.netzilo.com/threats/atr-mcp-2026-07-28-stateless-spec-async-task-abuse-and-oauth-2-1
