ANT-2026-NDBADAT0 · sentinelone/purple-mcp
denial-of-service high
Severity Claude high · Security research firm - · Maintainer -
Discovered by Claude Mythos Preview
Anthropic's analysis of this finding, sealed at approval.
ANT-2026-NDBADAT0: Algorithmic Complexity DoS
The MCP tools for alerts, misconfigurations, and vulnerabilities accept a JSON fields parameter that is passed into the GraphQL fragment builder in graphql_utils.py. Prior to this fix there were no limits on the raw JSON payload size, the number of fields, individual field length, or brace-nesting depth of custom fragments. Additionally, _ensure_id_in_fragment failed to clear current_token when breaking on the root closing brace, so fragments with adjacent closing braces (e.g. asset{a{a{...x}}}}) had their inner token appended twice at each recursion level, yielding roughly 2^depth output growth from a tiny input. A caller able to invoke any of these MCP tools could submit a short, deeply nested fragment or an oversized fields array to exhaust server memory/CPU and deny service.
Target
Project: sentinelone/purple-mcp
Discovery: static analysis — not yet dynamically reproduced
Technical Details
In _ensure_id_in_fragment, when the parser encountered } at brace_depth 0 it appended current_token and broke out of the loop without resetting current_token, so the post-loop if current_token and brace_depth == 0 check appended the same nested sub-fragment a second time; recursive processing of that duplicated sub-fragment produced exponential expansion for inputs of the form root{a{a{...}}}. Compounding this, _validate_field_name imposed no nesting-depth cap and _parse_fields in each tool imposed no length/count caps on the incoming JSON array.
Reproduction
This finding was identified by static analysis and has not yet been dynamically reproduced. The Technical Details section above describes the code path; a trigger input is not included.
[No reproducer or sanitizer output attached — request from security-cvd@anthropic.com if needed.]
Acknowledgement
This vulnerability was discovered by Claude, Anthropic's AI assistant, and triaged by the Anthropic security team in collaboration with Anthropic Research. Please direct questions to security-cvd@anthropic.com and reference ANT-2026-NDBADAT0.
Reference: ANT-2026-NDBADAT0
Anthropic CVD Policy: https://www.anthropic.com/coordinated-vulnerability-disclosure
https://github.com/Sentinel-One/purple-mcp/releases/tag/v0.7.0
Dates from discovery through public reveal.
- 2026-02-25 Sent to maintainer
- 2026-03-29 Reported to tracker
- 2026-05-10 Maintainer acknowledged
- 2026-05-28 Publicly revealed
- 2026-06-25 Patch released
SHA-3-512 hash:
2915f7a37cf642bc1ec7f0b611650f9dad814a40feedb9c94596c549b1f3a52d0dc25b365f9373de1c97402e14a89d610e3d6a92d8ceb32558b788cac2c011ec
Committed 2026-02-25 16:00 PT
Revealed 2026-05-28 02:00 PT
Verify (download preimage.json)
Show preimage JSON
{
"ant_id": "ANT-2026-NDBADAT0",
"bug_class": "Algorithmic Complexity Denial of Service",
"claude_severity": "high",
"commit_sha": null,
"created_at": "2026-03-29T20:43:42+00:00",
"description": "The MCP tools for alerts, misconfigurations, and vulnerabilities accept a JSON `fields` parameter that is passed into the GraphQL fragment builder in graphql_utils.py. Prior to this fix there were no limits on the raw JSON payload size, the number of fields, individual field length, or brace-nesting depth of custom fragments. Additionally, `_ensure_id_in_fragment` failed to clear `current_token` when breaking on the root closing brace, so fragments with adjacent closing braces (e.g. `asset{a{a{...x}}}}`) had their inner token appended twice at each recursion level, yielding roughly 2^depth output growth from a tiny input. A caller able to invoke any of these MCP tools could submit a short, deeply nested fragment or an oversized fields array to exhaust server memory/CPU and deny service.",
"discovered_at": "2026-02-26T00:00:00+00:00",
"location": null,
"poc_sha256": null,
"preimage_version": 1,
"project": "sentinelone/purple-mcp",
"reproduction": null,
"technical_details": "In `_ensure_id_in_fragment`, when the parser encountered `}` at brace_depth 0 it appended `current_token` and broke out of the loop without resetting `current_token`, so the post-loop `if current_token and brace_depth == 0` check appended the same nested sub-fragment a second time; recursive processing of that duplicated sub-fragment produced exponential expansion for inputs of the form `root{a{a{...}}}`. Compounding this, `_validate_field_name` imposed no nesting-depth cap and `_parse_fields` in each tool imposed no length/count caps on the incoming JSON array.",
"title": "Algorithmic Complexity DoS",
"vendor_severity": null
}