Echo (30120) and Deep (30121) serve turns to unauthenticated callers by design, and the network boundary in front of them is unverified #925
Labels
No labels
burndown-2026-06
burndown-2026-08
autonomy
async-consult
autonomy
epic
autonomy
headless
autonomy
live-collab
coherence-core
priority
P0
priority
P1
priority
P2
priority
P3
priority
P4
qa-fixture
role/advocate
role/director
role/exec
role/frontend
role/gamedev
role/human
role/platform
role/qa
role/science
role/sysadmin
state
ambient
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
coilyco-flight-deck/infrastructure#925
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Rewritten 2026-08-25. The original framing of this issue was wrong, and the correction matters because it changes the fix from a code change to a network question. Kai asked whether there was already an SSM key for this. There is, and reading the current code rather than #866's earlier summary shows the design is deliberate.
What I got wrong
I filed this saying the token "compares correctly and then writes the result to a span attribute" with "no
401, no403" — framing it as a broken authorization control.That describes the code accurately and reads its intent backwards.
What the code actually does
Verified against
coilyco-gaming/sirens-echoat5b3ec52.There are two surfaces and the token gates one of them on purpose:
turn-handleMCPTurn, registered inmcpserver.go:66with no trust gate. Deliberately open, because every turn passes the deployment's policy, its guardfile, and its response validation.server__tool) - gated atmcpreexport.go:135, which returnstoolFailure(reexportUntrusted)on a failed check. A real early return.The server's own instructions state the reasoning:
So the token's job is to gate the path that bypasses policy.
turndoes not need it becauseturncannot bypass anything.The
trustedbool on the turn path is telemetry, and the code says so athttp.go:359: "trusted records whether the caller authenticated. Only telemetry reads". That is a labelled observation, not a failed control.Why the token is unset, and why that is consistent
With re-export off, only
turnis served over/mcp, andturnis not token-gated. So the token currently has nothing to gate, and leaving it unwired is coherent rather than an oversight.callerTrustedreturnsfalsefor an empty configured token by design: "An empty configured token trusts nobody, which is the default."This becomes a live gap the moment
MCPReexportis turned on without wiringSIRENS_ECHO_HTTP_TOKENfirst. That combination would expose raw rostered tools to anonymous callers. Worth a guard that refuses to start with re-export enabled and no token, rather than relying on whoever flips the flag to remember.What is actually still open
Not an auth bug. A network question, and it is the one #866 could never answer either.
An unauthenticated caller who can reach these ports runs turns as Sirens Echo or Sirens Deep. Through policy, so no raw tool access, but a turn still:
X-Sirens-Caller, a header the caller suppliesEstablished: both ports are open over the tailnet and serve
turnwithout authentication.Not established: whether they are reachable from the public internet.
#103found port 22 publicly reachable and closed with "this was b/c of DMZ config" and no recorded remediation. A DMZ host takes every inbound port. k3s installs its own iptables chains for NodePort traffic that commonly bypassufwINPUT filtering, so an activeufwis not an answer.On the tailnet this design is reasonable. Off it, "anyone can spend your inference and post as your bot" is a different proposition, and nothing on record says which one is true.
Done means
turnas well, which is acoilyco-gaming/sirens-echochange rather than an infrastructure one.MCPReexportenabled with an emptyHTTPTrustToken.Related
#157(public-port allowlist in the repo, audited externally),#110(treat LAN as semi-hostile),#103(the unanswered DMZ precedent), and#866, closed when Dowel's port 30122 went away.The unauthenticated turn endpoint #866 found on Dowel is still live on Echo (30120) and Deep (30121)to Echo (30120) and Deep (30121) serve turns to unauthenticated callers by design, and the network boundary in front of them is unverified