Skip to content

fix: fetch adaptor is not enforcing max body or content length#10795

Merged
jasonsaayman merged 1 commit intov1.xfrom
fix/axi-201
Apr 22, 2026
Merged

fix: fetch adaptor is not enforcing max body or content length#10795
jasonsaayman merged 1 commit intov1.xfrom
fix/axi-201

Conversation

@jasonsaayman
Copy link
Copy Markdown
Member

@jasonsaayman jasonsaayman commented Apr 22, 2026

Summary by cubic

Enforces maxBodyLength and maxContentLength in the fetch adapter with pre-checks, streaming checks, and data: URL guards to match the Node HTTP adapter and prevent oversized payloads.

Description

  • Summary of changes
    • Enforce maxBodyLength before dispatch for non-GET/HEAD requests; emit ERR_BAD_REQUEST.
    • Pre-check Content-Length and reject early if it exceeds maxContentLength; emit ERR_BAD_RESPONSE.
    • Stream-time enforcement using chunk progress to stop oversized downloads mid-stream.
    • Guard data: URLs by estimating decoded size before materializing.
    • Fallback size checks for environments without ReadableStream.
    • Improve estimateDataURLDecodedBytes with browser-safe fallbacks (TextEncoder/string length).
  • Reasoning
    • The fetch adapter was not enforcing size limits; this aligns behavior with the HTTP adapter and docs.
    • Security hardening (tests reference GHSA-777c-7fjr-54vf).
    • Addresses Linear AXI-201.
  • Additional context
    • No change when limits are unset or negative.
    • Error codes: ERR_BAD_REQUEST (request body), ERR_BAD_RESPONSE (response/content).

Docs

  • Update /docs/ to note the fetch adapter now respects maxBodyLength and maxContentLength, including:
    • Early rejection on Content-Length, streaming enforcement, and data: URL behavior.
    • Error codes and example config.

Testing

  • Added unit tests in tests/unit/adapters/fetch.test.js:
    • Rejects outbound bodies over maxBodyLength.
    • Rejects responses where Content-Length exceeds maxContentLength.
    • Rejects chunked responses that exceed limits during streaming.
    • Rejects oversized data: URLs (base64 and plain).
    • Allows payloads at/below limits.
  • No additional tests needed.

Semantic version impact

  • Patch: bug fix aligning the fetch adapter with documented/expected limits. Potentially stricter behavior if limits were previously set but unenforced.

Written for commit 600048c. Summary will update on new commits.

@jasonsaayman jasonsaayman self-assigned this Apr 22, 2026
@jasonsaayman jasonsaayman added priority::medium A medium priority commit::fix The PR is related to a bugfix labels Apr 22, 2026
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

2 issues found across 3 files

Confidence score: 3/5

  • There is concrete regression risk in lib/adapters/fetch.js: the maxContentLength stream-wrapping path should check response.body first, otherwise no-body responses can throw a TypeError at runtime.
  • In lib/helpers/estimateDataURLDecodedBytes.js, the new comment overstates behavior: the body.length fallback is not strictly an upper-bound/over-count-only estimate, which can mislead future maintenance and assumptions.
  • Given both findings are medium severity (6/10) with high confidence (9/10), this PR has some user-impacting risk and should get a focused fix pass before merging.
  • Pay close attention to lib/adapters/fetch.js and lib/helpers/estimateDataURLDecodedBytes.js - runtime no-body handling and inaccurate safety-property documentation need correction.
Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="lib/helpers/estimateDataURLDecodedBytes.js">

<violation number="1" location="lib/helpers/estimateDataURLDecodedBytes.js:77">
P2: Custom agent: **Flag AI Slop and Fabricated Changes**

Added comment claims a safety property (“upper-bound” / “over-counting only”) that the `body.length` fallback does not provide.</violation>
</file>

<file name="lib/adapters/fetch.js">

<violation number="1" location="lib/adapters/fetch.js:315">
P2: Guard the maxContentLength stream-wrapping path with `response.body` to avoid TypeError on no-body responses.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

}

// Browser/worker fallback: use TextEncoder when available, else fall back to
// raw string length as an upper-bound heuristic. Both are safe for a DoS
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai Bot Apr 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: Custom agent: Flag AI Slop and Fabricated Changes

Added comment claims a safety property (“upper-bound” / “over-counting only”) that the body.length fallback does not provide.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At lib/helpers/estimateDataURLDecodedBytes.js, line 77:

<comment>Added comment claims a safety property (“upper-bound” / “over-counting only”) that the `body.length` fallback does not provide.</comment>

<file context>
@@ -69,5 +69,16 @@ export default function estimateDataURLDecodedBytes(url) {
+  }
+
+  // Browser/worker fallback: use TextEncoder when available, else fall back to
+  // raw string length as an upper-bound heuristic. Both are safe for a DoS
+  // guard (over-counting only makes the check stricter for non-ASCII content).
+  if (typeof TextEncoder === 'function') {
</file context>
Fix with Cubic

Comment thread lib/adapters/fetch.js
if (supportsResponseStream && (onDownloadProgress || (isStreamResponse && unsubscribe))) {
if (
supportsResponseStream &&
(onDownloadProgress || hasMaxContentLength || (isStreamResponse && unsubscribe))
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai Bot Apr 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: Guard the maxContentLength stream-wrapping path with response.body to avoid TypeError on no-body responses.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At lib/adapters/fetch.js, line 315:

<comment>Guard the maxContentLength stream-wrapping path with `response.body` to avoid TypeError on no-body responses.</comment>

<file context>
@@ -252,10 +293,27 @@ const factory = (env) => {
-      if (supportsResponseStream && (onDownloadProgress || (isStreamResponse && unsubscribe))) {
+      if (
+        supportsResponseStream &&
+        (onDownloadProgress || hasMaxContentLength || (isStreamResponse && unsubscribe))
+      ) {
         const options = {};
</file context>
Fix with Cubic

@jasonsaayman jasonsaayman merged commit e5540dc into v1.x Apr 22, 2026
28 checks passed
@jasonsaayman jasonsaayman deleted the fix/axi-201 branch April 22, 2026 16:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

commit::fix The PR is related to a bugfix priority::medium A medium priority

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant