Relationships
#2383 serve: minting a token for an unsupported principal kind (e.g. agent:) succeeds, then every connection 500s in parsePrincipal
Opened by randybias · 9/22/2026· Shipped 9/23/2026
Problem
swamp access token mint accepts any <kind>:<id> principal string, but a connection made with such a token crashes serve's upgrade handler, which accepts only user and worker. The token is minted, stored, and authenticates — and then every request with it fails.
Measured (serve 20260922.011324.0)
A token minted for agent:swamp-resumer:
Server log, per connection attempt:
system │ Authenticated token "swamp-resumer" as "agent:swamp-resumer"
Error: Invalid principal kind "agent": expected "user" or "worker"
at parsePrincipal (src/domain/access/principal.ts:47:11)
at src/cli/commands/serve.ts:4222:31
at async mapped (ext:deno_http/00_serve.ts)Client side, the WebSocket upgrade returns HTTP 500:
$ curl -s -o /dev/null -D - --http1.1 -H 'Connection: Upgrade' -H 'Upgrade: websocket' \
-H 'Sec-WebSocket-Version: 13' -H 'Sec-WebSocket-Key: ...' \
-H "Sec-WebSocket-Protocol: bearer.<agent token>" https://<serve>/
HTTP/1.1 500 Internal Server ErrorControl, same call with a user: token on the same server: HTTP/1.1 101 Switching Protocols.
PrincipalKindSchemaisz.enum(["user", "worker"])(src/domain/access/principal.ts:22).access_token_mint.tspassesprincipalId: principalthrough (lines 146 and 225) with no validation against that enum, locally or viaaccess.token.mint.
Impact
- Mint succeeds for a principal that can never connect. Nothing fails until a client tries to use the token, and the error it gets is misleading: the CLI reports "Authentication failed — run: swamp auth server-login", because
classifyConnectionError(src/cli/remote_run.ts:756) maps any non-101 to that message. Authentication in fact succeeded; the crash is after it. - No principal kind for automation. Naming a non-human client
agent:is the natural way to keep human and machine identities apart in the audit log, and grants are commonly written per group of such principals. Today every automation must masquerade asuser:, which weakens exactly the distinction an audit log exists to make.
Ask
- Reject an unsupported principal kind at mint time, with the valid kinds named.
- Never let a bad principal produce a 500: return 401/403 with a reason on the upgrade.
- Consider an
agent(orservice) principal kind for non-human clients, first-class in grants and audit records. - Make
classifyConnectionErrorstop reporting a server-side 500 as an authentication failure.
Shipped
Click a lifecycle step above to view its details.
stack72 commented 9/23/2026, 1:47:00 PM
Thanks @randybias for reporting this! We shipped: Fix asks 1, 2 and 4 of the issue; ask 3 (an agent principal kind) is out of scope. Enforce the Principal value object at the ServerToken mint boundary (model mint plus a fast CLI check), reject a stored token whose principal does not parse at authentication time with 401 invalid-principal instead of a 500 crash in three post-auth call sites, and stop classifyConnectionError reporting 5xx and other non-auth statuses as an authentication failure.. The fix has been merged and a release is on its way. We appreciate your contribution to swamp.
Sign in to post a ripple.