fix(preview): rate limit anonymous proxy previews per client - #67
Closed
polylane[bot] wants to merge 1 commit into
Closed
polylane[bot] wants to merge 1 commit into
polylane[bot] wants to merge 1 commit into
Conversation
Co-authored-by: polylane[bot] <277585245+polylane[bot]@users.noreply.github.com>
|
Important Review skippedBot user detected. To trigger a single review, invoke the ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Advanced Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Contributor
Author
|
Gilberto closed this pull request from Polylane: Planned |
This branch was successfully deployed
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.
Fixes: cache-app /api/preview is an unauthenticated media proxy that can stream 200 MB per request with no rate limit
The preview endpoint streams upstream media through the app origin, and nothing stopped an anonymous client from pulling fresh URLs without limit, so a burst of requests could exhaust the deployment's bandwidth budget and pause the app. Proxy previews now pass a per-client request budget before any upstream fetch, and callers over the budget receive a too-many-requests response.
What caused this
Affected:
int_0b563423d00164u048hh0sykWhy this fix
The read of
app/api/preview/route.tsconfirmed the finding's harmful behavior: the GET handler fetches a caller-supplied URL for image and video previews with no session check (only the Google Photos branch reads the session), the middleware matcher excludes/api/, and nothing throttles the route. The proxy delivery streams the upstream response through the Vercel origin, so an anonymous client can drive origin egress by requesting fresh URLs; a hot URL is cheap because the CDN serves it, but every miss is a full fetch. The same read shows the egress boundary itself is sound (pinned-address fetch, fail-closed SSRF checks), so this is a cost/abuse lever rather than an SSRF hole. Bandwidth is what pauses this deployment, and the workspace has no monitor or readable request series that would show it happening.The change bounds that lever at the request boundary with the repository's designated rate limiter, keyed per client and applied before any cache lookup or upstream fetch, so an over-limit caller is turned away without spending bandwidth. Cached, CDN-served, and redirect responses are unaffected, and the authenticated Google Photos branch is exempt.
Recorded as remaining work on the issue timeline, not fixed here: the 200 MB video cap and off-origin video delivery, the unthrottled
delivery=redirectresolution path, the control's fail-open behavior when Arcjet is unreachable, and the separately filed plan and monitoring gaps. Until those land, a determined client can still move real bandwidth within the per-client allowance, and a plan-driven pause would still be discovered by users rather than the team.Out of scope
delivery=redirectpath, which does not stream origin bytes but still triggers outbound resolution with no limit.Causal chain
1 file changed (+29/-0)
app/api/preview/route.ts: modified, +29/-0Generated by Polylane. You can ask follow-ups by mentioning @polylane in a comment.