Feature
WASI doesn't appear to be exercised by any fuzz target. The OSS-Fuzz crates/ coverage report for 2026-08-09 lists 15 instrumented crates — cache, cli-flags, component-util, core, cranelift, environ, fiber, fuzzing, jit-debug, jit-icache-coherence, test-util, unwinder, wasmtime, wast, winch — and no wasi* crate is among them. Grepping fuzz/fuzz_targets/ and crates/fuzzing/src/ for wasi also returns nothing.
Would a generative, stateful fuzz target for per-preopen FsPerms enforcement be useful? I'd rather ask than build, partly because there may be good reasons this hasn't been done that aren't visible from outside.
Benefit
Filesystem permissions look like they're enforced at three levels, and generative coverage seems to exist for the outer two but not the middle one:
| Layer |
Mechanism |
Generative coverage |
WASIp1 rights |
spec-level, per-fd |
wasi-testsuite — fixed conformance cases (e.g. truncation_rights.rs) |
wasmtime FsPerms |
embedder-level, per-preopen |
none found |
| cap-std containment |
per-Dir handle |
cap-std's fuzz_targets/cap-primitives.rs, with cfg(racy_asserts) checks |
The three recent WASI advisories all sit in that middle layer:
| Advisory |
Fix |
Cause |
| GHSA-2r75-cxrj-cmph (High) |
dc740c909 |
TRUNCATE didn't set open_mode |= OpenMode::WRITE, so the perms check saw a read-only open |
| GHSA-4ch3-9j33-3pmj (Moderate) |
2dc3f443d |
link_at/rename_at checked directory mutability but not permission parity |
| GHSA-3p27-qvp9-27qf (Low) |
f069f125c |
WASIp1 fd_renumber descriptor-table handling |
In each the permission gate runs in crates/wasi/src/filesystem.rs before cap_primitives is called, so cap-std's fuzzer isn't positioned to catch them — and FsPerms has no cap-std analogue to test against. The regression tests added with those fixes (p{1,2,3}_file_truncation_readonly.rs, p{1,2,3}_file_{hardlink,rename}_across_perms.rs) are targeted cases rather than generated sequences.
Implementation
Sketch, open to redirection:
- Two or more preopens with differing
FsPerms — the link/rename case needs at least two.
- Random sequences of filesystem operations across them, spanning the preopen boundary.
- Oracle: with a
ReadOnly preopen, snapshot the tree before and after and assert it's unchanged. That follows the documented contract on FsPerms directly and needs no model of individual operation semantics — it wouldn't need to know open_at(TRUNCATE) should fail, only that a file got shorter. atime excluded, since reading metadata is permitted.
- A second oracle asserting host file descriptors return to baseline would cover the
fd_renumber class.
- p1, p2 and p3 separately, since the regression tests suggest fixes don't automatically carry across surfaces.
Before proposing any of it as a PR I'd calibrate: check out the commit before each of the three fixes and confirm the oracle fires, then confirm it's silent across wasi-testsuite and crates/wasi/tests/. If it can't detect the three bugs already known, it isn't worth reviewing.
Alternatives
Extend the hand-written tests instead. FsPerms has two states, so the space is arguably small enough to enumerate — which is roughly what the current regression tests do. My hesitation is that the real space is operations × 2 permission states × 2+ preopens × path shapes × symlink/hard-link states × 3 API surfaces, and the link/rename issue was a relational property across two guest-chosen descriptors. But it's a fair objection and I'd rather hear it now than after writing the harness.
Fuzz at the cap-std layer. Doesn't reach it — FsPerms doesn't exist there.
Do nothing. Entirely possible this is deliberate; filesystem fuzzing is slow and awkward under OSS-Fuzz. If so, knowing that is worth the issue, and it may be worth a line in fuzz/README.md so the next person doesn't retrace it.
Happy to take this to an RFC instead if that's a better fit.
Feature
WASI doesn't appear to be exercised by any fuzz target. The OSS-Fuzz
crates/coverage report for 2026-08-09 lists 15 instrumented crates —cache,cli-flags,component-util,core,cranelift,environ,fiber,fuzzing,jit-debug,jit-icache-coherence,test-util,unwinder,wasmtime,wast,winch— and nowasi*crate is among them. Greppingfuzz/fuzz_targets/andcrates/fuzzing/src/forwasialso returns nothing.Would a generative, stateful fuzz target for per-preopen
FsPermsenforcement be useful? I'd rather ask than build, partly because there may be good reasons this hasn't been done that aren't visible from outside.Benefit
Filesystem permissions look like they're enforced at three levels, and generative coverage seems to exist for the outer two but not the middle one:
rightswasi-testsuite— fixed conformance cases (e.g.truncation_rights.rs)FsPermsDirhandlefuzz_targets/cap-primitives.rs, withcfg(racy_asserts)checksThe three recent WASI advisories all sit in that middle layer:
dc740c909TRUNCATEdidn't setopen_mode |= OpenMode::WRITE, so the perms check saw a read-only open2dc3f443dlink_at/rename_atchecked directory mutability but not permission parityf069f125cfd_renumberdescriptor-table handlingIn each the permission gate runs in
crates/wasi/src/filesystem.rsbeforecap_primitivesis called, so cap-std's fuzzer isn't positioned to catch them — andFsPermshas no cap-std analogue to test against. The regression tests added with those fixes (p{1,2,3}_file_truncation_readonly.rs,p{1,2,3}_file_{hardlink,rename}_across_perms.rs) are targeted cases rather than generated sequences.Implementation
Sketch, open to redirection:
FsPerms— thelink/renamecase needs at least two.ReadOnlypreopen, snapshot the tree before and after and assert it's unchanged. That follows the documented contract onFsPermsdirectly and needs no model of individual operation semantics — it wouldn't need to knowopen_at(TRUNCATE)should fail, only that a file got shorter.atimeexcluded, since reading metadata is permitted.fd_renumberclass.Before proposing any of it as a PR I'd calibrate: check out the commit before each of the three fixes and confirm the oracle fires, then confirm it's silent across
wasi-testsuiteandcrates/wasi/tests/. If it can't detect the three bugs already known, it isn't worth reviewing.Alternatives
Extend the hand-written tests instead.
FsPermshas two states, so the space is arguably small enough to enumerate — which is roughly what the current regression tests do. My hesitation is that the real space is operations × 2 permission states × 2+ preopens × path shapes × symlink/hard-link states × 3 API surfaces, and thelink/renameissue was a relational property across two guest-chosen descriptors. But it's a fair objection and I'd rather hear it now than after writing the harness.Fuzz at the cap-std layer. Doesn't reach it —
FsPermsdoesn't exist there.Do nothing. Entirely possible this is deliberate; filesystem fuzzing is slow and awkward under OSS-Fuzz. If so, knowing that is worth the issue, and it may be worth a line in
fuzz/README.mdso the next person doesn't retrace it.Happy to take this to an RFC instead if that's a better fit.