Skip to content

feat(vercel): Blob token verification and client uploads - #317

Draft
scotttrinh wants to merge 1 commit into
mainfrom
blob-token-verification
Draft

scotttrinh wants to merge 1 commit into
mainfrom
blob-token-verification

Conversation

@scotttrinh

@scotttrinh scotttrinh commented Oct 14, 2026 •

Copy link
Copy Markdown
Contributor

Every Blob endpoint (put, copy, head, list, delete and multipart create, upload and complete) now goes through one authenticate(c, operation) helper instead of trusting the store id it could parse out of a token. Read-write and client tokens take their store id from the token and ignore x-vercel-blob-store-id; any other bearer token is treated as OIDC and uses that header. Read-write tokens must exactly match the store's registered token, client tokens are limited to put and multipart operations, and a valid client token is decoded, checked for expiry, then re-signed with the store's read-write token and compared timing-safely. Public content under /blob/... is still unauthenticated. Stores live in a new blobStores collection (storeId, rwToken, access, createdAt) that later store lifecycle work can build on.

With verified client tokens in place, browser uploads through handleUpload() work end to end. The signed values for addRandomSuffix, cacheControlMaxAge, allowOverwrite and ifMatch replace the request headers, and the signed pathname (compared before the random suffix, using the same leading-slash normalization as the request), allowed content types (including type/*) and maximum size (measured on the actual body) are enforced before anything is written. The requested pathname and the stored key are now separate values. After a successful client-token PUT the emulator posts blob.upload-completed with the same blob object the PUT returned plus the token's tokenPayload, signed as hex HMAC-SHA256 over the exact body with the store's read-write token, x-vercel-signature-type: rw_token, and a JSON content type for API versions above 4. Delivery runs in the background and a failing callback never fails the upload.

This flips the two Vercel Blob credential verification tests and all of Vercel Blob browser client tokens (the signed-token upload, the four server-side constraint cases for expiry, pathname, MIME type and size, the forged store secret, signed options overriding headers, and the callback). The new client-token gate also made the list and delete cases of the browser permissions parameterization pass, so that it.fails.each is split: those two are now plain it.each and signed-token stays failing until the signed-token endpoint exists. The shared beforeAll now makes one list() call with the test token so client-token tests also pass when run on their own.

Two behaviors here are deliberately emulator-only, and the docs say so. To keep the zero-config setup working, an unknown store is auto-registered by the first well-formed vercel_blob_rw_<storeId>_<secret> token that names it, and after that only that exact token is accepted for it. OIDC tokens cannot be verified offline, so the literal local-oidc-token and any JWT-shaped token (three base64url segments) are accepted without verification and anything else gets 403 Invalid token. OIDC requests still need x-vercel-blob-store-id, but their stores do not have to be registered.

Left out on purpose: multipart part upload and completion (still 400 after authenticating), signed tokens and presigned URLs, TTL, private access, and any HTTPS upgrade, SSRF filtering or deployment-protection handling for the upload-completed callback, which is sent to the URL exactly as given so local http:// callbacks work.

Generated with Claude Code

Co-Authored-By: Scott Trinh <1682194+scotttrinh@users.noreply.github.com>
@vercel

vercel Bot commented Oct 14, 2026 •

Copy link
Copy Markdown
Contributor

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
emulate Ready Ready Preview, v0 Oct 14, 2026 9:28pm UTC

@vercel-security-reviewer

Copy link
Copy Markdown

Security review details

@scotttrinh

Copy link
Copy Markdown
Contributor Author

note: discussed the security review details, and they are moot for the use case that emulate has (local development, end-to-end testing, etc).

This branch was successfully deployed

1 active deployment
Preview — 19e5a446 Deployed Oct 14, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant