Follow-up from #275.
Problem
src/webview/webviewHtml.ts:26:
nonce += NONCE_CHARS[byte % NONCE_CHARS.length];
NONCE_CHARS is 62 characters and byte ranges over 0–255. 256 % 62 == 8, so indices 0–7 (A–H) are each reachable from 5 byte values while indices 8–61 are reachable from 4 — roughly 25% over-represented.
Not exploitable at 32 characters: even biased, the nonce carries far more entropy than an attacker could brute-force before the document is replaced. The reason to fix it is that the doc comment immediately above stakes a cryptographic claim —
crypto.getRandomValues is available in the extension host runtime and is preferred over Math.random for a value that gates script execution.
— and a biased modulo reduction is the textbook mistake that claim is supposed to rule out. Someone reading this as the reference pattern for the other five webview documents will copy it.
Suggested fix
Either:
- rejection-sample: discard bytes
>= 248 (the largest multiple of 62 below 256) and redraw, or
- use an alphabet whose size divides 256 — hex (16) or base64url (64). Both are valid CSP nonce characters, and base64url at 32 characters keeps the same entropy budget with no rejection loop.
The second is less code and has no loop to reason about.
Follow-up from #275.
Problem
src/webview/webviewHtml.ts:26:NONCE_CHARSis 62 characters andbyteranges over 0–255.256 % 62 == 8, so indices 0–7 (A–H) are each reachable from 5 byte values while indices 8–61 are reachable from 4 — roughly 25% over-represented.Not exploitable at 32 characters: even biased, the nonce carries far more entropy than an attacker could brute-force before the document is replaced. The reason to fix it is that the doc comment immediately above stakes a cryptographic claim —
— and a biased modulo reduction is the textbook mistake that claim is supposed to rule out. Someone reading this as the reference pattern for the other five webview documents will copy it.
Suggested fix
Either:
>= 248(the largest multiple of 62 below 256) and redraw, orThe second is less code and has no loop to reason about.