GET /api/v1/debug/memory on ciris-status answers unauthenticated on the published port. The equivalent report in ciris-server 0.5.199 is deliberately loopback-only behind a runtime gate, so the two nodes disagree about whether this data is public.
Measured just now on 108.61.242.236, cirisstatus:v0.3.62:
https://lens.ciris-services-1.ai/status/api/v1/debug/memory 200 <- public HTTPS, via Caddy
http://108.61.242.236:4253/api/v1/debug/memory 200 <- direct, bypasses Caddy
Returned body, unauthenticated, from the open internet:
{"live_fraction":0.0729,
"mallinfo2":{"arena":634642432,"fordblks":588381408,"hblkhd":0,"hblks":0,
"keepcost":1199920,"ordblks":629,"uordblks":46261024},
"proc":{"RssAnon":"622756 kB","RssFile":"32092 kB","Threads":"8",
"VmPeak":"766632 kB","VmRSS":"654848 kB","VmSize":"766560 kB","VmSwap":"0 kB"}}
Compare ciris-server 0.5.199 on the same host, same data shape:
http://108.61.242.236:4243/v1/node/diagnostics/memory 403 <- loopback-only
CIRISServer#549/#550 put that route behind CIRIS_DIAGNOSTICS (off by default) and bound it to loopback, so a request arriving from the docker bridge gateway is refused. ciris-status grew its route earlier, in v0.3.61, before that decision existed — this is drift, not disagreement.
Why it is worth closing
To be clear about severity: no keys, identity material, config, peer list, tokens or PII are disclosed. It is memory counters. It does not even carry the node.{instance_id,key_id} block the server's version has. On its own the data is close to harmless.
The reason to gate it anyway is that unauthenticated it is a live feedback oracle. An attacker can watch RssAnon / VmSwap / fordblks move in response to their own traffic and steer a memory-exhaustion attempt, instead of working blind. That matters more than usual here because this node has a known allocator-churn profile (#69): it runs at ~40% of a 1.5 GB cap with ~590 MB of free lists, and the endpoint reports exactly the counters that would tell an attacker whether they are making progress.
Secondary: it leaks thread count and VmPeak, i.e. build shape.
Bridge-side mitigation already applied (partial)
Caddy now 404s the discoverable path:
handle /status/api/v1/debug/* {
respond "404 — diagnostics not exposed" 404
}
Verified: /status/api/v1/debug/* → 404, while /status/api/v1/scoring, /status/v1/identity, /api/v1/scoring and /v1/identity all still → 200.
This is deliberately only half a fix. http://<host>:4253/api/v1/debug/memory still answers, because 4253 has to stay open for remote agents' delegation claims — so it cannot be firewalled and Caddy never sees it. Closing the other half needs the image.
Suggested fix
Match what 0.5.199 does, so the two nodes have one story:
- Bind the route to loopback, refusing non-loopback peers, and/or
- Put it behind the same runtime gate (
CIRIS_DIAGNOSTICS=1), off by default.
Either is fine for the bridge — the soak reads it with docker exec / nsenter from inside the netns, which is how the server's is read today. Nothing operationally depends on it being reachable from outside; the Caddy block above has been live since this was filed with no effect on anything.
Happy to test a build the moment there is a tag. Adjacent nit while the file is open: the ciris-server-side route in the same image is /v1/node/diagnostics/memory, and v0.3.62 still serves only /api/v1/debug/memory (the new path 404s) — converging on one path would remove a second thing to remember.
GET /api/v1/debug/memoryon ciris-status answers unauthenticated on the published port. The equivalent report in ciris-server 0.5.199 is deliberately loopback-only behind a runtime gate, so the two nodes disagree about whether this data is public.Measured just now on
108.61.242.236,cirisstatus:v0.3.62:Returned body, unauthenticated, from the open internet:
{"live_fraction":0.0729, "mallinfo2":{"arena":634642432,"fordblks":588381408,"hblkhd":0,"hblks":0, "keepcost":1199920,"ordblks":629,"uordblks":46261024}, "proc":{"RssAnon":"622756 kB","RssFile":"32092 kB","Threads":"8", "VmPeak":"766632 kB","VmRSS":"654848 kB","VmSize":"766560 kB","VmSwap":"0 kB"}}Compare ciris-server 0.5.199 on the same host, same data shape:
CIRISServer#549/#550 put that route behind
CIRIS_DIAGNOSTICS(off by default) and bound it to loopback, so a request arriving from the docker bridge gateway is refused.ciris-statusgrew its route earlier, in v0.3.61, before that decision existed — this is drift, not disagreement.Why it is worth closing
To be clear about severity: no keys, identity material, config, peer list, tokens or PII are disclosed. It is memory counters. It does not even carry the
node.{instance_id,key_id}block the server's version has. On its own the data is close to harmless.The reason to gate it anyway is that unauthenticated it is a live feedback oracle. An attacker can watch
RssAnon/VmSwap/fordblksmove in response to their own traffic and steer a memory-exhaustion attempt, instead of working blind. That matters more than usual here because this node has a known allocator-churn profile (#69): it runs at ~40% of a 1.5 GB cap with ~590 MB of free lists, and the endpoint reports exactly the counters that would tell an attacker whether they are making progress.Secondary: it leaks thread count and
VmPeak, i.e. build shape.Bridge-side mitigation already applied (partial)
Caddy now 404s the discoverable path:
Verified:
/status/api/v1/debug/*→ 404, while/status/api/v1/scoring,/status/v1/identity,/api/v1/scoringand/v1/identityall still → 200.This is deliberately only half a fix.
http://<host>:4253/api/v1/debug/memorystill answers, because 4253 has to stay open for remote agents' delegation claims — so it cannot be firewalled and Caddy never sees it. Closing the other half needs the image.Suggested fix
Match what 0.5.199 does, so the two nodes have one story:
CIRIS_DIAGNOSTICS=1), off by default.Either is fine for the bridge — the soak reads it with
docker exec/nsenterfrom inside the netns, which is how the server's is read today. Nothing operationally depends on it being reachable from outside; the Caddy block above has been live since this was filed with no effect on anything.Happy to test a build the moment there is a tag. Adjacent nit while the file is open: the
ciris-server-side route in the same image is/v1/node/diagnostics/memory, and v0.3.62 still serves only/api/v1/debug/memory(the new path 404s) — converging on one path would remove a second thing to remember.