cargo / web-sys / audit
cargo : web-sys @ 0.3.99
PE Patrick Elsen signed 2026-05-28 published 2026-05-28

Claims

has-binarieshas-build-exechas-fuzz-testshas-install-exechas-integration-testshas-property-testshas-unit-testsimpl-algorithmimpl-concurrencyimpl-cryptoimpl-datastructureimpl-interpreterimpl-jitimpl-parserimpl-protocolis-benignunsafe-documentedunsafe-minimalunsafe-safeuses-concurrencyuses-cryptouses-environmentuses-execuses-filesystemuses-interpreteruses-jituses-networkuses-unsafe

Summary

web-sys 0.3.99 is a machine-generated crate of wasm-bindgen FFI declarations covering the full browser Web API surface (1,706 files, ~212K LOC). No build script, no binaries, no I/O. The 17 unsafe fn declarations are all documented and follow a uniform u8-slice-lifetime pattern with safe alternatives generated alongside. No findings.

Report

Subject

web-sys 0.3.99 is a machine-generated Rust crate that exposes browser Web APIs to WebAssembly programs via wasm-bindgen. It contains 1,706 generated source files under src/features/, each corresponding to one WebIDL interface or dictionary. APIs are gated behind per-type Cargo features; nearly every type in the crate is feature-gated, so the compiled footprint is determined by the consumer's feature selection. The crate is #![no_std] and targets the wasm32 architecture exclusively. Two runtime dependencies are declared: js-sys (JavaScript built-in bindings) and wasm-bindgen (the FFI framework).

Methodology

The published crate contents were compared against the upstream Git repository using diff -rq. The crate root (src/lib.rs) was read in full. Ten representative generated feature files containing unsafe fn declarations were read. Source surveys using grep confirmed the absence of network, filesystem, process, environment, and concurrency usage. The unsafe count was measured by searching for unsafe\s*(\{|fn|impl|trait) and the # Safety comment count was cross-referenced. The VCS tests/ directory was listed to characterise the integration test suite. No binary artifacts were searched for using find. The Cargo.toml and Cargo.toml.orig were read to verify the absence of a build script, proc-macro declaration, and default features.

Scope. Due to the volume of generated code (1,706 files, approximately 212K LOC), this is a scoped audit. The scope verifies supply-chain integrity (VCS byte-equivalence), the capability surface (uses-*), build/install-time execution, and dependency enumeration. All 17 unsafe declarations were located and reviewed; the unsafe sub-claims are asserted. unsafe-tested is not asserted: no MIRI or sanitizer runs were verified.

Results

The diff -rq comparison shows only Cargo.toml differs between the published crate and the VCS checkout, which is cargo normalisation. Source files are byte-equivalent. The crate omits tests/ and webidls/ from the published package via the include directive, consistent with VCS-only content. No injected code or unexpected differences were found, justifying is-benign.

The manifest declares build = false explicitly, so no build script runs, justifying has-build-exec and has-install-exec. There is no [lib] proc-macro = true. The crate ships no binary artifacts, justifying has-binaries.

All 17 occurrences of unsafe in the crate are pub unsafe fn declarations inside #[wasm_bindgen] extern "C" blocks. They follow a single generated pattern: set_*_u8_slice and new_with_u8_slice methods that accept &mut [u8] and pass a raw slice view to the JavaScript side. Each carries a # Safety doc comment explaining the lifetime requirement (the slice must outlive JS-side use). A safe alternative (_array variant) is generated alongside every unsafe variant. There are no unsafe {} blocks, unsafe impl, or raw pointer dereferences in any hand-written code. The unsafe declarations exist only where a performance-sensitive zero-copy path requires them, and each is annotated with a precise invariant statement and a safe alternative, justifying uses-unsafe, unsafe-documented, unsafe-safe, and unsafe-minimal.

The crate body contains no network calls, filesystem operations, process spawning, environment variable reads, or concurrency primitives: grep for all relevant patterns returned zero matches, justifying uses-network, uses-filesystem, uses-exec, uses-environment, uses-concurrency. uses-crypto, uses-jit, and uses-interpreter are likewise false.

The crate implements no algorithms (impl-algorithm), no parsers (impl-parser), no cryptographic operations (impl-crypto), no protocols (impl-protocol), no data structures (impl-datastructure), no interpreters (impl-interpreter), no JIT (impl-jit), and no concurrency primitives (impl-concurrency). All generated code is extern "C" import declarations delegating to the wasm-bindgen host runtime.

Integration tests (54 WASM test files) exist in the VCS repository under tests/wasm/ covering DOM APIs, console, blob, and other browser interfaces, justifying has-integration-tests. No unit tests are present in the crate source itself (has-unit-tests false). No fuzz or property tests were found, justifying has-fuzz-tests and has-property-tests as false.

Conclusion

web-sys 0.3.99 is entirely machine-generated code producing extern "C" import declarations for browser APIs. The 17 unsafe function declarations are all documented with # Safety comments and follow a uniform pattern with no unsafe function bodies. No I/O, network, filesystem, environment, or concurrency code is present. The crate has two dependencies (js-sys, wasm-bindgen), both part of the wasm-bindgen project at matching version pins. No findings were recorded.

Findings

No findings.

Annotations(3)

src/features

The VCS repository contains a tests/wasm/ directory (54 files) with WASM integration tests covering DOM APIs, blob, console, and other browser bindings. These tests require a browser or headless WASM runner and are not included in the published crate (excluded via the include directive in Cargo.toml). No unit tests or property tests are present. Justifies has-integration-tests, has-unit-tests, has-fuzz-tests, has-property-tests.

src/features/gen_EncodedVideoChunkInit.rs

src/features/gen_EncodedVideoChunkInit.rs, line 42-48

    #[doc = "# Safety"]
    #[doc = ""]
    #[doc = "The `val` slice must outlive any use of the dictionary on the JavaScript side. wasm-bindgen passes a raw view into wasm linear memory — if the underlying data is freed or moved before JS is done reading the field, the behaviour is undefined. Prefer the `_array` variant (takes `&Uint8Array`) for a safe alternative that copies the data."]
    #[wasm_bindgen(method, setter = "data")]
    pub unsafe fn set_data_u8_slice(this: &EncodedVideoChunkInit, val: &mut [u8]);
    #[cfg(web_sys_unstable_apis)]
    #[doc = "Change the `data` field of this object."]

All 17 unsafe fn declarations in this crate follow a single pattern: pub unsafe fn set_*_u8_slice and pub unsafe fn new_with_u8_slice, which expose raw &mut [u8] slice access to WebIDL dictionary fields. Each carries a # Safety doc comment explaining that the caller must ensure the slice outlives any JS-side use, because wasm-bindgen passes a raw view into WASM linear memory. A safe alternative (_array variant accepting &Uint8Array) is also generated alongside each unsafe variant. The 17 unsafe declarations are spread across 10 generated files. All are in extern "C" blocks under #[wasm_bindgen], so no unsafe body code exists in this crate; the unsafe is delegated to the wasm-bindgen runtime. Justifies uses-unsafe.