Skip to content

fix(oauth): narrow MINT_REPO_TOKEN's response with typeof before storing it - #6988

Open
pedrofrxncx wants to merge 1 commit into
mainfrom
fix/github-mint-token-typeof-w3
Open

fix(oauth): narrow MINT_REPO_TOKEN's response with typeof before storing it#6988
pedrofrxncx wants to merge 1 commit into
mainfrom
fix/github-mint-token-typeof-w3

Conversation

@pedrofrxncx

@pedrofrxncx pedrofrxncx commented Sep 4, 2026

Copy link
Copy Markdown
Collaborator

Source: bug found while hardening the OAuth token-refresh lane (apps/api/src/oauth/).

Why: github-mint.ts's mintRepoToken reads res.structuredContent?.token from the (untrusted) response of the MINT_REPO_TOKEN MCP tool call and passes it straight through as the connection's accessToken, trusting an unchecked as MintResult cast. Every sibling OAuth response-parsing path in this same directory (refresh-access-token.ts's access_token/expires_in handling) explicitly narrows with typeof before trusting server-controlled fields — this one didn't, so a malformed or non-string token/expiresAt from a misbehaving/misconfigured mcp-github-slugged connection would reach the token vault (tokenStorage.upsert) as a non-string accessToken, or produce an Invalid Date for expiresAt.

Fix: extracted the parsing into a pure extractMintedToken(res) helper that:

  • rejects (RECONNECT_ERROR) when structuredContent.token isn't a non-empty string (matches the access_token typeof-guard pattern in refresh-access-token.ts)
  • only accepts expiresAt when it's a string that parses to a valid Date, otherwise falls back to null (the existing resolveGhsExpiry fallback then computes a safe expiry)

Behavior-preserving for well-formed responses (byte-identical logic, just extracted + typeof-guarded); the only behavior change is refusing to persist a malformed field instead of silently trusting it.

Verify: bun test apps/api/src/oauth/github-mint.test.ts — 6 new cases covering isError, missing/non-string token, and non-string/unparseable expiresAt, plus the existing resolveGhsExpiry suite, all green.

Checks run locally: bun run fmt, cd apps/api && bunx tsc --noEmit, the targeted test file above, bunx oxlint on both changed files (0 warnings/errors). Full CI validates the rest.


Summary by cubic

Hardens the OAuth token-refresh lane by type-checking MINT_REPO_TOKEN's response before persisting it, so malformed tool output can't reach the token vault.

  • Extracts parsing into extractMintedToken, which rejects non-string tokens and falls back to null expiry for invalid dates.
  • Throws RECONNECT_ERROR when the token is missing or not a string, matching the pattern in refresh-access-token.ts.
  • Behavior is unchanged for well-formed responses; only malformed fields are now rejected.

Written for commit c49a095. Summary will update on new commits.

Review in cubic

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