AntFleet

Disagreement · 70f6bb2c-anthropic-2

Opt-in link is a 30-day bearer credential vulnerable to referer/log leakage and replay-as-disable

solo Opus
repo e24ef98c·PR #9·reviewed 1 week ago

Opus finding

Opt-in link is a 30-day bearer credential vulnerable to referer/log leakage and replay-as-disable

mediumsecurityhigh
  • apps/web/lib/optin-token.ts:1-10
  • apps/web/lib/optin-token.ts:11
  • apps/web/app/api/opt-in/route.ts:34-40
The comment claims 'replay inside the validity window is a no-op, not an exploit' but that's only true if the desired and current states already match. An attacker who obtains the token (HTTP referer headers leaked to third parties from the GitHub PR comment page, browser history, server access logs at any intermediate proxy, screenshare, etc.) can flip state in either direction by toggling &action=disable. Concretely: maintainer enables → attacker disables (hides receipts) or vice versa. The action parameter is unauthenticated — only the token is signed, and the same token serves both enable and disable. GitHub comment URLs are public on public repos, but tokens for private-repo installs travel through GitHub which is an auth boundary; still, any log/referer leak gives 30 days of toggle power. The 'no-op' framing in the docstring is misleading because action=disable inverts the meaning.

Recommendation

Either (a) bind the action to the token (sign {installation, owner, repo, action, exp}, mint separate enable/disable tokens), or (b) require the requesting GitHub user to authenticate (OAuth) before honoring a state change, or (c) drastically shorten the TTL (hours, not 30 days) and reissue from the comment on demand. At minimum, fix the docstring's 'replay is a no-op' claim — it's only true within the same action.

Other reviewer

The other reviewer flagged nothing in this file/line range.

Why this didn't post

This finding didn't meet AntFleet's unanimous agreement threshold. Both frontier models review every PR independently; only findings they both flag with the same severity and category are posted to the PR. This one fell through.

read the methodology →

From the same review

These findings passed the unanimous gate on the same PR review. The disagreement above was filtered out; the findings below were posted.