Repository navigation
fix: harden the Vercel pairing flow before release - #14
Merged
Merged
Conversation
A Vercel 401 used to become a generic 502, so an expired or revoked token looked like a network failure and never asked for reconnection. Map it to 401, which the client already treats as expired, and add nosniff to the callback response.
The app reads VercelWorkerURL and VercelIntegrationSlug from its Info.plist, but nothing supplied them, so every build was inert. make app now fills them from VERCEL_WORKER_URL and VERCEL_INTEGRATION_SLUG; without them the keys are absent and the Vercel UI stays hidden.
Record the pairing model, ten findings with severity and status (two fixed here), the residual risk before a public release, the exact README and CONTRIBUTING changes needed for the opt-in network exception, and the deployment steps that need the owner's accounts.
The runbook asked for wrangler secret put before the Worker existed, and never said that Vercel assigns the client ID and secret when the integration is created. Deploy first, then create the integration with the redirect URL, then store the three values.
A cd failure sends wrangler deploy to a directory with no wrangler.toml, where it looks for a Pages project and fails; record that and add a 401 smoke test for the deployed Worker.
Vercel answers the token exchange with team_id null for a personal account; the Worker required a string and rejected a successful authorization with 502. Store an empty team and omit teamId in that case. Also move to /v6/deployments, the endpoint in Vercel's current reference, and cover both with tests.
An exception during the token exchange surfaced as an opaque Error 1101 page, hiding the cause. The callback now catches it, returns a short JSON reason, and logs the exchange status plus whether each secret binding is present, without printing any value. Add tests for a network failure and a non-JSON authorization response.
Cloudflare Workers rejects fetch redirect: 'error' at runtime, even though Node accepts it, so the callback threw an unhandled exception and showed Error 1101 after a successful authorization. Use redirect: 'manual' and refuse any 3xx explicitly, in both the token exchange and the deployments call. Record the finding and cover the redirect case.
The flow completed against production on 2026-11-04 (team install: start, Vercel authorization, callback, connected). Record what that does and does not prove, and keep the checklist for the next change.
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.
Linked issue
Closes #13
What and why
The Vercel integration is blocked less by code than by three things: an unreviewed pairing flow, a
build that can never be configured, and a privacy promise that contradicts the feature. This PR
closes what can be closed without your accounts.
docs/vercel-security-review.mdwalks the pairing model and lists ten findings withseverity and status. Two are fixed here; the rest are documented residual risk, including the
review not being independent.
401used to become a generic502, so an expired or revoked tokenlooked like a network failure and never asked to reconnect; it now maps to
401, which the clientalready treats as expired. The callback response also gained
nosniff.make appnow fillsVercelWorkerURLandVercelIntegrationSlugfromVERCEL_WORKER_URL/VERCEL_INTEGRATION_SLUG. Nothing is committed, and without the variablesthe keys stay absent, so a dev build is inert exactly as before.
docs/vercel-privacy.mdhas the exact README and CONTRIBUTING changes thefeature needs: the current "never sends anything anywhere" becomes "never sends your agent
activity", with one opt-in exception. It is drafted, not applied, because it is your promise.
Vercel integration registration, building a release that reaches it) plus an end-to-end checklist.
Changes
integrations/vercel-worker/index.mjs401from Vercel maps to401;nosniffon the callbackintegrations/vercel-worker/index.test.mjsMakefileVERCEL_WORKER_URL/VERCEL_INTEGRATION_SLUGinjection before signingscripts/release.shdocs/vercel-security-review.mddocs/vercel-privacy.mdintegrations/vercel-worker/README.mddocs/vercel-deployment-monitoring.mdHow I tested it
node --test integrations/vercel-worker/index.test.mjspasses (6 tests)bash -n scripts/release.shpassesmake appwithVERCEL_WORKER_URLwrites both keys into the packagedInfo.plist; without them the keys are absent (verified by extracting both ways)No Swift sources changed, so the Swift build and tests are unaffected; CI will still run them.
What still needs you
integrations/vercel-worker/README.md.