AntFleet

Anatomy · 6084d1ea-1

Synchronous child_process calls block the Node event loop on every request

mediumperformanceclosed in 4b9b492
repo 6f7fc663·PR #3·reviewed 1 week ago·closed 1 week ago

The vulnerable code

dashboard/app/api/secrets/route.ts:33-50

33 try {
34 execSync('gh auth status', { stdio: 'pipe' })
35 return true
36 } catch {
37 return false
38 }
39}
40
41function listSecrets(): string[] {
42 try {
43 const out = execSync('gh secret list --json name -q ".[].name"', {
44 stdio: 'pipe',
45 cwd: process.cwd(),
46 }).toString().trim()
47 return out ? out.split('\n').filter(Boolean) : []
48 } catch {
49 return []
50 }

The reasoning

Opus

Missing authentication/authorization on secrets API exposes GitHub secret management to any caller

criticalsecurityhigh
  • dashboard/app/api/secrets/route.ts:59-119
The route exports GET/POST/DELETE handlers that list, set, and delete GitHub repository secrets via the `gh` CLI. There is no authentication, authorization, CSRF check, origin check, or session validation. If this Next.js dashboard is ever exposed beyond localhost (or reachable via a CSRF/DNS-rebinding/LAN attack from a browser), any caller can enumerate secret names, overwrite any secret matching `[A-Z][A-Z0-9_]+` (including builtins like ANTHROPIC_API_KEY or GH_GLOBAL) with attacker-controlled values, or delete them — silently pivoting CI to attacker credentials. Even on a local dev box this is reachable via CSRF because POST/DELETE bodies are JSON but no `Origin`/`Content-Type` enforcement exists (a form-encoded POST will be parsed by `request.json()` failing, but a fetch from a malicious page with `Content-Type: text/plain` can still send JSON in many configurations; more importantly any tool on the host can hit it).

Recommendation

Require authentication on all three handlers (session/token check, or restrict the route to bind only to loopback and verify Origin/Host headers to mitigate CSRF/DNS-rebinding). At minimum, gate behind an env-token header and reject if request `Origin` is not same-origin.

GPT-5

Secrets API endpoints lack authentication/authorization; unauthenticated clients can list/set/delete repository secrets via GH CLI

criticalsecurityhigh
  • dashboard/app/api/secrets/route.ts:53-77
  • dashboard/app/api/secrets/route.ts:79-105
  • dashboard/app/api/secrets/route.ts:107-125
  • dashboard/app/api/secrets/route.ts:90-93
  • dashboard/app/api/secrets/route.ts:69-74
There is no user authentication or authorization in any handler; the only check is whether the server’s GitHub CLI is authenticated. Any client able to hit these endpoints can enumerate and mutate repository secrets via the server’s GH credentials. The POST path also allows setting arbitrary secret names (not limited to known built-ins), compounding impact.

Recommendation

- Enforce authentication and role-based authorization on all handlers (e.g., require an authenticated session and admin role). - Add CSRF protection if using cookie-based auth. - Restrict allowed secret names (default-deny to builtin names or a server-side allowlist), or gate custom names behind an elevated permission flag. - Consider disabling these endpoints entirely in production builds or behind server-only admin network controls.

The agreement

Both frontier models flagged this within the same line range. AntFleet's unanimous gate fired — the finding posted on the PR. Closed in 4b9b492.

The fix

33 try {
34 execSync('gh auth status', { stdio: 'pipe' })
35 return true
36 } catch {
37 return false
38 }
39}
40
41function ghRepo(): string | null {
42 try {
43 const repo = execSync('gh repo set-default --view', { stdio: 'pipe' }).toString().trim()
44 if (repo && !repo.startsWith('no default')) return repo
45 } catch {}
46 try {
47 const repo = execSync('gh repo view --json nameWithOwner -q .nameWithOwner', { stdio: 'pipe' }).toString().trim()
48 if (repo) return repo
49 } catch {}
50 return null

Closure

Closed 1 week ago

SHA: 4b9b49251c8c9808bf147d55aa2930352af2e8c0

View closure receipt on GitHub →

Tweet thread template

tweet 1 of 8164 / 280

Two frontier models reviewed PR #3 on 6f7fc663. Both found this bug: medium performance: Synchronous child_process calls block the Node event loop on every request

tweet 2 of 8126 / 280

The vulnerable code (dashboard/app/api/secrets/route.ts:33-50): (full snippet at https://www.antfleet.dev/anatomy/6084d1ea-1)

tweet 3 of 8280 / 280

What Opus saw: "The route exports GET/POST/DELETE handlers that list, set, and delete GitHub repository secrets via the `gh` CLI. There is no authentication, authorization, CSRF check, origin check, or session validation. If this Next.js dashboard is ever exposed beyond localho…

tweet 4 of 8280 / 280

What GPT-5 saw: "There is no user authentication or authorization in any handler; the only check is whether the server’s GitHub CLI is authenticated. Any client able to hit these endpoints can enumerate and mutate repository secrets via the server’s GH credentials. The POST pat…

tweet 5 of 897 / 280

Both flagged the same line range. AntFleet's unanimous gate fired — the finding posted on the PR.

tweet 6 of 893 / 280

The fix landed in commit 4b9b492: (view diff at https://www.antfleet.dev/anatomy/6084d1ea-1)

tweet 7 of 881 / 280

AntFleet reviews every PR with two frontier models. Only unanimous findings post.

tweet 8 of 877 / 280

Full anatomy + reasoning + diffs: https://www.antfleet.dev/anatomy/6084d1ea-1

Paste into X composer one tweet at a time. X has no multi-tweet intent API.