Skip to content

Commit 40fcd96

Browse files
committed
feat(random): make get-random-bytes fallible
get-random-bytes and get-insecure-random-bytes accept a u64 length with no way to signal failure, allowing guests to request up to 2^64-1 bytes and forcing hosts to allocate unbounded memory or hard-trap. Add an error enum with a too-many-bytes case and change both functions to return result<list<u8>, error>. Add max-random-bytes-length and max-insecure-random-bytes-length query functions so guests can check limits upfront. Hosts MUST support at least 4096 bytes. The error type is defined in the random interface and reused by insecure via use. get-random-u64 and get-insecure-random-u64 are unchanged. Part of #888
1 parent bef9091 commit 40fcd96

File tree

5 files changed

+67
-16
lines changed

5 files changed

+67
-16
lines changed

proposals/cli/wit-0.3.0-draft/deps.lock

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,15 @@ sha512 = "f08a2828b88fc6ddea935af584531c484ad4a7a5f30340265e11e91b2bfe0f81e74a66
55

66
[filesystem]
77
path = "../../filesystem/wit-0.3.0-draft"
8-
sha256 = "184861e98785957311bfaab242cdf9e66a9ecca11fe2c493b840c461b2361088"
9-
sha512 = "50fa8801fc0a2c1ecfa3cea52af57836f98a12bb0a264439c13bbdcc0e269b3b37ade38b903d6ce10594d1f585d02ef993f3f769c4cddeebdfc00bf93734ed25"
8+
sha256 = "8808ea3adfbc1a025d649b82ddf4f38232ca4377100cfe671d80d5ee37fa3147"
9+
sha512 = "19f4eb8fa62e96ba37b3ea231af6a3bc396c28f82935018a3322441321936b34fb0e44360b378145fcb681d9fea810745969d8baab02ae6017be1784be8abe45"
1010

1111
[random]
1212
path = "../../random/wit-0.3.0-draft"
13-
sha256 = "5794796c909d6656fcbae6bed28265210ca57308a624119ac0a472326a75aa8f"
14-
sha512 = "812ce57aa13ff3128779d41f4dad50714365e4f9cfd2e1b13458a885fa65da05e409f145deefa25c4a82e0e301a41e2e6572705b35752dc33908d565a73a2e9c"
13+
sha256 = "e51ca727c7bbc0f5b6d7e52bb68d5d838a1c8f3d3ae683cf1c0f247b91b0633f"
14+
sha512 = "77791400acebdea60c35a3ca455ad73bc64584840a42fb2365bcfee6cff835fb14fb625145cdbde6cb7a153c841b479393dde8aa0f21bc7bab7046aca541aefb"
1515

1616
[sockets]
1717
path = "../../sockets/wit-0.3.0-draft"
18-
sha256 = "985821e86f2643d90b7a100420a44a5a60a6838adcf76fdb90a66255e3926dde"
19-
sha512 = "9ba1e9456c0dc02800ba738acd382a4113103bed72127396546c5f0ad3d38dd5c8e077443bd508b15f86f6095706907e9cb258cccab37c273b4c597a238987e7"
18+
sha256 = "0be70fab90ec1d62e620f37f8fc55397222ceb68ca8387eb0503df7173782634"
19+
sha512 = "997e336258dd3d8d1bf1b27463e77d1dc2160eb13fff899c93b446973f5efbc59448a23279b60568679c08e006a20cc88769ec74d6d30baa4e7a17df0bdb2c30"

proposals/http/wit-0.3.0-draft/deps.lock

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,13 @@ sha256 = "888647625fec3eaaf276cb884e426bc32bfa79ced22955f10eb239df74c8550c"
1010
sha512 = "f08a2828b88fc6ddea935af584531c484ad4a7a5f30340265e11e91b2bfe0f81e74a660a512f72e5197d60278feccc00534833ebd73868e801859dd31a61bdbb"
1111

1212
[filesystem]
13-
sha256 = "184861e98785957311bfaab242cdf9e66a9ecca11fe2c493b840c461b2361088"
14-
sha512 = "50fa8801fc0a2c1ecfa3cea52af57836f98a12bb0a264439c13bbdcc0e269b3b37ade38b903d6ce10594d1f585d02ef993f3f769c4cddeebdfc00bf93734ed25"
13+
sha256 = "8808ea3adfbc1a025d649b82ddf4f38232ca4377100cfe671d80d5ee37fa3147"
14+
sha512 = "19f4eb8fa62e96ba37b3ea231af6a3bc396c28f82935018a3322441321936b34fb0e44360b378145fcb681d9fea810745969d8baab02ae6017be1784be8abe45"
1515

1616
[random]
17-
sha256 = "5794796c909d6656fcbae6bed28265210ca57308a624119ac0a472326a75aa8f"
18-
sha512 = "812ce57aa13ff3128779d41f4dad50714365e4f9cfd2e1b13458a885fa65da05e409f145deefa25c4a82e0e301a41e2e6572705b35752dc33908d565a73a2e9c"
17+
sha256 = "329785794587f27cc531d19e23fe872237f052d7d839b29ae2288db5ae9f0533"
18+
sha512 = "691a26b30ce4fdfce070d0a9ccfe8b4f998b8dca6f58a7e22298457a8e0d05eba2f5fd38aa19879cc25bcc5f73a99358b33ae2690dde4e1dfea80fc841b1d69b"
1919

