fix(security): resolve all 17 codex findings — auth, grants, crypto, ops
Some checks failed
CI / Lint (push) Has been cancelled
CI / Typecheck (push) Has been cancelled
CI / Broker tests (Postgres) (push) Has been cancelled
CI / Docker build (linux/amd64) (push) Has been cancelled

Critical: broker HTTP auth via cli_session bearer token on all /cli/*;
file download requires auth+membership; v2 claim gated; duplicate
claimInviteV2Core removed; grant enforcement tries member then
session pubkey; audit hash uses canonical sorted-keys JSON.

High: rate limit args fixed (burst 10, 60/min) + both buckets swept;
BROKER_ENCRYPTION_KEY fail-fast in prod; migrate uses pg_try + lock_
timeout; hello validates sessionPubkey hex; blocked DMs rejected pre-
queue; watch timers cleaned on disconnect.

Medium: inbound pushes serialized; reconnect jitter + timer guard;
hardcoded URLs through env; v2 claim path configurable.

Low: WSHelloMessage optional protocolVersion+capabilities.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Alejandro Gutiérrez
2026-04-15 19:18:25 +01:00
parent 1a7a059e75
commit 2be5e9dccb
12 changed files with 464 additions and 341 deletions

View File

@@ -417,6 +417,7 @@ export async function listPeersInMesh(
): Promise<
Array<{
pubkey: string;
memberPubkey: string;
displayName: string;
status: string;
summary: string | null;
@@ -449,8 +450,12 @@ export async function listPeersInMesh(
)
.orderBy(asc(presence.connectedAt));
// Prefer session pubkey for routing, session displayName for display.
// memberPubkey is also surfaced so callers (grants, audit, safety-number
// verify) can operate on the stable identity key rather than the
// per-connection ephemeral one.
return rows.map((r) => ({
pubkey: r.sessionPubkey || r.memberPubkey,
memberPubkey: r.memberPubkey,
displayName: r.presenceDisplayName || r.memberDisplayName,
status: r.status,
summary: r.summary,