From 3277a7e7a1eaa916acc5f35388972e68f70d6f49 Mon Sep 17 00:00:00 2001 From: NAOE Kenichi Date: Mon, 31 Aug 2026 14:36:25 +0900 Subject: [PATCH] fix(remote): connect --e2ee actually bypasses the plaintext-address check cmd_connect validated the endpoint unconditionally before --e2ee was ever consulted, so the refusal text's own claim ("connect with --e2ee so the contents are sealed before they leave this machine") did not hold. Skip the check when e2ee is requested, matching the documented and advertised behavior. Adds a control test (same address, no --e2ee, still refused) and the positive case (with --e2ee, gets past the refusal and fails at the network instead) to tests/test_remote.bats. --- scripts/remote.sh | 9 ++++++++- tests/test_remote.bats | 24 ++++++++++++++++++++++++ 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/scripts/remote.sh b/scripts/remote.sh index 4e6c2db02..b0c64bfe4 100644 --- a/scripts/remote.sh +++ b/scripts/remote.sh @@ -2190,7 +2190,14 @@ cmd_connect() { esac done : "${endpoint:?Usage: remote.sh connect --endpoint [--e2ee] }" - _remote_validate_endpoint "$endpoint" || exit 1 + # The plaintext-address rule protects message bodies that would otherwise + # cross the network unencrypted. Under --e2ee those bodies are sealed before + # they ever reach this check, so the rule has nothing left to protect here -- + # skip it, exactly as the refusal text itself promises ("connect with --e2ee + # so the contents are sealed before they leave this machine"). + if [ "$e2ee" -eq 0 ]; then + _remote_validate_endpoint "$endpoint" || exit 1 + fi endpoint="${endpoint%/}" team="${positional[0]:-}" [ -n "$team" ] || { echo "agmsg: connect requires a team: remote.sh connect --endpoint [--e2ee] " >&2; exit 1; } diff --git a/tests/test_remote.bats b/tests/test_remote.bats index e6aa3b577..5fd784036 100644 --- a/tests/test_remote.bats +++ b/tests/test_remote.bats @@ -150,6 +150,30 @@ skip_if_no_age() { [ "$status" -eq 0 ] } +@test "connect: without --e2ee, an address outside the allowlist is still refused (control)" { + # 0.0.0.0 is not in the private-range allowlist (10/8, 172.16/12, 192.168/16, + # 169.254/16, 127/8) and nothing listens on port 1 there, so this fails fast + # either way. The control for the next test: plain sync must still refuse it. + run bash "$SCRIPTS/remote.sh" connect --endpoint "http://0.0.0.0:1" testteam + [ "$status" -ne 0 ] + [[ "$output" == *"must be https://"* ]] +} + +@test "connect --e2ee: an address the plaintext check would refuse is accepted, since e2ee seals the body before it leaves" { + skip_if_no_age + # Same address as the control above. Without --e2ee this fails validation + # before ever reaching the network. The promise in the refusal text itself + # ("connect with --e2ee so the contents are sealed before they leave this + # machine") is that --e2ee is an independent way to satisfy this, not + # something layered on top of an address that already passed -- so under + # --e2ee this must get past the check and fail at the network instead, for + # an unrelated reason (nothing listens on 0.0.0.0:1), never for the address. + run bash "$SCRIPTS/remote.sh" connect --endpoint "http://0.0.0.0:1" --e2ee testteam + [ "$status" -ne 0 ] + refute grep -qF 'must be https://' <<<"$output" + grep -qF 'agmsg: connect failed' <<<"$output" +} + # --- #143: a connect that already registered must not dead-end ------------- # # Registration commits on the server in one transaction, and the binding is