2020
[sockets]
21-
sha256 = "985821e86f2643d90b7a100420a44a5a60a6838adcf76fdb90a66255e3926dde"
22-
sha512 = "9ba1e9456c0dc02800ba738acd382a4113103bed72127396546c5f0ad3d38dd5c8e077443bd508b15f86f6095706907e9cb258cccab37c273b4c597a238987e7"
21+
sha256 = "0be70fab90ec1d62e620f37f8fc55397222ceb68ca8387eb0503df7173782634"
22+
sha512 = "997e336258dd3d8d1bf1b27463e77d1dc2160eb13fff899c93b446973f5efbc59448a23279b60568679c08e006a20cc88769ec74d6d30baa4e7a17df0bdb2c30"

proposals/random/README.md

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,9 +50,12 @@ The primary goals of WASI Random are:
5050

5151
### Non-goals
5252

53-
WASI Random is not aiming to allow programs to handle errors or to query for
53+
In WASIp2, WASI Random does not allow programs to handle errors or to query for
5454
availability. It always succeeds (though on platforms where randomness is
55-
unavailable, programs may fail to be instantiated or may trap).
55+
unavailable, programs may fail to be instantiated or may trap). In WASIp3,
56+
`get-random-bytes` and `get-insecure-random-bytes` return `result` types so that
57+
hosts can reject oversized requests gracefully (see
58+
[Resource exhaustion](#resource-exhaustion) below).
5659

5760
WASI Random is not aiming to be a full DRBG API. Such an API could be
5861
considered in WASI, but it should be a separate proposal.
@@ -171,6 +174,27 @@ their bits of security, and it doesn't seem desirable to require wasm engines to
171174
run their own CSPRNG on a platform which already has one, so for now, the API
172175
does not specify a specific number.
173176

177+
### Resource exhaustion
178+
179+
In WASIp2, `get-random-bytes` and `get-insecure-random-bytes` accept a `u64`
180+
length and return `list<u8>` with no way to signal failure. A guest can request
181+
up to 2^64-1 bytes, forcing hosts to either allocate unbounded memory or
182+
hard-trap. This was reported as [GHSA-852m-cvvp-9p4w].
183+
184+
WASIp3 addresses this by changing both functions to return
185+
`result<list<u8>, error>` where `error` is a variant with a `too-many-bytes`
186+
case and an `other(option<string>)` catch-all. This allows hosts to reject
187+
oversized requests gracefully instead of trapping. Callers that need more bytes
188+
than the host supports can simply retry in smaller chunks.
189+
190+
The `error` variant is defined once in the `random` interface and reused by
191+
`insecure` via `use random.{error}`, keeping the error type consistent.
192+
193+
The `get-random-u64` and `get-insecure-random-u64` functions are unchanged since
194+
they always return exactly 8 bytes, posing no resource exhaustion risk.
195+
196+
[GHSA-852m-cvvp-9p4w]: https://github.com/WebAssembly/WASI/security/advisories/GHSA-852m-cvvp-9p4w
197+
174198
### Why is insecure-random a fixed-sized return value?
175199

176200
This limits the amount of data that can be obtained through it. Since it's

proposals/random/wit-0.3.0-draft/insecure.wit

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@ package wasi:random@0.3.0-rc-2026-02-09;
55
/// Windows.
66
@since(version = 0.3.0-rc-2026-02-09)
77
interface insecure {
8+
@since(version = 0.3.0-rc-2026-02-09)
9+
use random.{error};
10+
811
/// Return `len` insecure pseudo-random bytes.
912
///
1013
/// This function is not cryptographically secure. Do not use it for
@@ -13,8 +16,13 @@ interface insecure {
1316
/// There are no requirements on the values of the returned bytes, however
1417
/// implementations are encouraged to return evenly distributed values with
1518
/// a long period.
19+
///
20+
/// # Errors
21+
///
22+
/// Returns `error::too-many-bytes` if `len` exceeds the host's supported
23+
/// limit.
1624
@since(version = 0.3.0-rc-2026-02-09)
17-
get-insecure-random-bytes: func(len: u64) -> list<u8>;
25+
get-insecure-random-bytes: func(len: u64) -> result<list<u8>, error>;
1826

1927
/// Return an insecure pseudo-random `u64` value.
2028
///

proposals/random/wit-0.3.0-draft/random.wit

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,20 @@ package wasi:random@0.3.0-rc-2026-02-09;
55
/// Windows.
66
@since(version = 0.3.0-rc-2026-02-09)
77
interface random {
8+
/// An error type for random byte generation.
9+
@since(version = 0.3.0-rc-2026-02-09)
10+
variant error {
11+
/// The requested number of bytes exceeds the host's supported limit.
12+
too-many-bytes,
13+
14+
/// A catch-all error for anything that doesn't fit into a more
15+
/// specific case. The optional string provides an unstructured
16+
/// description of the error. Users should not depend on the string
17+
/// for diagnosing errors, as it is not required to be consistent
18+
/// between implementations.
19+
other(option<string>),
20+
}
21+
822
/// Return `len` cryptographically-secure random or pseudo-random bytes.
923
///
1024
/// This function must produce data at least as cryptographically secure and
@@ -17,8 +31,13 @@ interface random {
1731
/// This function must always return fresh data. Deterministic environments
1832
/// must omit this function, rather than implementing it with deterministic
1933
/// data.
34+
///
35+
/// # Errors
36+
///
37+
/// Returns `error::too-many-bytes` if `len` exceeds the host's supported
38+
/// limit.
2039
@since(version = 0.3.0-rc-2026-02-09)
21-
get-random-bytes: func(len: u64) -> list<u8>;
40+
get-random-bytes: func(len: u64) -> result<list<u8>, error>;
2241

2342
/// Return a cryptographically-secure random or pseudo-random `u64` value.
2443
///

0 commit comments

Comments
 (0)