summaryrefslogtreecommitdiffstats
path: root/packages/meshbay-client/src/main.js
diff options
context:
space:
mode:
authorChristophe Besson <cbesson@gmail.com>2026-10-14 13:34:47 +0200
committerChristophe Besson <cbesson@gmail.com>2026-10-14 13:34:47 +0200
commit51705056a578d2649a989bf14a056fbcfae58a6b (patch)
treedfd078aba518427387fca29b9d43c3723b030008 /packages/meshbay-client/src/main.js
parentdaec4bc6a2a9f9e038e5269586b06018ff327a27 (diff)
downloadmeshbay-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-client/src/main.js')
-rw-r--r--packages/meshbay-client/src/main.js23
1 files changed, 5 insertions, 18 deletions
diff --git a/packages/meshbay-client/src/main.js b/packages/meshbay-client/src/main.js
index 33388e8..8845b7b 100644
--- a/packages/meshbay-client/src/main.js
+++ b/packages/meshbay-client/src/main.js
@@ -115,29 +115,16 @@ function nodeLogHint() {
// The hub is reachable under connect-src, for its API and its signaling socket.
// It is deliberately absent from script-src: nothing it returns is executed,
// which is the whole reason this application exists (T3).
-//
-// The one exception is reCAPTCHA, used to gate sign-up (and password reset) the
-// same way it gates them in the browser. Its script comes from www.google.com,
-// its challenge is a www.google.com iframe, and its assets sit on
-// www.gstatic.com. These two hosts — and only these two — are allowed under
-// `script-src`, `frame-src` and `img-src` for that purpose. It is a real, if
-// small, dent in "no third-party code runs here": Google's reCAPTCHA script
-// executes in the renderer. It is accepted deliberately so a native sign-up is
-// gated like a web one without asking the user to do anything extra, and it is
-// the *same* dependency the hub-served SPA already carries. If sign-up ever
-// moves to a proof-of-work challenge, delete RECAPTCHA_SRC and the three
-// directives that spread it, and the widget in auth-page.js with them.
-const RECAPTCHA_SRC = 'https://www.google.com https://www.gstatic.com';
const CSP = [
"default-src 'none'",
- `script-src 'self' 'wasm-unsafe-eval' ${RECAPTCHA_SRC}`,
+ "script-src 'self' 'wasm-unsafe-eval'",
"style-src 'self' 'unsafe-inline'",
- `img-src 'self' data: blob: ${RECAPTCHA_SRC}`,
+ "img-src 'self' data: blob:",
"media-src 'self' blob:",
"font-src 'self'",
// Every hub call leaves from this process, so the page connects to nothing
- // but its own files and reCAPTCHA; see the hub's webapp.CSP.
- `connect-src 'self' ${RECAPTCHA_SRC}`,
+ // but its own files; see the hub's webapp.CSP.
+ "connect-src 'self'",
"worker-src 'self'",
// `blob:` here and in `frame-src` are one thing, not two: the PDF preview.
//
@@ -157,7 +144,7 @@ const CSP = [
// is PDFium parsing bytes that came from a node — exactly what a browser
// does with the same file.
"object-src blob:",
- `frame-src blob: ${RECAPTCHA_SRC}`,
+ "frame-src blob:",
"frame-ancestors 'none'",
"base-uri 'none'",
"form-action 'none'",