aboutsummaryrefslogtreecommitdiffstats
path: root/packages/meshbay-hub/src
diff options
context:
space:
mode:
Diffstat (limited to 'packages/meshbay-hub/src')
-rw-r--r--packages/meshbay-hub/src/meshbay_hub/static/transport.js10
1 files changed, 10 insertions, 0 deletions
diff --git a/packages/meshbay-hub/src/meshbay_hub/static/transport.js b/packages/meshbay-hub/src/meshbay_hub/static/transport.js
index 0bffeae..624c3c3 100644
--- a/packages/meshbay-hub/src/meshbay_hub/static/transport.js
+++ b/packages/meshbay-hub/src/meshbay_hub/static/transport.js
@@ -248,6 +248,10 @@ class MeshBayTransport {
// Kept for the life of the connection: a join_request is signed over it,
// which is what stops one being lifted onto another connection.
this._nonceNode = nonceNode;
+ // Announced in the challenge because joining needs it before the ack: a
+ // first-time member has no GEK, so they cannot complete the handshake that
+ // would prove this key. Unverified here; checked against the ack below.
+ this.nodePk = reply.node_pk || null;
const gid = groupId || '';
const proof = await C.handshakeProof(
@@ -281,6 +285,12 @@ class MeshBayTransport {
// fails the GEK proof — this covers the case where an attacker HAS the GEK
// (an ex-member, or a leaked key) and swaps the node underneath.
// Strict refusal: a warning users can click through is decorative.
+ // The key announced in the challenge must be the one that just proved
+ // itself. A peer that changed identity mid-handshake is not one to trust
+ // with anything, including a join we may already have signed for it.
+ if (this.nodePk && this.nodePk !== ack.node_pk) {
+ throw new Error('Node identity changed during the handshake — refusing');
+ }
_checkNodePin(nodeId, ack.node_pk);
this.nodePk = ack.node_pk;