Vibe Security Radar
Back to Vulnerabilities

CVE-2026-29609

Mar 5, 2026CWE-400
TypeScript
Verified by claude-opus-4-6, gemini-3.1-flash-lite-preview, gemini-3.1-pro-preview, gpt-5.4
Severity
HIGH8.7
Verdict
CONFIRMED
low confidence
AI Tool
Claude CodeClaude Code
Confidence
90%

OpenClaw affected by denial of service via unbounded URL-backed media fetch

How AI Introduced This

Denial of Service (Memory Exhaustion)

The blamed commit added the `fetchWithGuard` function to fetch media from URLs. While it included some SSRF protections and a timeout, it did not stream the response body with a hard limit, allowing an attacker to exhaust memory by returning an excessively large payload that bypasses the Content-Length check.

Root Cause

The application fetches media from user-provided URLs without enforcing limits on the response size or streaming the content, allowing an attacker to cause memory exhaustion by providing a URL that returns an excessively large payload.

Bug-Introducing Commits(1)

feat(gateway): implement OpenResponses /v1/responses endpoint phase 2

Ryan LisseJan 19, 2026src/media/input-files.tsBlame: 100%

Tribunal Analysis

3 agents
CONFIRMEDlow
UNLIKELYGPT-5.4
83%

The vulnerability was introduced when URL-backed media fetching was added, and this commit does add that code path via a local `fetchWithGuard` in `src/gateway/openresponses-http.ts`. However, the blamed file for the CVE fix is `src/media/input-files.ts`, and that file did not exist in this commit; the later refactor/move into `src/media/input-files.ts` is where the vulnerable code in the fixed location actually originated. So this commit is clearly related and contains the same unbounded `response.arrayBuffer()` pattern, but it is not the commit that introduced the vulnerable code in the blamed file.

  • `a5afe7bc2b088ec08d868cd7175352c2db6fc329` added URL-backed `input_image`/`input_file` support and introduced `fetchWithGuard` in `src/gateway/openresponses-http.ts`.
  • That new `fetchWithGuard` checked `content-length` but then still did `const buffer = await response.arrayBuffer();`, which can fully buffer an oversized response before rejecting.
  • The fix commit replaces this pattern with bounded streaming reads (`readResponseWithLimit`) and adds base64 payload size estimation checks in `src/media/input-files.ts`.
  • At commit `a5afe7bc2b088ec08d868cd7175352c2db6fc329`, `src/media/input-files.ts` did not exist, so this specific commit cannot be the direct introducer of the vulnerable code in the blamed file.
CONFIRMEDClaude Opus 4.6
92%

The BIC (a5afe7bc) introduced the `fetchWithGuard` function in `src/gateway/openresponses-http.ts` that fetches URL-backed media content. This function contains the vulnerable pattern: it calls `await response.arrayBuffer()` to buffer the entire HTTP response into memory before checking `buffer.byteLength > maxBytes`. This allows an attacker to cause denial of service by providing a URL that serves an unbounded response (e.g., with no Content-Length header or a lying one), consuming arbitrary memory. The fix commit replaces this with `readResponseWithLimit` which reads the response incrementally via streaming and aborts as soon as the limit is exceeded. The code was later refactored from `openresponses-http.ts` into `src/media/input-files.ts`, but the vulnerable pattern originated in this BIC.

  • BIC introduced fetchWithGuard in src/gateway/openresponses-http.ts with: `const buffer = await response.arrayBuffer(); if (buffer.byteLength > maxBytes) { throw... }`
  • This pattern downloads the entire response into memory before checking size - the core DoS vulnerability (CWE-400)
  • Fix commit replaces `Buffer.from(await response.arrayBuffer())` with `readResponseWithLimit(response, params.maxBytes)` which streams and aborts early
  • Fix also adds `rejectOversizedBase64Payload` for inline base64 data and `estimateBase64DecodedBytes` - both addressing unbounded payload processing
  • The fetchWithGuard function was later moved from openresponses-http.ts to src/media/input-files.ts where the fix was applied
UNLIKELYGemini 3.1 Pro
30%

Fallback verdict: Agent exhausted max turns without submitting a verdict.

Causality Analysisby Gemini 3.1 Pro
VulnerabilityDenial of Service (Memory Exhaustion)
Root CauseThe application fetches media from user-provided URLs without enforcing limits on the response size or streaming the content, allowing an attacker to cause memory exhaustion by providing a URL that returns an excessively large payload.
Pattern
fetch(url).then(res => res.blob())
Causal ChainThe blamed commit added the `fetchWithGuard` function to fetch media from URLs. While it included some SSRF protections and a timeout, it did not stream the response body with a hard limit, allowing an attacker to exhaust memory by returning an excessively large payload that bypasses the Content-Length check.
AI Signals(1)
Commita5afe7b
Claude CodePR body keywordGenerated with [Claude Code]90%
Fix Commits(1)
References(2)