diff --git a/index.html b/index.html index a7acd634..845f565f 100644 --- a/index.html +++ b/index.html @@ -6,8 +6,12 @@ Content-Security-Policy: defense-in-depth against XSS. The critical directive is script-src, which is strict — only same-origin scripts, the hash of the inline theme-bootstrap below, and the nostr-tools CDN - fallbacks (js/nostrToolsBootstrap.js). No 'unsafe-inline'/'unsafe-eval' - (verified: no bundle uses eval/Function/wasm). This blocks injected + fallbacks (js/nostrToolsBootstrap.js). No 'unsafe-inline'/'unsafe-eval'. + 'wasm-unsafe-eval' IS required: BitLogin's crypto worker compiles an + Argon2id WASM module, and a script-src without it blocks + WebAssembly.compile and breaks every BitLogin password flow. That + keyword permits WASM compilation only — JS eval stays blocked. This + blocks injected script and object elements, inline handlers (none exist), and base-tag hijack, so an injected payload cannot execute and read the in-memory storage master key / signer / DM plaintext. connect/img/media stay broad @@ -19,7 +23,7 @@ --> bitvid | Decentralized Video Sharing diff --git a/tests/csp-policy.test.mjs b/tests/csp-policy.test.mjs index 6f3e1bea..274889c0 100644 --- a/tests/csp-policy.test.mjs +++ b/tests/csp-policy.test.mjs @@ -87,6 +87,18 @@ for (const file of ["index.html", "embed.html"]) { ["'self'"], "base-uri must be 'self'", ); + + // index.html mounts (components/login-modal.html), whose + // crypto worker compiles an Argon2id WASM module. Without + // 'wasm-unsafe-eval' the browser blocks WebAssembly.compile and EVERY + // BitLogin password flow fails -- silently, since the page still loads. + // This exact omission broke sign-in on bitlogin.network for four days. + if (file === "index.html") { + assert.ok( + scriptSrc.includes("'wasm-unsafe-eval'"), + "script-src must include 'wasm-unsafe-eval' or BitLogin sign-in breaks", + ); + } }); test(`${file}: every inline