diff options
| author | Christophe Besson <cbesson@gmail.com> | 2026-10-14 13:34:47 +0200 |
|---|---|---|
| committer | Christophe Besson <cbesson@gmail.com> | 2026-10-14 13:34:47 +0200 |
| commit | 51705056a578d2649a989bf14a056fbcfae58a6b (patch) | |
| tree | dfd078aba518427387fca29b9d43c3723b030008 /packages/meshbay-hub/tests/test_desktop_shell.py | |
| parent | daec4bc6a2a9f9e038e5269586b06018ff327a27 (diff) | |
| download | meshbay-51705056a578d2649a989bf14a056fbcfae58a6b.tar.gz | |
feat(hub): replace reCAPTCHA with a self-hosted proof of work
Sign-up and passphrase reset sent every visitor's address and browser
details to Google, which needed a consent the sign-up form could not ask
for freely. The hub now issues its own challenge (ALTCHA's scheme, signed
with a key derived from the hub's private key, single-use, 30 minutes)
and the page solves it with SubtleCrypto while the form is filled in.
- GET /v1/users/captcha issues a challenge; 404 captcha_disabled when off.
- [captcha] enabled / max_number replace site_key / secret_key, which are
now ignored with a warning; MESHBAY_CAPTCHA_ENABLED replaces the old
variables.
- No Google origin left in the CSP of the hub, the desktop shell or the
Android shell; captcha_site_key leaves /v1/hub/info.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Diffstat (limited to 'packages/meshbay-hub/tests/test_desktop_shell.py')
| -rw-r--r-- | packages/meshbay-hub/tests/test_desktop_shell.py | 34 |
1 files changed, 11 insertions, 23 deletions
diff --git a/packages/meshbay-hub/tests/test_desktop_shell.py b/packages/meshbay-hub/tests/test_desktop_shell.py index c2ea4ca..7a26dfb 100644 --- a/packages/meshbay-hub/tests/test_desktop_shell.py +++ b/packages/meshbay-hub/tests/test_desktop_shell.py @@ -197,14 +197,9 @@ def _policy() -> str: """ import re source = _main() - # The array mixes plain strings and one `${RECAPTCHA_SRC}` template literal; - # resolve the constant so every directive reads as plain text. - rec = re.search(r"const RECAPTCHA_SRC = '([^']*)'", source) match = re.search(r"const CSP = \[(.*?)\]\.join", source, re.S) assert match, "no CSP constant in the main process" body = match.group(1) - if rec: - body = body.replace("${RECAPTCHA_SRC}", rec.group(1)) # Skip the `//` comments inside the array. Reading one as a directive is # the mistake this file already records against the packaged unit test, # which matched the comment explaining why `User=` was absent: parse @@ -226,24 +221,22 @@ def _directive(name: str) -> str: def test_the_hub_is_reachable_but_never_executable(): """ - The page connects to its own files and to reCAPTCHA, nothing else: every + The page connects to its own files, nothing else: every hub call leaves from the main process (a page on `app://` is refused by CORS anyway), and the node arrives over WebRTC, which connect-src does not govern. A bare `https:` there let injected script post anything anywhere. script-src never names the hub: nothing it returns is ever executed. The - only script sources are 'self', the wasm eval token, and the two reCAPTCHA - hosts (see the next test) — never a bare `https:` scheme, which would let - the hub's own origin serve script. + only script sources are 'self' and the wasm eval token — never a bare + `https:` scheme, which would let the hub's own origin serve script. """ connect = _directive("connect-src").split()[1:] - assert set(connect) == {"'self'", "https://www.google.com", "https://www.gstatic.com"} + assert set(connect) == {"'self'"} script = _directive("script-src") assert script, "no script-src directive" sources = script.split()[1:] # drop the "script-src" keyword itself allowed = { "'self'", "'wasm-unsafe-eval'", - "https://www.google.com", "https://www.gstatic.com", } assert set(sources) <= allowed, \ f"unexpected script-src source: {set(sources) - allowed}" @@ -252,22 +245,17 @@ def test_the_hub_is_reachable_but_never_executable(): assert "default-src 'none'" in _policy() -def test_recaptcha_is_the_only_third_party_and_stays_scoped_to_it(): +def test_no_third_party_origin_in_the_policy(): """ - reCAPTCHA gates sign-up in the app the same way it does in the browser. - www.google.com and www.gstatic.com are allowed under script-src, frame-src - and img-src for that — and no other external origin appears anywhere in the - policy. Remove this expectation only alongside the reCAPTCHA widget. + Nothing outside the application's own files is reachable from the page. + The one exception there was, reCAPTCHA's two Google origins under + script-src, frame-src and img-src, went with the captcha: sign-up is gated + by a proof of work the hub issues itself (meshbay_hub/captcha.py). """ - hosts = {"https://www.google.com", "https://www.gstatic.com"} - for directive in ("script-src", "frame-src", "img-src"): - srcs = set(_directive(directive).split()[1:]) - assert hosts <= srcs, f"{directive} is missing a reCAPTCHA host" - for part in _policy().split(";"): for tok in part.strip().split()[1:]: - if tok.startswith(("http://", "https://")): - assert tok in hosts, f"unexpected external origin in CSP: {tok}" + assert not tok.startswith(("http://", "https://")), ( + f"external origin in CSP: {tok}") def test_the_pdf_preview_has_both_permissions_it_needs(): |