[PR #176] [MERGED] fix: bound fetch cache key body serialization #371

Closed
opened 2026-05-06 12:39:28 +02:00 by BreizhHardware · 0 comments

📋 Pull Request Information

Original PR: https://github.com/cloudflare/vinext/pull/176
Author: @dknecht
Created: 2/27/2026
Status: Merged
Merged: 2/27/2026
Merged by: @threepointone

Base: mainHead: codex/fix-unbounded-memory-usage-in-cached-fetch


📝 Commits (2)

  • 6e68559 fix: bound fetch cache key body serialization
  • bff0861 Safeguard cache key serialization from large bodies

📊 Changes

2 files changed (+241 additions, -57 deletions)

View changed files

📝 packages/vinext/src/shims/fetch-cache.ts (+78 -53)
📝 tests/fetch-cache.test.ts (+163 -4)

📄 Description

Motivation

  • The fetch cache key generator previously serialized and fully buffered many BodyInit types (streams, blobs, form data) with no size limit, allowing an attacker to cause unbounded memory growth during cached fetch() calls.
  • The goal is to prevent OOM scenarios while preserving caching behavior for normal-sized bodies and ensuring the original request body remains usable for the real network fetch.

Description

  • Add a configurable hard limit MAX_CACHE_KEY_BODY_BYTES (1 MiB) and a BodyTooLargeForCacheKeyError to guard cache-key body serialization and abort unsafe buffering.
  • Rework stream handling to use ReadableStream.prototype.tee() so one branch is consumed for cache-key hashing while the other branch is forwarded to the real fetch without reconstructing a full in-memory buffer.
  • For bodies that exceed the size limit (Blob, Uint8Array, streamed chunks, FormData files), short-circuit cache-key generation and fall back to passing the request through to originalFetch (i.e., bypass caching) to avoid buffering; _ogBody restoration remains supported for safe cases.
  • Update tests to reflect preserved stream forwarding behavior and add checks that oversized Blob and ReadableStream bodies bypass the cache and still perform the network fetch.

Testing

  • Ran unit tests with pnpm test tests/fetch-cache.test.ts, which passed (54 tests all green).
  • Ran type checking with pnpm run typecheck, which completed successfully with no type errors.
  • New/updated tests exercise stream preservation and oversized-body fallback behavior and passed as part of the test run.

Codex Task


🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/cloudflare/vinext/pull/176 **Author:** [@dknecht](https://github.com/dknecht) **Created:** 2/27/2026 **Status:** ✅ Merged **Merged:** 2/27/2026 **Merged by:** [@threepointone](https://github.com/threepointone) **Base:** `main` ← **Head:** `codex/fix-unbounded-memory-usage-in-cached-fetch` --- ### 📝 Commits (2) - [`6e68559`](https://github.com/cloudflare/vinext/commit/6e68559c82d61c6c1e920c797ddb02cc9a5d2ef3) fix: bound fetch cache key body serialization - [`bff0861`](https://github.com/cloudflare/vinext/commit/bff08610e9bfefb65a360f535f476bc1c0e357dc) Safeguard cache key serialization from large bodies ### 📊 Changes **2 files changed** (+241 additions, -57 deletions) <details> <summary>View changed files</summary> 📝 `packages/vinext/src/shims/fetch-cache.ts` (+78 -53) 📝 `tests/fetch-cache.test.ts` (+163 -4) </details> ### 📄 Description ### Motivation - The fetch cache key generator previously serialized and fully buffered many `BodyInit` types (streams, blobs, form data) with no size limit, allowing an attacker to cause unbounded memory growth during cached `fetch()` calls. - The goal is to prevent OOM scenarios while preserving caching behavior for normal-sized bodies and ensuring the original request body remains usable for the real network fetch. ### Description - Add a configurable hard limit `MAX_CACHE_KEY_BODY_BYTES` (1 MiB) and a `BodyTooLargeForCacheKeyError` to guard cache-key body serialization and abort unsafe buffering. - Rework stream handling to use `ReadableStream.prototype.tee()` so one branch is consumed for cache-key hashing while the other branch is forwarded to the real fetch without reconstructing a full in-memory buffer. - For bodies that exceed the size limit (Blob, `Uint8Array`, streamed chunks, `FormData` files), short-circuit cache-key generation and fall back to passing the request through to `originalFetch` (i.e., bypass caching) to avoid buffering; `_ogBody` restoration remains supported for safe cases. - Update tests to reflect preserved stream forwarding behavior and add checks that oversized `Blob` and `ReadableStream` bodies bypass the cache and still perform the network fetch. ### Testing - Ran unit tests with `pnpm test tests/fetch-cache.test.ts`, which passed (`54 tests` all green). - Ran type checking with `pnpm run typecheck`, which completed successfully with no type errors. - New/updated tests exercise stream preservation and oversized-body fallback behavior and passed as part of the test run. ------ [Codex Task](https://chatgpt.com/codex/tasks/task_e_69a1f69e2e14832396f748a282248f53) --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
BreizhHardware 2026-05-06 12:39:28 +02:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
starred/vinext#371
No description provided.