fix: bearer-token auth gate on dashboard actions and APIs (Bug #3)#55
Open
fix: bearer-token auth gate on dashboard actions and APIs (Bug #3)#55
Conversation
Why: Security auditor flagged that POST /dashboard/actions/* and
GET /api/* were reachable without auth. Anyone able to hit the bot's
HTTP port could trigger org-wide reconfiguration, force AI reviews
against arbitrary PRs, exfiltrate repo lists, or generate analysis
reports. The bot binds to 0.0.0.0 by default in PM2 — the only thing
between the public internet and these endpoints was the operator's
firewall.
What:
- New `DASHBOARD_TOKEN` env var. When set, /dashboard/actions/* and
/api/* require `Authorization: Bearer <token>`.
- When DASHBOARD_TOKEN is unset, those routes return 503 with
`{"error":"auth_unconfigured"}`. Fail-closed beats fail-open for
an admin surface — the operator gets a clear signal to set the
token, and a forgotten config never leaves the routes wide open.
- HTML pages (/dashboard, /dashboard/htmx.js, partials) stay public.
They render aggregated GitHub data via the same cache that
webhooks populate; the operator should put a reverse proxy in
front if even that's too sensitive.
- crypto.timingSafeEqual for the compare so the token's prefix
isn't leaked via timing.
Test plan:
- 10 new unit tests in __tests__/unit/dashboard-auth.test.js cover:
unset → 503 on protected routes, public HTML still through
set: missing/wrong/Basic → 401, valid Bearer → through,
all four POST action routes consistently rejected
- Full suite: 844 pass (was 834), lint clean
Risk: medium. This is a deliberate behaviour change. Operators with
an existing dashboard setup must:
1. Generate a random token (e.g. `openssl rand -hex 32`).
2. Set DASHBOARD_TOKEN in PM2 / .env.
3. Update any frontend / curl scripts to send the header.
A follow-up doc note in CLAUDE.md / GITHUB_APP_SETUP.md should call
this out.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Why
The bot binds 0.0.0.0 by default. Anyone able to reach the port could trigger org-wide reconfig (`POST /dashboard/actions/sync`), exfiltrate repo lists (`GET /api/org/repos`), or queue AI reviews against arbitrary PRs.
What's gated
What's still public
Operator setup
```bash
generate a token
openssl rand -hex 32 > /etc/temper.env # or store in PM2 ecosystem config
in env:
DASHBOARD_TOKEN=…
```
Test plan
Risk
Medium — deliberate behaviour change. Operators must set `DASHBOARD_TOKEN` and update any curl/frontend callers.
🤖 Generated with Claude Code