AntFleet

Disagreement · f1b5393a-openai-0

Health endpoint exposes operational details (env var presence, raw DB error messages) to unauthenticated callers

mismatch
repo ab4e09bc·PR #3·reviewed 2 weeks ago

Primary finding

Health endpoint exposes operational details (env var presence, raw DB error messages) to unauthenticated callers

highsecurityhigh
  • apps/web/app/api/health/route.ts:5-11
  • apps/web/app/api/health/route.ts:37-41
  • apps/web/app/api/health/route.ts:47-51
  • apps/web/app/api/health/route.ts:55-58
The health endpoint is publicly accessible and intended for external uptime checks. It returns a detailed JSON payload that includes an explicit list of missing environment variable names and a raw database error message. DB error messages can reveal internal infrastructure details (hosts, driver info) and the env.missing array confirms which secrets are configured. This is unnecessary information disclosure for unauthenticated callers and increases the attack surface. A minimal health check should avoid leaking internal state beyond an overall status code or a simple boolean, or require authentication for detailed diagnostics.

Recommendation

For unauthenticated requests in production, limit the response to a simple status (e.g., { ok: boolean } or just HTTP 200/503) and omit fields like env.missing and db.error. Optionally gate detailed diagnostics behind authentication (e.g., require a secret header, signed token, or internal allowlist), or only include details in non-production environments. At minimum, sanitize/replace DB error messages with a generic string and avoid enumerating missing env vars to the public.

Counterpart finding

Health endpoint leaks which secrets are missing to unauthenticated callers

mediumsecurityhigh
  • apps/web/app/api/health/route.ts:17-26
  • apps/web/app/api/health/route.ts:53-57
The GET handler has no authentication and returns the `missing` array verbatim in the JSON response. A public, anonymous attacker hitting /api/health can enumerate exactly which production secrets are unset (e.g. ANTHROPIC_API_KEY, GITHUB_APP_WEBHOOK_SECRET, CRON_SECRET). This is a directly useful reconnaissance signal: knowing CRON_SECRET is unset means the cron endpoint can be invoked; knowing GITHUB_APP_WEBHOOK_SECRET is unset means webhook signature verification is likely disabled. Additionally the DB error string is echoed (err.message), which on connection failures typically contains the DB host, user, and sometimes credentials parsed from DATABASE_URL by pg/drizzle, leaking infra topology. Standard practice is to return a boolean ok/not-ok publicly and gate the detailed payload behind a shared secret (e.g. the existing CRON_SECRET) or an internal-only path.

Recommendation

Either (a) require an auth header (Bearer of CRON_SECRET or a dedicated HEALTH_TOKEN) before returning the detailed payload and otherwise return only `{ok}` with status, or (b) drop the `missing` array and `error` string from the public response and log them server-side instead.

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.