Skip to content

fix: bearer-token auth gate on dashboard actions and APIs (Bug #3)#55

Open
avrabe wants to merge 1 commit intomainfrom
fix/dashboard-auth
Open

fix: bearer-token auth gate on dashboard actions and APIs (Bug #3)#55
avrabe wants to merge 1 commit intomainfrom
fix/dashboard-auth

Conversation

@avrabe
Copy link
Copy Markdown
Contributor

@avrabe avrabe commented May 2, 2026

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

  • All `POST /dashboard/actions/*` (sync, review, analyze-org, refresh, check-config, check-dependabot, fix-dependabot-labels)
  • All `GET /api/*` (org/health, org/repos, reviews/insights)

What's still public

  • `GET /dashboard` and partials — read-only HTML rendering of cached data. If even that's too exposed, put a reverse proxy in front.

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

  • 10 new unit tests cover unset/wrong/missing/valid paths
  • Full suite: 844 pass (was 834)
  • `npm run lint` clean
  • After deploy: confirm dashboard frontend includes the bearer header (will need a follow-up patch to the dashboard JS)

Risk

Medium — deliberate behaviour change. Operators must set `DASHBOARD_TOKEN` and update any curl/frontend callers.

🤖 Generated with Claude Code

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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant