diff options
Diffstat (limited to 'second-review.md')
| -rw-r--r-- | second-review.md | 28 |
1 files changed, 27 insertions, 1 deletions
diff --git a/second-review.md b/second-review.md index a2218ad..01ee2af 100644 --- a/second-review.md +++ b/second-review.md @@ -394,6 +394,16 @@ Consider a localhost token in the URL to blunt DNS-rebinding against the unauthe ### H3 — An active hub breaks confidentiality through key substitution (T2 is not a residual risk) +> **CLOSED 2026-08-14.** Not by the fix proposed below. The invite path no longer reads +> the directory at all: the node holds the GEK and wraps it for a key the recipient +> proves possession of over the authenticated channel, and identities are bound to +> accounts by one-time codes the hub never sees. Safety numbers would have made the +> substitution *detectable by a human who checks*; removing the lookup makes it +> impossible. See `docs/invite-pairing-v1.md` and draft-v5 §5.5. +> +> `gek-init` had the same flaw with the node as the victim — it fetched every member's +> public key from the hub and wrapped for the answer. That is gone too. + **Location:** `app.js:1389-1415`, `users.py:340-358`, `users.py:310-337` The invite flow is: fetch `pk_x25519` for the invitee **from the hub**, wrap the GEK for it, @@ -535,7 +545,11 @@ minimum password, and the calibration command prints instructions to hand-edit a `meshbay_common` rather than writing a per-node parameter — so the keystore parameters cannot actually be tuned per hardware as §4.2.1 promises. -**M3 — Node operator cannot delete files in the default configuration.** `_resolve_admin_pk` +**M3 — Node operator cannot delete files in the default configuration.** *(CLOSED +2026-08-14 — the auto-pin is deleted; authority comes from the node's roster, established +locally by `meshbay-node operator pair`. Asking the hub for the operator's key, the +obvious-looking fix, would have let the hub install itself as node administrator.)* +`_resolve_admin_pk` (`daemon.py:451-465`) auto-pins the **node keystore's** Ed25519 key, while the browser signs challenges with the **user identity** key from the keypair bundle (`app.js:983`). These are different keys, so verification fails unless the operator manually sets `admin_pk_ed25519` to @@ -543,6 +557,13 @@ their browser key. Fails closed, so it is a correctness problem rather than a ho sovereignty feature is effectively inert as shipped, and the mismatch will invite the wrong fix (relaxing the check) unless it is documented. +> **C4 — REDUCED 2026-08-14, not closed.** The bundle's KDF moved from PBKDF2-SHA512 +> 600k to Argon2id 128 MB/t=3 in the browser (vendored WebAssembly), so an operator +> attacking one offline no longer enjoys the GPU economics of a compute-only KDF. The +> pre-proof window is unchanged and still bounded. What remains: bundles are still stored +> on every node their owner joins, and a weak passphrase still loses — draft-v5 §7.1 gives +> the measured numbers. It closes at 13.3. + **M4 — Response-to-request matching by arrival order.** `transport.js:390-422` resolves the **oldest** pending promise with whatever message arrives, ignoring type. With the 8-deep pipelined download window, a node that reorders responses (or an `error` message arriving @@ -619,6 +640,11 @@ client path. ## 7. Does the system do what it claims? +> This table is the verdict **on the code as it stood on 2026-08-13**, and is left as the +> record of what the review found. It is not the current state: Phase 11.5 closed C1–C6 +> and H1–H7 except H3, and the invite redesign closed H3 and M3 on 2026-08-14. For what +> holds today, and against which adversary, read draft-v5 §2 — never this table. + | Claim (draft-v4) | Verdict | Why | |---|---|---| | Data never transits a central server | **Yes** | WebRTC DataChannel is genuinely P2P; hub relays SDP only. Well executed. | |