Finding
handle_renderer_connection adds a ConnectedRenderer entry to the shared registry and then immediately calls connection.open_uni().await?. If open_uni returns an error, the ? operator forces an early return before the registry.remove(&session_id).await cleanup, so the entry is permanently stuck in the registry.
Evidence
crates/archon/src/render/server.rs:229:
let _audio_send = connection.open_uni().await?;
The registry.add(..) call is at lines 219–226 (before this line); registry.remove(&session_id).await is at line 234 and only runs on the straight-line path after both open_uni and read_status_loop return normally. Any error from open_uni bypasses line 234 entirely.
Why this matters
Every subsequent list_renderers call (served by DynRendererRegistry) includes a stale entry for a renderer that never finished negotiating. If open_uni failures are transient (QUIC flow-control, server back-pressure), the registry grows unboundedly and a legitimate renderer reconnecting with the same name appears twice, with no way for the API consumer to distinguish live from stale entries. Under the counter-surveillance threat model an attacker who can induce repeated open_uni failures (network shaping, resource pressure) turns this into an unbounded-memory and registry-poisoning vector, and a phantom entry can mislead the operator about which endpoints are actually live.
Desired correction
Move registry.add to after open_uni succeeds, or wrap the registration in a RAII guard / defer that calls registry.remove on every exit path after add. Alternatively, replace the ? bail with an explicit registry.remove before returning the error.
Done when: a unit test exercises the open_uni-failure path and verifies the registry contains zero entries afterward.
Finding
handle_renderer_connectionadds aConnectedRendererentry to the shared registry and then immediately callsconnection.open_uni().await?. Ifopen_unireturns an error, the?operator forces an early return before theregistry.remove(&session_id).awaitcleanup, so the entry is permanently stuck in the registry.Evidence
crates/archon/src/render/server.rs:229:The
registry.add(..)call is at lines 219–226 (before this line);registry.remove(&session_id).awaitis at line 234 and only runs on the straight-line path after bothopen_uniandread_status_loopreturn normally. Any error fromopen_unibypasses line 234 entirely.Why this matters
Every subsequent
list_rendererscall (served byDynRendererRegistry) includes a stale entry for a renderer that never finished negotiating. Ifopen_unifailures are transient (QUIC flow-control, server back-pressure), the registry grows unboundedly and a legitimate renderer reconnecting with the same name appears twice, with no way for the API consumer to distinguish live from stale entries. Under the counter-surveillance threat model an attacker who can induce repeatedopen_unifailures (network shaping, resource pressure) turns this into an unbounded-memory and registry-poisoning vector, and a phantom entry can mislead the operator about which endpoints are actually live.Desired correction
Move
registry.addto afteropen_unisucceeds, or wrap the registration in a RAII guard / defer that callsregistry.removeon every exit path after add. Alternatively, replace the?bail with an explicitregistry.removebefore returning the error.Done when: a unit test exercises the
open_uni-failure path and verifies the registry contains zero entries afterward.