groundy
developer tools

Vercel CLI Now Signs Blob URLs: Moving Access Control Off the App Server

Vercel CLI 5.14.5 adds vercel blob presign for scoped, time-limited blob access without per-request app-server auth. Revocation requires expiry or key rotation.

8 min · · · 3 sources ↓

Vercel CLI 5.14.5 ships vercel blob presign, a command that mints time-limited, operation-scoped URLs for private Vercel Blob objects without touching your application server. Teams that currently funnel every private download through an auth middleware now have the option to hand users a pre-authorized URL that expires on its own terms, with the usual tradeoff: what the signed URL model gains in server-side simplicity, it concedes on revocation.

What does vercel blob presign generate?

A signed URL is scoped to exactly one operation, one pathname, and a caller-specified expiry window, according to Vercel’s June 22 changelog. The default invocation issues a signed GET URL:

Terminal window
vercel blob presign media/photo.jpg --access private

That covers the common case: downloading a private asset with a link you can pass to a user or embed in a notification. For upload flows, PUT operations can be constrained further. The --allowed-content-type flag limits what MIME types the recipient can push, and --maximum-size-in-bytes caps payload size. Per the changelog:

Terminal window
vercel blob presign uploads/image.jpg --access private \
--operation put \
--allowed-content-type image/* \
--maximum-size-in-bytes 10485760

Supported operations are get, head, put, and delete. One command, one blob, one operation, the scope doesn’t stretch.

That constraint is the point. A signed URL scoped to a GET on media/photo.jpg cannot be replayed as a DELETE or redirected to media/other.jpg. The blast radius of a leaked link is bounded by the scope at minting time, which is a more defensible position than a raw API key with write access to the whole store.

How does vercel blob signed-token differ from presign?

vercel blob signed-token decouples token generation from URL generation entirely, according to Vercel’s changelog. It produces delegation tokens and client-signing tokens that can be piped into a subsequent presign call.

The separation matters for agent and CI pipelines. Consider an orchestrator that holds the full blob store key alongside a batch job running in a restricted environment that needs to generate download URLs for individual files. Without delegation tokens, the batch job needs the store key, which means a compromised batch job forces a rotation of the whole store credential. With the signed-token flow, the orchestrator generates a scoped delegation token, passes it to the batch job, and the batch job calls presign with that token rather than the root key.

The orchestrator retains the blast radius; the agent only holds delegation authority. Whether that separation matters in practice depends on your key management posture, but for teams running agent pipelines on Vercel, the platform has positioned itself around agentic infrastructure, this is the pattern the command is designed for.

How do expiry and scripting work?

Expiry is controlled via --valid-for and --valid-until, as documented in the changelog. The former accepts human-readable durations (15m, 1h, 7d); the latter takes an absolute timestamp for cases where the URL needs to expire at a specific wall-clock time rather than a relative offset. The maximum window is 7 days.

For scripting pipelines, passing --json returns structured output rather than a bare URL string:

Terminal window
vercel blob presign media/photo.jpg --access private --valid-for 1h --json

The JSON response includes the URL, the operation, and the expiry time, per the changelog. A downstream pipeline step can read the expiry field and decide whether a previously minted URL is still safe to use, rather than guessing from a fixed window baked into the script. For batch jobs generating URLs ahead of time and queuing them for later consumption, that’s a practical difference from parsing a raw URL string with an opaque token.

What is the revocation problem, and why does it matter?

A signed URL minted with vercel blob presign is valid until its expiry elapses, according to the changelog.

This is structural to the stateless signed-URL model, not a gap specific to Vercel’s implementation. Signed URLs derive their authority from a cryptographic signature over the parameters. Checking that signature at request time requires no database lookup and no per-request auth call, the storage layer validates the token math and serves the content. The efficiency gain is real. The cost is that individual URL revocation before expiry is an inherent limitation of stateless token validation.

S3 presigned URLs have the same property. The efficiency tradeoff is the same: stateless validation eliminates per-request auth overhead while making individual URL revocation impractical.

For teams running leak-sensitive workflows, sending download links to users who might forward them, or embedding URLs in documents that could be shared, the practical implication is direct: short expiry windows are the only readily available mitigation. A 15-minute URL that leaks is a 15-minute problem. A 7-day URL that leaks is a 7-day problem.

When should you use signed URLs instead of request-time middleware?

The right answer depends on who calls your auth check and how often. Request-time auth middleware is flexible: every download passes through your application server, you can check permissions on each request, and access can be revoked instantly by updating a session or permission record. The cost is the round trip, each download hits your application layer before reaching the object store.

Signed URLs invert the flow. The application server does one operation (minting the URL) and then steps out of the serving path entirely. The client goes directly to Vercel’s blob infrastructure with a pre-authorized token. This works well when:

  • Assets are large and routing them through an app server is expensive or slow.
  • The download recipient is a machine or agent that will consume the asset once, soon, without caching the URL.
  • Permission state is stable between when you mint the URL and when it’s consumed.

It works poorly when:

  • Permissions can change in flight (a user account suspended mid-session).
  • URLs will pass through untrusted intermediaries before consumption.
  • The operation is destructive (DELETE or a broadly scoped PUT) and the minting context is less trusted than the signing key implies.

The signed-token delegation pattern shifts the trust boundary rather than eliminating it. An orchestrator minting a delegation token for a batch job still decides what scope to grant, and cannot revoke the delegation token once issued. The chain of trust gets longer; the revocability gap at each link remains.

How do you get the new commands?

Upgrading to CLI 5.14.5 or later picks up both vercel blob presign and vercel blob signed-token, per Vercel’s changelog:

Terminal window
npm i -g vercel@latest

Both commands operate against the Vercel Blob store associated with your project’s linked environment. You’ll need a linked project (vercel link) and a Blob store attached to it for presign calls to resolve.

The addition is CLI-only as announced. The Vercel Blob JavaScript SDK already supports signed URL generation on the SDK side; the new CLI surface makes the same capability available in shell scripts, Makefiles, and CI steps without requiring you to instantiate the SDK outside your application. For teams already using the SDK in application code, the CLI version closes the scripting gap rather than replacing the SDK path.

The delegation token pattern addresses a real gap for agent-oriented toolchains specifically. An orchestrator in a privileged environment generates a scoped delegation token, passes it to a subprocess via environment variable or stdin, and the subprocess mints its own signed URLs without the root key appearing anywhere in its environment. Whether that’s enough for your access control posture depends on how much operational weight you’re willing to put on expiry windows as your revocation mechanism. The answer shapes whether you reach for presign directly, combine it with short-lived delegation tokens, or keep request-time middleware in the path for anything where instant revocation is a hard requirement.

Frequently Asked Questions

Does rotating the Vercel Blob signing key revoke outstanding signed URLs immediately?

Yes. Key rotation invalidates all previously minted signed URLs across all expiry windows, because each URL’s signature is verified against the current signing key at request time. This is the only path to immediate revocation available. The cost is real: any URL already distributed to users, queued pipelines, or partner systems stops working the moment the key rotates. That asymmetry is the underlying reason short expiry windows carry more operational weight than key discipline alone.

The Vercel Blob JavaScript SDK already generates signed URLs. When does the CLI surface actually add something?

The SDK path requires importing a Node.js module inside application code, which is straightforward in serverless functions but unavailable in shell scripts, Makefiles, or CI steps that run outside a Node environment. The CLI lets a bash script or a GitHub Actions step mint a signed URL with a single subprocess call, without standing up a Node.js runtime or an application entry point to host the SDK call. The two paths produce equivalent URLs; the difference is where in the pipeline the signing step lives.

What is a signed HEAD URL for, and how does it differ from a signed GET URL in practice?

A signed HEAD request returns only the response headers (content-type, content-length, ETag) without transferring the blob body. An agent that needs to verify a file exists and check its size before starting a downstream job can issue a HEAD check at negligible bandwidth cost, compared to probing with a GET that downloads the full asset only to discard it. The --operation head flag scopes the URL to that metadata check only, so the token cannot be replayed as a full download.

Yes. Setting VERCEL_TOKEN, VERCEL_ORG_ID, and VERCEL_PROJECT_ID as environment variables in the CI context satisfies the project-linking requirement without the interactive prompt that vercel link produces locally. Without those three variables the CLI cannot resolve which blob store to sign against and exits with an error. For teams already passing VERCEL_TOKEN to CI for deployments, adding the org and project IDs is the only additional configuration step.

sources · 3 cited

  1. Vercel CLI now supports signing blob URLs - Vercel vercel.com vendor accessed 2026-06-26
  2. Agentic Infrastructure - Vercel vercel.com vendor accessed 2026-06-26
  3. Vercel - Wikipedia en.wikipedia.org analysis accessed 2026-06-26