Skip to content

fix/unbounded download dos#12445

Merged
gr2m merged 9 commits intomainfrom
fix/unbounded-download-dos
Feb 12, 2026
Merged

fix/unbounded download dos#12445
gr2m merged 9 commits intomainfrom
fix/unbounded-download-dos

Conversation

@gr2m
Copy link
Collaborator

@gr2m gr2m commented Feb 11, 2026

  • Replace unbounded arrayBuffer()/blob() calls in download() and downloadBlob() with streaming reads that enforce a 2 GiB default size limit
  • Add abortSignal passthrough from callers (transcribe, generateVideo) to fetch()
  • Check Content-Length header for early rejection before reading body
  • Track bytes incrementally via ReadableStream.getReader(), abort with DownloadError when limit exceeded
  • Expose configurable download parameter on transcribe() and experimental_generateVideo() (instead of adding a new maxDownloadSize argument) — keeps download config separate from API function signatures
  • Export createDownload({ maxBytes }) factory from ai for custom size limits

closes #9481 / addresses #9481 (comment)

gr2m and others added 5 commits February 10, 2026 20:13
Replace unbounded `arrayBuffer()`/`blob()` calls in `download()` and
`downloadBlob()` with streaming reads that enforce a 2 GiB default
size limit. Add `abortSignal` passthrough from callers (`transcribe`,
`generateVideo`) to `fetch()`.

Add `maxDownloadSize` option to `transcribe()` and
`experimental_generateVideo()` for configuring the limit.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Update API reference docs and fix JSDoc/changeset to reflect actual
1 GiB default (changed from 2 GiB during review). Update test
Content-Length values to match.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace `maxDownloadSize` parameter with a configurable `download`
function in `transcribe()` and `experimental_generateVideo()`. Add
`createDownload({ maxBytes })` factory exported from `ai` so users
can create download functions with custom size limits.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@vercel-ai-sdk vercel-ai-sdk bot added the ai/core core functions like generateText, streamText, etc. Provider utils, and provider spec. label Feb 11, 2026
Co-authored-by: vercel[bot] <35613825+vercel[bot]@users.noreply.github.com>
@lgrammel
Copy link
Collaborator

why is the download blob function in provider-utils when it is only used by the ai package? package churn and api surface could be reduced by moving it into the ai pkg

export { convertToFormData } from './convert-to-form-data';
export { downloadBlob } from './download-blob';
export { DownloadError } from './download-error';
export {
Copy link
Collaborator

Choose a reason for hiding this comment

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

a) could this be part of the ai pkg instead
b) the difference between file and function name is strange

@gr2m
Copy link
Collaborator Author

gr2m commented Feb 12, 2026

why is the download blob function in provider-utils when it is only used by the ai package

it's also used by

I'll look into refactoring but not yet sure if it's worth it.

b) the difference between file and function name is strange

Will fix, thanks

@gr2m
Copy link
Collaborator Author

gr2m commented Feb 12, 2026

I tried some refactoring, but it would lead to a circular dependency or code duplication to move readResponseWithSizeLimit and DEFAULT_MAX_DOWNLOAD_SIZE from provider-utils to ai:

ad95f2a

@gr2m gr2m merged commit 4024a3a into main Feb 12, 2026
18 checks passed
@gr2m gr2m deleted the fix/unbounded-download-dos branch February 12, 2026 19:56
gr2m added a commit that referenced this pull request Feb 12, 2026
- Replace unbounded `arrayBuffer()`/`blob()` calls in `download()` and
`downloadBlob()` with streaming reads that enforce a **2 GiB default
size limit**
- Add `abortSignal` passthrough from callers (`transcribe`,
`generateVideo`) to `fetch()`
- Check `Content-Length` header for early rejection before reading body
- Track bytes incrementally via `ReadableStream.getReader()`, abort with
`DownloadError` when limit exceeded
- Expose configurable `download` parameter on `transcribe()` and
`experimental_generateVideo()` (instead of adding a new
`maxDownloadSize` argument) — keeps download config separate from API
function signatures
- Export `createDownload({ maxBytes })` factory from `ai` for custom
size limits

closes #9481 / addresses
#9481 (comment)

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: vercel[bot] <35613825+vercel[bot]@users.noreply.github.com>
gr2m added a commit that referenced this pull request Feb 12, 2026
## Summary
- Backport of #12445 to `release-v5.0`
- Adds size-limited download via `readResponseWithSizeLimit` to prevent
unbounded memory consumption (DoS)
- Adds `maxBytes` and `abortSignal` parameters to download functions
- Skipped generate-video and download-blob changes (files don't exist on
v5.0)

## Test plan

- [x] Test changes against local POC

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: vercel[bot] <35613825+vercel[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ai/core core functions like generateText, streamText, etc. Provider utils, and provider spec.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants