fix(dashboard): pass -R repo to gh commands so multi-remote setups work (replay of 416244f)#25
fix(dashboard): pass -R repo to gh commands so multi-remote setups work (replay of 416244f)#25antfleet-ops wants to merge 2 commits into
Conversation
…rk (aeonfun#169) * fix(dashboard): pass -R repo to gh commands so multi-remote setups work When a fork adds upstream as a second remote (recommended by README's two-repo strategy), `gh secret list/set/delete` errors with "multiple remotes detected" because it can't pick a default repo. The auth and secrets API routes invoked gh without -R, so authentication and secret management both broke as soon as upstream was added. Both routes now resolve the active repo via `gh repo set-default --view` (falls back to `gh repo view`) and pass it explicitly via -R. * refactor(dashboard): unify gh repo helper on execFileSync + array form Both routes share the same ghRepo/ghArgsRepo pattern now — strip the shell-string ghRepoFlag() from auth and switch its three gh invocations to execFileSync. Also drop the unused listSecrets shell branch in secrets. Behaviour-identical; just kills the inconsistency between the two routes. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: traewang <traewang@gmail.com> Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Initial review missed in 30-PR burst on 2026-05-18 (rate limit hit on first batch). Re-firing pull_request.synchronize webhook.
AntFleet · 3 findingsBoth reviewers flagged the items below on the changed files. AntFleet posts only what two independent frontier models agree on. Security · Critical — Missing authentication/authorization on secret-management endpoints
Fix: Require authentication for all mutating routes (and arguably GET, which leaks which secrets exist). At minimum, bind the dev server to 127.0.0.1, verify a same-origin/Host header, require a CSRF token, and gate behind a session cookie or local-only token. Also reject requests if NODE_ENV === 'produ… Bug · High — Token reassembly from
Fix: Strip ANSI escapes first (e.g. Performance · Low — Synchronous child_process calls block the Node event loop on every request
Fix: Use the async — Review |
AntFleet · finding
|
AntFleet · finding
|
AntFleet · finding
|
…#188) Closes the 3 critical findings AntFleet flagged in #184: - C1 · /api/skills/[name]/run — unauthenticated POST triggers `gh workflow run aeon.yml` - C2 · /api/secrets GET — unauthenticated read of secret name set - C3 · /api/secrets POST/DELETE — unauthenticated set / delete of any GitHub secret on the repo Same root cause: every dashboard `/api/*` route assumes "the OS user owns localhost". Two paths break that assumption — a malicious page that DNS-rebinds `attacker.example` to `127.0.0.1` and POSTs to the loopback socket, and a browser cross-origin no-cors POST that bypasses preflight. Both reach the routes today; both write GitHub secrets or trigger Actions on the operator's behalf. Add a single Next middleware (`dashboard/middleware.ts`) that gates every `/api/*` request through `dashboard/lib/security/api-gate.ts`: - Host header must resolve to a loopback variant (127.0.0.1, localhost, ::1, [::1], 0.0.0.0) — defeats DNS rebinding. - On non-GET/HEAD/OPTIONS, Origin (with Referer fallback) must also resolve to a loopback variant — defeats no-cors CSRF. Two operator hatches preserve LAN/Tailscale/reverse-proxy setups: - `AEON_DASHBOARD_ALLOWED_HOSTS=aeon.local,box.tail-xxx.ts.net` — extend the allowlist (comma-separated; case + port insensitive). - `AEON_DASHBOARD_ALLOW_ANY_HOST=1` — bypass entirely, intended for a trusted proxy that owns Host policy. Loudly insecure; not the default. Pure stdlib in `api-gate.ts` (Set + URL parsing); no new deps. Smoke tests in `api-gate.test.ts` cover stripPort, the env-driven wrapper, the loopback-accept happy path, both rejection paths, and both env hatches — run with `node --test dashboard/lib/security/api-gate.test.ts`. README gains a `### Dashboard access` block under Quick start documenting the env vars + the two threat-model paths the gate defeats. Refs: AntFleet receipts - AntFleet#1 (comment) - AntFleet#3 (comment) - AntFleet#25 (comment)
…-token reassembly (#194) The prior loop pushed line.trim() unconditionally for the first line, which included any trailing terminal prose, spaces, or ANSI sequences that appeared after the token text on that line. Those bytes were then concatenated into the stored CLAUDE_CODE_OAUTH_TOKEN, writing a malformed credential to the GitHub secret. Fix: apply the same /^[A-Za-z0-9_\-]+/ extraction to every line (including the first). The regex anchors at the start of the trimmed line and stops at the first non-token character, so only the token alphabet is ever appended. Add a post-loop guard that returns a 400 if the assembled value does not start with "sk-ant-oat", making extraction failures explicit instead of silently storing garbage. Ref: AntFleet bench receipt AntFleet#25 (comment) Co-authored-by: a11 <augstar@gmail.com> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Benchmark replay
This PR replays upstream commit
416244f("fix(dashboard): pass -R repo to gh commands so multi-remote setups work") as a diff against its parent.Not for merge. Purpose: AntFleet two-model PR review evaluation.
See BENCHMARK.md for the policy.