Skip to content

lab: gate /lab behind API_TOKEN (basic auth + x-api-token) - #1618

Merged
Evanfeenstra merged 1 commit into
mainfrom
lab-basic-auth
Aug 28, 2026
Merged

lab: gate /lab behind API_TOKEN (basic auth + x-api-token)#1618
Evanfeenstra merged 1 commit into
mainfrom
lab-basic-auth

Conversation

@Evanfeenstra

Copy link
Copy Markdown
Collaborator

What

/lab is mounted before mcp's auth middleware, so the entire lab surface — workflow launches (which spend LLM budget), run logs, workspace step editing, secrets listing — was reachable unauthenticated on any host where mcp is exposed. This was the documented known follow-up in mcp/src/lab/AGENTS.md.

This gates the whole /lab mount behind the mcp-wide API_TOKEN:

  • HTTP Basic admin:<API_TOKEN> — the browser prompts once for the UI, then attaches credentials to every request including EventSource/SSE streams (which can't carry custom headers), so the whole SPA + live run tailing works with zero UI changes
  • x-api-token header — parity with the rest of mcp for server-to-server/script callers
  • API_TOKEN unset ⇒ open (dev mode) — same posture as the existing /events route

Testing

Verified against a live instance (tsc --noEmit clean):

request result
no credentials 401 + WWW-Authenticate: Basic realm="stakgraph-lab"
wrong password / wrong user 401
-u admin:<token> on /lab/health and /lab/ UI 200
x-api-token: <token> 200
API_TOKEN unset open (dev mode)

Prod note: sphinx-swarm already injects API_TOKEN into the container env from boltwall's stakwork_secret, so this becomes enforced in prod automatically once the image updates.

🤖 Generated with Claude Code

/lab was mounted before mcp's auth middleware, so every lab route —
including run launches that spend LLM budget — was reachable
unauthenticated on a public host (the known follow-up in lab/AGENTS.md).

Gate the whole mount with the mcp-wide API_TOKEN, accepting either HTTP
Basic admin:<API_TOKEN> (the browser prompts once for the UI and then
attaches credentials to every request, including EventSource streams,
which cannot carry custom headers) or the x-api-token header (parity
with the rest of mcp for server-to-server callers). API_TOKEN unset =
dev mode = open, the same posture as the /events route.

Verified against a live instance: 401 + WWW-Authenticate with no/wrong
credentials (wrong user, wrong pass), 200 for basic and x-api-token on
/lab/health and the UI, open when API_TOKEN is unset.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@Evanfeenstra
Evanfeenstra merged commit 3bc9e25 into main Aug 28, 2026
6 checks passed
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