fix(provider-utils): route provider-response URLs through the download-URL guard#16971
Open
dnukumamras wants to merge 1 commit into
Open
fix(provider-utils): route provider-response URLs through the download-URL guard#16971dnukumamras wants to merge 1 commit into
dnukumamras wants to merge 1 commit into
Conversation
…d-URL guard Make getFromApi validate URLs taken from provider responses and require an explicit trust decision at every call site. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What this does
getFromApiin@ai-sdk/provider-utilsfetches URLs that come from provider response bodies (image, audio, and video downloads, and polling URLs). Those URLs are untrusted, but they were fetched with no scheme, host, or IP checks. This PR routes them through the same guard thatdownloadBlobalready uses.validateUrlflag togetFromApithat routes the request throughfetchWithValidatedRedirects, which rejects private, loopback, and link-local targets and re-validates every redirect hop. Blocked URLs throwDownloadError.AuthorizationandCookieon any redirect that crosses origin, so credentials never follow a redirect to a different host.credentialedOriginoption so caller headers are sent only when the URL is same-origin with the provider's own origin, and withheld otherwise.validateDownloadUrl: IPv4224.0.0.0/4(multicast) and IPv62001:db8::/32(documentation).Secure by default going forward
validateUrlis a required field, with no default. Every current and futuregetFromApicall site has to make an explicit choice, so a new integration cannot silently inherit an unsafe default.truefor a URL that comes from a response body,falsefor a URL built from a configuredbaseURL. The compiler will not let a new call site skip the decision.credentialedOriginfolds credential gating into the same call, so a new integration that opts into validation gets first-hop credential protection without hand-rolling a same-origin check.AGENTS.md,contributing/add-new-provider.md, andcontributing/secure-url-handling.md, plus a user-facing page incontent/docs.Happy path
Unhappy path
DownloadErrorand never fetched.credentialedOrigin, and dropped if a redirect crosses origin.Not solved here
The guard does string and literal-IP checks and does not resolve DNS, so a hostname that resolves to a private address, and DNS rebinding, are out of scope at this layer. These need Node-only APIs (
undici,node:dns) that are not available across all runtimes this package targets (edge, browser, Bun), and the threat is server-only.content/docs/06-advanced/11-secure-url-fetching.mdxexplains how a server deployment closes the gap: restrict network egress, or inject a Nodefetchthat pins the resolved IP at connect time.