wasi-runtime random_get is a no-op stub (returns 0, writes nothing) #22

Closed
opened 2026-06-02 02:03:14 +02:00 by catbot · 0 comments
Member

In wasi-runtime/runtime.js the WASI random_get import is stubbed:

random_get() { return 0; }

It returns success (0) but never writes any bytes into the target buffer, so the destination stays whatever it was (zero in practice). Any wasm program that uses std::random_device (or otherwise calls random_get) therefore gets all-zero "randomness".

This bit us in 3DForts: every browser tab generated an identical all-zero peer id from std::random_device, which collided WebRTC signaling routing (two peers can't share an id). We worked around it app-side by sourcing entropy from crypto.getRandomValues via our own JS bridge, but the runtime stub is the root cause and will silently break any other random_device user.

Suggested fix: back random_get with crypto.getRandomValues, e.g.

random_get(ptr, len) {
    const mem = new Uint8Array(this.instance.exports.memory.buffer, ptr, len);
    crypto.getRandomValues(mem);
    return 0;
}

(adjust for how the runtime accesses wasm memory / the import's arg shape). Found via Catcrafts/3DForts#50.

In `wasi-runtime/runtime.js` the WASI `random_get` import is stubbed: ```js random_get() { return 0; } ``` It returns success (`0`) but never writes any bytes into the target buffer, so the destination stays whatever it was (zero in practice). Any wasm program that uses `std::random_device` (or otherwise calls `random_get`) therefore gets all-zero "randomness". This bit us in 3DForts: every browser tab generated an identical all-zero peer id from `std::random_device`, which collided WebRTC signaling routing (two peers can't share an id). We worked around it app-side by sourcing entropy from `crypto.getRandomValues` via our own JS bridge, but the runtime stub is the root cause and will silently break any other `random_device` user. Suggested fix: back `random_get` with `crypto.getRandomValues`, e.g. ```js random_get(ptr, len) { const mem = new Uint8Array(this.instance.exports.memory.buffer, ptr, len); crypto.getRandomValues(mem); return 0; } ``` (adjust for how the runtime accesses wasm memory / the import's arg shape). Found via Catcrafts/3DForts#50.
Sign in to join this conversation.
No description provided.