aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristophe Besson <cbesson@gmail.com>2026-08-13 14:44:34 +0200
committerChristophe Besson <cbesson@gmail.com>2026-08-13 14:44:34 +0200
commitd7576a578d1cdf0a342660385083982dfca033a6 (patch)
tree867bf064d925b2d8a99ba8cb9687ad7d83be9d7f
parent38ad6c54f8c8a9180f0f7522dead38e57760d55e (diff)
downloadmeshbay-d7576a578d1cdf0a342660385083982dfca033a6.tar.gz
docs: draft-v5 — mark C6, M8 and 11.5.8 closed
Phase 11.5 is complete. All six critical and all seven high findings from the second review are now closed, bounded, or deferred by explicit decision. Updated in place rather than appended, so the document does not carry stale "open" markers next to shipped work: - §9 split into "closed since this document was drafted" and "still open", with C6, 11.5.6, 11.5.8 and M8 moved across and the closing mechanism recorded for each - §2 claim table: node impersonation is no longer pending - §3.1 QUIC now shows the unified handshake enforced - §4.2 records what the QUIC binding actually turned out to be, including the finding that a resumed TLS session carries no certificate, so the anchor travels with the session ticket - §4.4 states that the client pins pk_node and refuses a change Added a scope note: with C6 closed, pinning is defence in depth, not the primary control. A substituted node already fails the GEK proof; pinning covers the case where an attacker holds the group key and swaps the node underneath. H3 remains the last unfixed finding, and the document still says so. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
-rw-r--r--docs/meshbay-draft-v5.md41
1 files changed, 29 insertions, 12 deletions
diff --git a/docs/meshbay-draft-v5.md b/docs/meshbay-draft-v5.md
index 0d64b0c..9e1ddb3 100644
--- a/docs/meshbay-draft-v5.md
+++ b/docs/meshbay-draft-v5.md
@@ -1,6 +1,6 @@
# MeshBay — Architecture Draft v5
-> Status: Phase 11.5 (security remediation) largely complete — see `devel-phases-next.md`.
+> Status: **Phase 11.5 (security remediation) complete.** See `devel-phases-next.md`.
> Supersedes `meshbay-draft-v4.md`. Sections not restated here are unchanged from v4.
>
> v5 exists because the second security review (`second-review.md`, 2026-08-13) found
@@ -58,7 +58,7 @@ This replaces the informal assurances scattered through v4 §4.2.x and §13.
| Chat content is unreadable | ✅ | ❌ H3 | ❌ plaintext at rest until Phase 15 | ❌ | ✅ |
| File index is unreadable | ✅ | ❌ H3 | ❌ | ❌ | ✅ |
| Content cannot be modified | ✅ | ✅ | ❌ by design | ✅ | ✅ |
-| Node cannot be impersonated | ✅ | ⚠️ pending 11.5.8 pinning | — | ✅ | ✅ |
+| Node cannot be impersonated | ✅ | ✅ | — | ✅ | ✅ |
| Client code integrity | ❌ **T3, accepted** | ❌ T3 | ✅ | ✅ | ✅ |
| Node content authority | ✅ | ✅ | ✅ sovereign | ✅ | ✅ |
@@ -89,7 +89,7 @@ means "end-to-end" here describes *client ↔ node*, never *client ↔ client*.
| Listener | Role | Status |
|---|---|---|
| **WebRTC DataChannel** (aiortc) | Primary, browser **and** native clients | Unified handshake enforced |
-| **QUIC** (aioquic) | LAN, port-forwarded, hub-less `group://` | Authorization shared; **GEK proof pending** |
+| **QUIC** (aioquic) | LAN, port-forwarded, hub-less `group://` | Unified handshake enforced |
| ~~TCP + TLS 1.3~~ | — | **Removed** (C6) |
| ~~HTTP file API~~ | — | **Removed** (C1) |
@@ -147,7 +147,7 @@ a missing fingerprint silently degraded it to nonce-only, dropping MitM detectio
| Transport | Anchor |
|---|---|
| WebRTC | both DTLS certificate fingerprints |
-| QUIC | SHA-256 of the server certificate — **unproven**, see 11.5.6. An RFC 5705 exporter would be stronger; aioquic does not currently expose one |
+| QUIC | SHA-256 of the server certificate. aioquic exposes no RFC 5705 exporter; the client's access to the peer certificate is a guarded private attribute, and on a **resumed** session — which carries no certificate — the anchor travels with the session ticket |
### 4.3 Authorization rules
@@ -163,8 +163,8 @@ with its long-term key. Previously the client received an unverifiable `node_pk`
trusted `is_node_admin` from whoever answered — so a peer that had hijacked signaling
could serve a forged index, forged chat history and forged permissions.
-**Still open (11.5.8):** the client verifies the signature but does not yet *pin* the
-key, so a substituted node is caught only by its lack of the GEK.
+The client also **pins** `pk_node` per node on first use (11.5.8) and refuses a changed
+key outright, with a deliberate reset path in Settings for a legitimate rotation.
---
@@ -308,18 +308,35 @@ format.
## 9. Open items
+**Phase 11.5 is complete.** All six critical and all seven high findings from
+`second-review.md` are closed, bounded, or deferred by explicit decision.
+
+### Closed since this document was drafted
+
+| # | Item | Closed by |
+|---|---|---|
+| **C6** | GEK proof on the QUIC path | QUIC now runs the same challenge/response as WebRTC — client nonce, role-bound transcript, GEK proof, and the node proving itself with a GEK proof plus an Ed25519 signature |
+| 11.5.6 | QUIC channel-binding anchor | Certificate hash. Server reads its own certificate from disk; the client's access to the peer certificate is guarded and fails loudly if aioquic moves it. **A resumed TLS session carries no certificate**, so the anchor travels with the session ticket — sound, because the ticket is derived from the handshake where the certificate was presented |
+| 11.5.8 | `pk_node` TOFU pinning | Pinned per `node_id` on first handshake; a change is **refused**, with a deliberate reset in Settings |
+| **M8** | Node announce proof-of-possession | Announcer signs `meshbay:node_announce:{user_id}:{pk_node}:{timestamp}`; re-announcing updates in place |
+
+### Still open
+
| # | Item | Status |
|---|---|---|
-| **C6** | GEK proof on the QUIC path | **Open** — authorization shared, proof pending. A forged token still injects chat over QUIC |
-| 11.5.6 | QUIC channel-binding anchor | Unproven — certificate hash vs RFC 5705 exporter |
-| 11.5.8 | `pk_node` TOFU pinning | Open |
-| 11.5.10 | Node announce proof-of-possession | Open |
-| **H3** | Hub key substitution | **Open** — fixed by Phase 12.1 safety numbers |
-| C4 | Remote keypair bundles | Bounded; closes in Phase 13.3 |
+| **H3** | Hub key substitution | **Open** — the last unfixed finding. The hub is the public-key directory, so it can be handed the GEK at invite time. Fixed by Phase 12.1 safety numbers |
+| C4 | Remote keypair bundles | Bounded (4 pre-proof fetches, audited); closes in Phase 13.3 when the native client stops storing them remotely |
| — | Chat encryption (Sender Keys) | Phase 15. Distribution must be **pairwise to identity keys**, never GEK-derived |
| — | Chat attachments | Plaintext on the node; decide in Phase 15.7 |
| **T3** | Hub serves the SPA | **Accepted permanently** (D1) |
+### Scope note on pinning
+
+With C6 closed, `pk_node` pinning is defence in depth rather than the primary control: a
+substituted node already fails the GEK proof. Pinning covers the case where an attacker
+*holds* the group key — an ex-member, or a leaked GEK — and swaps the node underneath,
+which the proof alone cannot distinguish from the genuine node.
+
### Sender Keys — scope correction
Sender Keys protects chat from someone holding the node's disk who is **not** a group