diff options
| author | Christophe Besson <cbesson@gmail.com> | 2026-09-02 11:54:22 +0200 |
|---|---|---|
| committer | Christophe Besson <cbesson@gmail.com> | 2026-09-02 11:54:22 +0200 |
| commit | 2d8c6bc449e343a80569e45d4ceae0423616cedd (patch) | |
| tree | 09a1ee29c2a39db6189ba80315cfa0a1c463bcf3 /docs/captcha.md | |
| parent | bee5901f7a04d17c40e2c8d077437f10e59c8d81 (diff) | |
| download | meshbay-2d8c6bc449e343a80569e45d4ceae0423616cedd.tar.gz | |
fix(hub): a desktop solve reports no hostname at all, not "meshbay"
Registering from the native client failed with `captcha_failed` while the
checkbox was green — a worse symptom than the one being fixed, because the
widget now looked fine and only the hub's own log said otherwise:
captcha solved on an unexpected host ''; allowed: ['localhost', 'meshbay', 'meshbay.org']
The previous commit assumed Google would report the host component of the
origin, so `app://meshbay` would come back as `meshbay` and could sit in
`allowed_hosts`. It does not. A solve Google cannot attribute to a domain
reports an **empty** hostname, and no allowlist entry can match that. An empty
entry is not the answer either: a blank in a TOML list is a typo far more
often than an intention, and `load_config` drops blanks for that reason —
`captcha.allow_unattributed_host` is a named flag instead, so the trade is
stated where it is made.
What it admits, plainly: every non-web client, not only ours. A file:// page
or somebody else's Electron application look identical from here. That is the
same bar the client's own origin would have been — main.js already records
that `app://meshbay` is not a credential — and it is a bar: the captcha still
has to be solved, per token, in something that can render it. What is given up
is the origin restriction for non-web clients, not the captcha. Off by
default, and a hub without the desktop client should leave it off.
The refusal now names which of the two it is, since they need different
answers: an unexpected host names the host, an unattributed one says to set
the flag.
docs/captcha.md §6 said `meshbay` was the value and told operators to add it;
it now records what was measured and why the guess was wrong. The packaged
example config carries the flag with the same warning.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014UtzVrzM7e2tG9fSpkR9ML
Diffstat (limited to 'docs/captcha.md')
| -rw-r--r-- | docs/captcha.md | 59 |
1 files changed, 41 insertions, 18 deletions
diff --git a/docs/captcha.md b/docs/captcha.md index 84dadc4..4054e9f 100644 --- a/docs/captcha.md +++ b/docs/captcha.md @@ -415,7 +415,9 @@ solutions" on the key, and check the origin on the hub, where it belongs: [captcha] site_key = "6Le..." secret_key = "6Le..." -allowed_hosts = ["meshbay.org", "localhost", "meshbay"] +allowed_hosts = ["meshbay.org", "localhost"] +# Only with the desktop client. See below — this is the loose one. +allow_unattributed_host = true ``` `verify_captcha` then refuses a solve whose reported hostname is not in that @@ -430,20 +432,37 @@ setting keeps the behaviour it has, with reCAPTCHA doing the origin check itself. **The two settings go together**: turning the console check off without setting `allowed_hosts` leaves no origin check anywhere. -**The last entry is the desktop client's own, and it is the weak one.** Any -Electron application can claim the same scheme and host — `main.js` already -records that `app://meshbay` is not a credential, which is why the hub's API is -reachable from no web origin at all and every call leaves from the main -process. So `meshbay` in that list is spoofable by someone who builds an -equivalent application. What it still costs them is a per-token captcha solve -inside a real Chromium, rather than a token farmed from any web page. That is -the trade, stated plainly; a hub that does not ship the desktop client should -leave the entry out. +### The hostname a desktop solve reports is empty, not `meshbay` -**Confirming the hostname.** `meshbay` is the host component of -`app://meshbay`. If a solve is refused, `captcha.py` logs it at WARNING with -the hostname spelled out and the allowed list beside it, which is how to read -the value a given client actually reports rather than guess at it. +Built first as an allowlist entry, on the assumption that Google would report +the host component of the origin. It does not, and registration from the +client failed with `captcha_failed` while the checkbox was green — a worse +symptom than the one being fixed, because the widget now looked fine. The log +line said it outright: + +``` +captcha solved on an unexpected host ''; allowed: ['localhost', 'meshbay', 'meshbay.org'] +``` + +A solve Google cannot attribute to a domain reports an **empty** hostname. No +allowlist entry can match that, and an empty entry is not the answer either: +a blank in a TOML list is a typo far more often than an intention, and +`load_config` drops blanks for that reason. `allow_unattributed_host` is a +named flag instead, so the trade is stated where it is made. + +**What it admits, plainly.** Every non-web client, not only ours — a `file://` +page or somebody else's Electron application report the same nothing. That is +the same bar the client's own origin would have been (`main.js` already records +that `app://meshbay` is not a credential; any application can claim it), and it +*is* a bar: the captcha still has to be solved, per token, in something that +can render it. What is given up is the origin restriction for non-web clients, +not the captcha. A hub that does not ship the desktop client should leave the +flag off. + +**Reading the value yourself.** Any refusal is logged at WARNING, with the +hostname spelled out and the allowed list beside it when there is one. That is +how the empty hostname was found, and it is the way to check what a given +client actually reports rather than guess — which is what went wrong here. --- @@ -508,7 +527,9 @@ from Google — no npm package. site_key = "6Le..." secret_key = "6Le..." # Required whenever the console's origin check is off, and only then. - allowed_hosts = ["meshbay.org", "localhost", "meshbay"] + allowed_hosts = ["meshbay.org", "localhost"] + # Only with the desktop client — §6 says what it gives up. + allow_unattributed_host = true ``` 3. Deploy the new hub code (`deploy-hub.sh` — runs `alembic upgrade head` + restart; no migration needed for this change). @@ -517,6 +538,8 @@ from Google — no npm package. solving the captcha. 5. Verify reset: open `https://meshbay.org/#/reset`, confirm the checkbox appears. Request a reset code, confirm email arrives only after solving it. -6. Verify the desktop client: register from it and confirm the widget solves - rather than showing "Invalid domain for site key". A refusal logged as - `captcha solved on an unexpected host` names the hostname to add. +6. Verify the desktop client by actually registering from it. Two distinct + failures, and the first hides the second: "Invalid domain for site key" + inside the widget means the console's origin check is still on, while a + green checkbox followed by `captcha_failed` means the hub refused it — the + WARNING in the journal says which host, or that there was none. |