fix(integrations): don't persist unverified GitHub installation_id (CS-710)#3370
Merged
Conversation
The GitHub App install callback returns an `installation_id`, which GitHub's own docs document as not trustworthy (it can be spoofed on the callback URL). The previous code stored it on the connection metadata, but nothing reads it anywhere, so it was unused data that a future installation-token flow could later trust unsafely. Remove the storage (and its now-unused query fields + test). If GitHub App installation-token auth is added later, resolve the installation via `GET /user/installations` with the user token — which also proves the user owns it — instead of trusting the callback value. No behavior change: the integration authenticates with the OAuth user token, which is unaffected. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XyttkYNbkdYRp7DBKNuFVH
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
claudfuen
pushed a commit
that referenced
this pull request
Jul 7, 2026
# [3.99.0](v3.98.1...v3.99.0) (2026-07-07) ### Bug Fixes * **integrations:** don't persist unverified GitHub installation_id ([#3370](#3370)) ([9c6f6fa](9c6f6fa)) * **isms:** lock before writing control links so edits serialize with approve ([#3369](#3369)) ([a21f866](a21f866)) * **isms:** production-deploy review follow-ups (CS-701) ([#3365](#3365)) ([d756d4a](d756d4a)), closes [#3364](#3364) * **isms:** serialize approve against ALL register/content edits (central lock) ([#3367](#3367)) ([5c88a3d](5c88a3d)) * **isms:** serialize approve/decline to prevent concurrent double-publish (CS-701) ([#3366](#3366)) ([b158bc9](b158bc9)), closes [#3364](#3364) ### Features * **integrations:** add read-only GitHub App integration (CS-710) ([#3363](#3363)) ([a5a9243](a5a9243)) * **isms:** document versioning and history (CS-701) ([#3361](#3361)) ([d95dc2e](d95dc2e))
Contributor
|
🎉 This PR is included in version 3.99.0 🎉 The release is available on GitHub release Your semantic-release bot 📦🚀 |
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.
What & why
The GitHub App install callback returns an
installation_id. GitHub's own docs state this value should not be trusted — it can be spoofed on the callback URL. The initialgithub-appintegration stored it on the connection'smetadata, but nothing in the codebase reads it (verified: written in one place, read in zero). It was unused data that a future installation-token flow could later trust unsafely.This removes the storage so there's no untrusted value sitting around waiting to be trusted.
Follow-up to CS-710 (cubic flagged it on the production deploy PR #3364).
Changes
installation_idpersistence block from the OAuth callback.installation_id/setup_actionfields from the callback query type.NOTEat the call site explaining the decision, so it isn't naively re-added.No behavior change
The integration authenticates with the OAuth user token (obtained from the
codeexchange), which is untouched. Connect, token storage, and all checks work identically. The removed field was never used, so this is a no-op functionally.If installation-token auth is added later
Resolve the installation via
GET /user/installationswith the user token — which also proves the user owns it — rather than trusting the callback value. (This is GitHub's recommended approach.)Verification
oauth.controller.spec: 21 passgithubInstallationId🤖 Generated with Claude Code
Summary by cubic
Stop storing the GitHub App
installation_idfrom the OAuth callback to avoid persisting spoofable data; no behavior change to auth or connect flows. Aligns with CS-710 by tightening the GitHub App migration to least-privilege, trusted data only.installation_id/setup_actionon connections, deleted unused query fields and obsolete test.installation_id; if installation-token auth is added later, resolve viaGET /user/installationswith the user token.Written for commit b72ae40. Summary will update on new commits.