Verified medium protocol-layer hardening items from the audit.
- No schema validation of inbound messages —
server.ts:324 casts raw JSON.parse output as ClientMessage; protocol/types.ts has no zod. Missing fields throw deep in handlers (caught into response.error, but no validation layer). Robustness/DoS, not auth bypass (auth + scope checks run first). Fix: zod discriminated-union for ClientMessage; safeParse at server.ts:324, return invalid_request on failure.
- Unknown
msg.type hangs the client's request — session-manager.ts:186-237 switch has no default, so handle() returns undefined → ws.send(undefined) (server.ts:337) sends nothing → the client's pending promise for that id never resolves until its 30s timeout. Fix: default: arm returning {type:"response.error", requestId: msg.id ?? "", code:"invalid_request"} (subsumed by the zod fix above).
- No WS payload cap / no broadcast backpressure —
server.ts:269 (no maxPayloadLength), session.ts:2454 #broadcastRaw ignores ws.send's backpressure return (Bun returns -1, never throws) so the catch-and-prune is effectively dead; a slow/stalled client accrues unbounded server-side buffer and is never pruned. Fix: set maxPayloadLength + a backpressure policy; in #broadcastRaw inspect ws.bufferedAmount/send result and detach past a threshold.
(Telegram frontend low-sev polish — stale-client pruning on permanent send failure telegram/index.ts:934, and lengthening the 8-hex approval-prefix key telegram/index.ts:762 — tracked here too; negligible-probability but no upside.)
Verified medium protocol-layer hardening items from the audit.
server.ts:324casts rawJSON.parseoutputas ClientMessage;protocol/types.tshas no zod. Missing fields throw deep in handlers (caught intoresponse.error, but no validation layer). Robustness/DoS, not auth bypass (auth + scope checks run first). Fix: zod discriminated-union forClientMessage;safeParseatserver.ts:324, returninvalid_requeston failure.msg.typehangs the client's request —session-manager.ts:186-237switch has nodefault, sohandle()returnsundefined→ws.send(undefined)(server.ts:337) sends nothing → the client's pending promise for thatidnever resolves until its 30s timeout. Fix:default:arm returning{type:"response.error", requestId: msg.id ?? "", code:"invalid_request"}(subsumed by the zod fix above).server.ts:269(nomaxPayloadLength),session.ts:2454#broadcastRawignoresws.send's backpressure return (Bun returns-1, never throws) so the catch-and-prune is effectively dead; a slow/stalled client accrues unbounded server-side buffer and is never pruned. Fix: setmaxPayloadLength+ a backpressure policy; in#broadcastRawinspectws.bufferedAmount/sendresult and detach past a threshold.(Telegram frontend low-sev polish — stale-client pruning on permanent send failure
telegram/index.ts:934, and lengthening the 8-hex approval-prefix keytelegram/index.ts:762— tracked here too; negligible-probability but no upside.)