Repository navigation
Conversation
The auth middleware exempted a long list of GET endpoints from
requiring the api_key — /api/agents, /api/sessions, /api/config,
/api/config/schema, /api/channels, /api/hands(/active), /api/skills,
/api/integrations(/available|/health), /api/workflows, /api/approvals,
/api/budget(/agents), /api/providers, /api/models(/aliases),
/api/network/status, /api/a2a/agents, /api/cron/*, /api/uploads/*,
and the SSE /api/logs/stream — with the stated rationale "so the SPA
can render before the user enters their API key".
In practice this means any unauthenticated visitor who reaches a
deployed instance can browse real operational data: session lists,
the full config (via /api/config and /api/config/schema — which also
leaks provider/channel field names and structure), installed
integrations, channel and hand status, agent details, cron jobs, and
uploaded files. None of that requires proving you hold the api_key;
only mutating requests (POST/PUT/DELETE) were actually gated.
This trims the exemption list to what's needed for the page shell to
load and for the API-key entry flow itself to work: static assets,
health/version checks, the A2A discovery card, OAuth callback path,
and /api/auth/login|logout|check (the mechanism that validates a
freshly-typed key, which necessarily can't require the key first).
Every other endpoint now requires the api_key as intended.
## Test plan
- Verified against a real deployment: /api/sessions, /api/config,
/api/channels all return 401 without a key, 200 with the correct
key.
- The dashboard's own index page ("/") still loads without a key, as
designed — only the data calls behind the "Unlock Dashboard" screen
now correctly require it.
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
The auth middleware exempted a long list of GET endpoints from requiring the
api_key—/api/agents,/api/sessions,/api/config,/api/config/schema,/api/channels,/api/hands(/active),/api/skills,/api/integrations(/available|/health),/api/workflows,/api/approvals,/api/budget(/agents),/api/providers,/api/models(/aliases),/api/network/status,/api/a2a/agents,/api/cron/*,/api/uploads/*, and the SSE/api/logs/stream— with the stated rationale "so the SPA can render before the user enters their API key".In practice this means any unauthenticated visitor who reaches a deployed instance can browse real operational data: session lists, the full config (via
/api/configand/api/config/schema, which also leaks provider/channel field names and structure), installed integrations, channel and hand status, agent details, cron jobs, and uploaded files. Only mutating requests (POST/PUT/DELETE) were actually gated — reads were wide open.I found this by deploying an instance publicly behind a reverse proxy: opening the dashboard URL and dismissing the "API Key Required" modal (without entering anything) still showed real data underneath it.
Fix
Trims the exemption list to what's actually needed for the page shell to load and for the key-entry flow itself to work:
/,/logo.png,/favicon.ico)/api/health,/api/health/detail,/api/status,/api/version)/.well-known/agent.json,/a2a/*on GET) — meant to be public per the A2A spec/api/auth/login,/api/auth/logout,/api/auth/check(GET) — the auth mechanism itself, which necessarily can't require the key first to validate a freshly-typed oneEvery other endpoint now requires the
api_keyas the "Unlock Dashboard" UI already implies it does.Test plan
/api/sessions,/api/config,/api/channelsall return401without a key,200with the correct key./) still loads without a key, as designed — only the data calls behind the "Unlock Dashboard" screen now correctly require it.🤖 Generated with Claude Code