From ed9fb22ed703db38f9b07c00d17076f90aa4cbc8 Mon Sep 17 00:00:00 2001 From: Christophe Besson Date: Thu, 13 Aug 2026 04:10:14 +0200 Subject: fix(node)!: remove unauthenticated HTTP file API and TCP transport MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Phase 11.5.A — findings C1 and C6 (see second-review.md). C1: the per-group HTTP file API bound 0.0.0.0 for every configured group, private ones included, and served two endpoints with no authentication at all: GET /index (full Mesh Group Index) and GET /file/{id} (raw plaintext file via FileResponse). Anyone able to reach the port — LAN, forwarded port, permissive IPv6 — read every private file. This bypassed the entire GEK-proof and node sovereignty layer. Deleted rather than patched: it duplicated MNP without any of its controls. C6: the TCP+TLS chunk server accepted a bare JWT with no GEK proof, leaving a second non-compliant handshake path. Deleted; QUIC remains and will be brought to parity with WebRTC by the unified handshake in 11.5.4. Transport decision recorded in transport/__init__.py: WebRTC/ICE is primary for browser and native clients (the only NAT traversal validated here — 2 ISPs, IPv4 STUN + IPv6, 4G CGNAT); QUIC is kept for LAN, port-forwarded and hub-less group:// access. punch_nat() is a direct-connection helper, not a traversal stack. Also removed server_ssl_context()/client_ssl_context() from tls_cert.py (no remaining callers) and a dead import of the former in quic_server.py. generate_self_signed_cert() stays: QUIC uses it, and the certificate hash is the intended channel-binding anchor for 11.5.6, since QUIC has no DTLS fingerprint to bind the GEK proof to. BREAKING CHANGE: node.toml keys `port` and `http_port` are gone. Regenerate config with `meshbay-node init`. Env var MESHBAY_PORT -> MESHBAY_QUIC_PORT. Tests: 198 passed (209 - 7 test_http_server - 4 test_transport). No other test changed status. Net -1300 lines. Co-Authored-By: Claude Opus 5 --- packages/meshbay-node/src/meshbay_node/ui/app.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'packages/meshbay-node/src/meshbay_node/ui') diff --git a/packages/meshbay-node/src/meshbay_node/ui/app.py b/packages/meshbay-node/src/meshbay_node/ui/app.py index b4885af..31deb66 100644 --- a/packages/meshbay-node/src/meshbay_node/ui/app.py +++ b/packages/meshbay-node/src/meshbay_node/ui/app.py @@ -48,7 +48,6 @@ def create_ui_app(state: dict) -> FastAPI: "status": state.get("status", "starting"), "hub_url": state.get("hub_url", ""), "username": state.get("username", ""), - "node_port": state.get("node_port", 0), "quic_port": state.get("quic_port", 0), "endpoint_hint": state.get("endpoint_hint"), "group_count": len(groups_ctx), @@ -154,9 +153,7 @@ def create_ui_app(state: dict) -> FastAPI: return { "hub_url": config.hub.url, "username": config.hub.username, - "node_port": config.node.port, "quic_port": config.node.quic_port, - "http_port": config.node.http_port, "ui_port": config.node.ui_port, "data_dir": str(config.data_dir), "groups": [ @@ -493,8 +490,7 @@ def _render_page(state: dict) -> str:

Node Configuration

Hub: {state.get("hub_url", "—")}

-

QUIC port: {state.get("quic_port", "—")} — - TCP port: {state.get("node_port", "—")}

+

QUIC port: {state.get("quic_port", "—")}

Node ID: {state.get("endpoint_hint") or "—"}

-- cgit v1.2.3