Repository navigation
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
104bfaf to
ed43299
Compare
On Vercel, or locally after `vercel env pull`, verify override tokens which the Vercel Toolbar signs with Vercel KMS, alongside FLAGS_SECRET tokens. Share the host project lookup and the JWKS cache with the platform encryption of the flag values. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ds group Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…lues Rename vercel-overrides to flag-overrides-platform, and use the same shape as flag-values-platform: an exported issuer, JWKS URL and frozen policy, a publicKeys cache, and the FromPlatform/ForPlatform names. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Apps which read the vercel-flag-overrides cookie themselves call decryptOverrides, so it verifies overrides signed by Vercel KMS too. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
chriswdmr
left a comment
There was a problem hiding this comment.
Thanks! Two things to fix before approval:
- SvelteKit: signed overrides do not work in local development, because
vite devdoes not put.env.localvalues inprocess.env - Replace the nested ternary in SvelteKit
flag()and add braces to theifinisInScope(AGENTS.md)
The other comments are non-blocking. The "Shared with #586" part and the test count in the description are out of date.
| publicKeys.set(issuer, keys); | ||
| return async (header, token) => { | ||
| try { | ||
| return await (await keys.get())(header, token); |
There was a problem hiding this comment.
suggestion (non-blocking): The key fetch has no timeout
createKeySetCache (from #586) calls fetch with no signal. With this PR, a flag call for a request with a signed cookie waits on that fetch. If the key set endpoint does not answer, the flag call does not settle. This also occurs when keys are in memory but older than 5 minutes, because get() waits for the reload.
An AbortSignal.timeout(...) on the fetch, and the keys in memory as the result during a reload, would fix it. This can go in #586.
There was a problem hiding this comment.
The timeout is in #586 (4196d37): 5 s with AbortSignal.timeout.
I did not make get() return the keys in memory during a reload. With the timeout, the wait is at most 5 s, and when the reload fails or times out, the keys in memory are used. Keys in memory as the result during each reload would let a revoked key verify tokens after the 5 minutes. Tell me if you prefer it anyway.
…er/kms-signed-overrides Co-Authored-By: Claude Code <noreply@anthropic.com>
- SvelteKit: verify signed tokens in vite dev, where the variables of vercel env pull are only in $env - Replace the nested ternary in SvelteKit flag() with one guard - Next.js: ignore an overrides cookie which the host can not read without a secret, instead of throwing - Warn with the cause when a signed token is ignored - Do not need a process global to check for a signed token - Set the key cache entry only when it is missing - More rejection tests for the verifier Co-Authored-By: Claude Code <noreply@anthropic.com>
…er/kms-signed-overrides
…he request Co-Authored-By: Claude Code <noreply@anthropic.com>
Summary
Lets v4 apps accept flag overrides that the Vercel Toolbar signs with Vercel KMS, so overrides work on Vercel without a
FLAGS_SECRET. This is the SDK half of vercel/next-live-mode#3898.vercel-flag-overrides, and no exports change.VERCEL), or locally aftervercel env pull(VERCEL_OIDC_TOKEN), a 3-part JWS is verified as a Vercel-signed token. Everything else goes to the existingdecryptOverrides, unchanged. Signed andFLAGS_SECRETtokens are dual-read, so the Toolbar can roll signing out to projects that still have aFLAGS_SECRET.src/lib/flag-overrides-platform.ts, shaped likeflag-values-platform.ts: exported issuer, JWKS URL and frozenFLAG_OVERRIDES_POLICY;isFlagOverridesFromPlatform/verifyFlagOverridesFromPlatform):https://kms.vercel.com/64af96a2-ba60-42ef-91af-459fcef6f864; audvercel:flag-overrides; purflag-overrides; ver 1; requirediat/exp; at most 7-day lifetime.kidand nojku/jwk/x5u/crit. The token is limited to 16 KB.scope.projectIds(all projects of a microfrontends group share the cookie), its environment inenvironments, and the team must match when known. Unknown scope keys are rejected.projectIdsdiffers fromscope.projectIdin the v5 standard, which needs the same change.src/lib/vercel-platform.ts, which [flags] Encrypt FlagValues with the public key of Vercel without FLAGS_SECRET #586 adds withfindVercelProject()andcreateKeySetCache()). This PR adds:isVercelSignedToken()/verifyVercelSignedToken(): the checks above for a given issuer and policy, so [flags] accept Vercel-signed tokens for flags discovery #589 can use them for the discovery tokens.VERCEL,VERCEL_PROJECT_ID). Locally,vercel env pullsupplies theVERCEL_OIDC_TOKEN. SvelteKit reads it from$envtoo, becausevite devdoes not put.env.localinprocess.env.flags: Missing FLAGS_SECRET. SvelteKit already did this.Notes for reconciling with
standard(v5)standardrejects signed tokens whenFLAGS_SECRETis set. This PR intentionally accepts them, because the Toolbar signs for all projects behind its rollout flag. v5 needs the same rule before it ships.standardreadsflag-overridesfirst, thenvercel-flag-overrides, so v5 already works with the Toolbar writingvercel-flag-overrides.standard'svercel.ts. This module is a reduced copy: no options object, and ES256 only.Test plan
pnpm type-check,pnpm check,pnpm buildandpnpm attwpasspnpm test: 229/229 pass, including [flags] Encrypt FlagValues with the public key of Vercel without FLAGS_SECRET #586's tests unchanged, a secret-less SvelteKit signed-override test, and a SvelteKit test with the variables only in$env🤖 Generated with Claude Code