Found by driving the real popup in a containerized Chrome (see #181). Not
reachable by the unit tests, because they run in node where no extension CSP
applies.
Observed
Every single load of src/popup/index.html in a real browser emits an uncaught
page error:
Aborted(CompileError: WebAssembly.instantiate(): Refused to compile or
instantiate WebAssembly module because neither 'wasm-eval' nor 'unsafe-eval' is
an allowed source of script in the following Content Security Policy directive:
"script-src 'self'"). Build with -sASSERTIONS for more info.
libsodium-wrappers-sumo ships a WASM build and an asm.js fallback. The
extension CSP (script-src 'self', correctly, with no wasm-unsafe-eval)
refuses the WASM module, libsodium catches it and falls back to asm.js, and
everything continues to work - wallet creation, vault encryption and state
persistence were all verified working in the same session.
Why this matters anyway
vault.js is the password-based encryption for the user's seed. Three concerns,
in order of how much they should worry us:
We are running an untested code path in production. Every unit test runs
under node, where WASM instantiates fine. So the crypto backend the tests
exercise is not the backend users actually get. Whatever confidence the test
suite provides for vault.js, it provides it for the wrong build.
The failure is silent. It surfaces as console noise that nobody reads.
If a future libsodium version drops or breaks the asm.js fallback, this
becomes a hard failure of wallet decryption, and the only warning we ever had
was a log line we had learned to ignore.
asm.js Argon2 is materially slower than WASM. If the KDF parameters were
ever tuned against node timings, users are getting a slower unlock than
intended - or, worse, parameters were softened to compensate for a slowness
that only exists because of this.
Definition of done
The popup loads with no uncaught page error relating to WASM.
It is explicit and deliberate which libsodium backend ships, rather than
being decided by a caught exception at runtime. Either:
add wasm-unsafe-eval to the extension CSP and confirm the WASM backend
actually loads (weighed against the fact that a wallet loosening its own
CSP deserves a hard look and may simply not be worth it), or
deliberately ship the asm.js build so no WASM instantiation is attempted
at all, and document why.
Whichever is chosen, vault.js unit tests must exercise the backend that
actually ships.
Record the decision and its reasoning in the code near the import, not only
in this issue.
Verified in the #181 harness with the error no longer present, and its
allowlist entry for this error removed.
Notes
Investigate whether the same applies to the Firefox MV2 build, whose CSP is
declared separately in manifest/firefox.json.
Recommendation: prefer shipping asm.js explicitly over loosening the CSP. A
wallet should not relax script-src for a performance gain on an operation the
user performs a handful of times a session. But measure the unlock time before
deciding, rather than assuming - if the asm.js KDF is unacceptably slow, that is
a real argument and the tradeoff should be made on numbers.
Found by driving the real popup in a containerized Chrome (see #181). Not
reachable by the unit tests, because they run in node where no extension CSP
applies.
## Observed
Every single load of `src/popup/index.html` in a real browser emits an uncaught
page error:
```
Aborted(CompileError: WebAssembly.instantiate(): Refused to compile or
instantiate WebAssembly module because neither 'wasm-eval' nor 'unsafe-eval' is
an allowed source of script in the following Content Security Policy directive:
"script-src 'self'"). Build with -sASSERTIONS for more info.
```
`libsodium-wrappers-sumo` ships a WASM build and an asm.js fallback. The
extension CSP (`script-src 'self'`, correctly, with no `wasm-unsafe-eval`)
refuses the WASM module, libsodium catches it and falls back to asm.js, and
everything continues to work - wallet creation, vault encryption and state
persistence were all verified working in the same session.
## Why this matters anyway
`vault.js` is the password-based encryption for the user's seed. Three concerns,
in order of how much they should worry us:
1. **We are running an untested code path in production.** Every unit test runs
under node, where WASM instantiates fine. So the crypto backend the tests
exercise is not the backend users actually get. Whatever confidence the test
suite provides for `vault.js`, it provides it for the wrong build.
2. **The failure is silent.** It surfaces as console noise that nobody reads.
If a future libsodium version drops or breaks the asm.js fallback, this
becomes a hard failure of wallet decryption, and the only warning we ever had
was a log line we had learned to ignore.
3. **asm.js Argon2 is materially slower than WASM.** If the KDF parameters were
ever tuned against node timings, users are getting a slower unlock than
intended - or, worse, parameters were softened to compensate for a slowness
that only exists because of this.
## Definition of done
- The popup loads with **no uncaught page error** relating to WASM.
- It is explicit and deliberate which libsodium backend ships, rather than
being decided by a caught exception at runtime. Either:
- add `wasm-unsafe-eval` to the extension CSP and confirm the WASM backend
actually loads (weighed against the fact that a wallet loosening its own
CSP deserves a hard look and may simply not be worth it), **or**
- deliberately ship the asm.js build so no WASM instantiation is attempted
at all, and document why.
- Whichever is chosen, `vault.js` unit tests must exercise the backend that
actually ships.
- Record the decision and its reasoning in the code near the import, not only
in this issue.
- Verified in the #181 harness with the error no longer present, and its
allowlist entry for this error removed.
## Notes
Investigate whether the same applies to the Firefox MV2 build, whose CSP is
declared separately in `manifest/firefox.json`.
Recommendation: prefer shipping asm.js explicitly over loosening the CSP. A
wallet should not relax `script-src` for a performance gain on an operation the
user performs a handful of times a session. But measure the unlock time before
deciding, rather than assuming - if the asm.js KDF is unacceptably slow, that is
a real argument and the tradeoff should be made on numbers.
clawbot
added this to the 1.0.0 milestone 2026-08-09 16:10:35 +02:00
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Found by driving the real popup in a containerized Chrome (see #181). Not
reachable by the unit tests, because they run in node where no extension CSP
applies.
Observed
Every single load of
src/popup/index.htmlin a real browser emits an uncaughtpage error:
libsodium-wrappers-sumoships a WASM build and an asm.js fallback. Theextension CSP (
script-src 'self', correctly, with nowasm-unsafe-eval)refuses the WASM module, libsodium catches it and falls back to asm.js, and
everything continues to work - wallet creation, vault encryption and state
persistence were all verified working in the same session.
Why this matters anyway
vault.jsis the password-based encryption for the user's seed. Three concerns,in order of how much they should worry us:
under node, where WASM instantiates fine. So the crypto backend the tests
exercise is not the backend users actually get. Whatever confidence the test
suite provides for
vault.js, it provides it for the wrong build.If a future libsodium version drops or breaks the asm.js fallback, this
becomes a hard failure of wallet decryption, and the only warning we ever had
was a log line we had learned to ignore.
ever tuned against node timings, users are getting a slower unlock than
intended - or, worse, parameters were softened to compensate for a slowness
that only exists because of this.
Definition of done
being decided by a caught exception at runtime. Either:
wasm-unsafe-evalto the extension CSP and confirm the WASM backendactually loads (weighed against the fact that a wallet loosening its own
CSP deserves a hard look and may simply not be worth it), or
at all, and document why.
vault.jsunit tests must exercise the backend thatactually ships.
in this issue.
allowlist entry for this error removed.
Notes
Investigate whether the same applies to the Firefox MV2 build, whose CSP is
declared separately in
manifest/firefox.json.Recommendation: prefer shipping asm.js explicitly over loosening the CSP. A
wallet should not relax
script-srcfor a performance gain on an operation theuser performs a handful of times a session. But measure the unlock time before
deciding, rather than assuming - if the asm.js KDF is unacceptably slow, that is
a real argument and the tradeoff should be made on numbers.