AntFleet

Disagreement · 9b74dece-openai-0

Opt-in route 500s if OPTIN_HMAC_SECRET is missing (no graceful handling)

mismatch
repo e24ef98c·PR #9·reviewed 1 week ago

Primary finding

Opt-in route 500s if OPTIN_HMAC_SECRET is missing (no graceful handling)

mediumbughigh
  • apps/web/lib/optin-token.ts:1-200
  • apps/web/app/api/opt-in/route.ts:1-200
verifyTokenDetailed() calls getSecret(), which throws if OPTIN_HMAC_SECRET is unset. handleOptIn() calls verifyTokenDetailed() without try/catch, so the request will crash with a 500 and no targeted error/log context. This is a server misconfiguration path that should be handled gracefully to aid operations and avoid noisy 5xx.

Recommendation

- In the route, guard the token verification with a try/catch that logs a clear server-misconfig event and returns a 500 with a generic error page. - Alternatively, validate OPTIN_HMAC_SECRET at module init of the route (or app startup) and fail fast with a clear boot-time error, preventing the app from serving until the secret is present. - Example: at top-level of route.ts, read process.env.OPTIN_HMAC_SECRET and if missing, log and export a GET that returns a 500 error page with a friendly message (no details about secrets). - Consider adding a healthcheck that asserts required env vars are present.

Counterpart finding

verifyTokenDetailed calls getSecret() before MAC length check — secret-missing surfaces as 500 on any request

lowbugmedium
  • apps/web/lib/optin-token.ts:68-76
  • apps/web/app/api/opt-in/route.ts:41-55
If OPTIN_HMAC_SECRET is unset in production by misconfiguration, verifyTokenDetailed throws (per getSecret), and handleOptIn does not catch — it bubbles as an unhandled rejection and returns a 500 with no user-friendly page. The error page infrastructure exists; using it would also avoid leaking the secret-missing condition through stack traces in logs. This is a low-severity ops issue, not a logic bug, but the route file claims to render errorPage for all bad-token cases.

Recommendation

Either wrap verifyTokenDetailed in try/catch in handleOptIn (returning a generic 500 errorPage), or have verifyTokenDetailed return {kind:"invalid"} when the secret is missing (less safe — masks misconfig).

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.