summaryrefslogtreecommitdiffstats
path: root/packages/meshbay-node/src
diff options
context:
space:
mode:
authorChristophe Besson <cbesson@gmail.com>2026-08-13 10:43:40 +0200
committerChristophe Besson <cbesson@gmail.com>2026-08-13 10:43:40 +0200
commitab4657789eaca1d88b54e5d5123a0bc71a95e6ce (patch)
tree4588be861beecf7e54d480b8fd30f54afd791fe4 /packages/meshbay-node/src
parent3ce051e134a432417fcaca4e8b5775d98f614a31 (diff)
downloadmeshbay-ab4657789eaca1d88b54e5d5123a0bc71a95e6ce.tar.gz
fix(hub): authenticate node WebSocket registration
Phase 11.5 — finding C2 (see second-review.md). /v1/nodes/ws took node_id and group_ids straight from the client's first message with no ownership check: node_id = msg.get("node_id") or decoded.get("sub", "unknown") _connected_nodes[node_id] = ws Any registered user could connect with an ordinary browser token, claim a victim node's id and overwrite its entry. Every WebRTC offer for that node was then relayed to the attacker, who answered with their own SDP — full node impersonation. The DTLS channel binding does not help, because the attacker is the endpoint rather than a relay: the browser sends its GEK proof to the attacker, who ignores it and replies handshake_ack. The attacker received the victim's encrypted keypair bundle, chat and uploads, and could serve a forged index. Registration now requires scope == "node", verifies Node.user_id against the token subject, checks the account is active, and refuses to displace a live registration instead of silently overwriting it. group_ids are intersected with the operator's actual membership: a node may narrow the set to what it hosts but cannot widen it, so it cannot advertise itself as an online source for arbitrary groups. Authorization uses a short-lived session rather than Depends(get_db): a node WebSocket lives for hours and a request-scoped dependency would pin a PostgreSQL connection for its whole lifetime. BEHAVIOUR: a node hosting a group whose hub membership was never recorded for the operator's account will stop appearing in GET /v1/groups/{id}/nodes. Adds tests/test_node_ws_auth.py (7 tests). The node WebSocket had no test coverage at all, which is why this went unnoticed. Tests: 109 node, 139 hub+common. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Diffstat (limited to 'packages/meshbay-node/src')
0 files changed, 0 insertions, 0 deletions