diff --git a/crates/beamr/RUSTSEC-0000-0000.md b/crates/beamr/RUSTSEC-0000-0000.md new file mode 100644 index 0000000000..b16f5aed23 --- /dev/null +++ b/crates/beamr/RUSTSEC-0000-0000.md @@ -0,0 +1,85 @@ +```toml +[advisory] +id = "RUSTSEC-0000-0000" +package = "beamr" +date = "2026-08-07" +url = "https://github.com/ablative-io/beamr/blob/main/CHANGELOG.md" +categories = ["memory-corruption"] +keywords = ["use-after-free", "garbage-collection", "memory-corruption"] + +[versions] +patched = [">= 0.16.3"] +``` + +# Three classes of silent memory corruption in the garbage collector, ETS, and binary BIFs + +`beamr` is a BEAM virtual machine. Its collector is a per-process generational +**copying** collector: a minor collection physically relocates live young-heap +objects and then zero-fills the vacated region. The only roots are the X/Y +register file and the process's native-root slots. A `Term` held in a Rust +local, or a `&[u8]` borrowed out of a binary, is **not** a root and is **not** +forwarded. + +Three classes of defect follow from that, all fixed by `0.16.3`: + +1. **`as_bytes` borrow-across-allocation** (fixed in `0.16.3`). A helper + returned `&'static [u8]` borrowed from garbage-collected process-heap + memory. Consumers held that borrow across a call that could trigger a + collection and then read through it. Eleven real crossings were enumerated, + including nine BIF sites reachable from ordinary Erlang/Gleam string and + binary operations, `binary_to_term`, and a JIT binary-match helper. + +2. **Garbage-collector refcount-release walk** (fixed in `0.16.2`). The walk + inferred an object's type from `word[0]` and could call `Arc::from_raw` on + a heap-cons payload — freeing memory that was never refcounted. + +3. **ETS stored borrowed caller-heap terms** (fixed in `0.16.2`) that outlived + the heap they pointed into. + +## Impact + +**There is no error, no panic and no crash in any of these classes.** The +vacated heap region is zero-filled rather than poisoned, so the failure mode +is corrupted or freed data read as valid. A passing test suite is not evidence +of non-exposure. + +Reaching class 1 requires no unsafe code and no unusual configuration on the +part of a user of the VM — the affected operations are ordinary string and +binary BIFs invoked by compiled Erlang/Gleam bytecode. + +## Affected versions + +**Upgrade to `0.16.3` or later.** `0.17.0` is the current release. + +No lower bound is claimed, and that is deliberate rather than unknown-by- +omission. Class 1's mechanism was measured across the crate's tag history: +the file carrying the borrow helper and all five affected string BIFs is +**byte-identical (one blob hash) across all 29 tags from `0.4.4` through +`0.15.2`, and at the `0.16.2` release commit**. The helper's signature is +present as far back as `0.2.0`. The introduction points of classes 2 and 3 +have **not** been measured; they are stated here as unmeasured rather than +assumed narrow. Treat every version below `0.16.3` as affected. + +## A separate, still-open class — disclosed, not fixed + +Independently of the three above, `beamr` publicly discloses a remaining set +of JIT-reachable rooting sites that is **not fixed in any released version, +including `0.17.0`**, and is reachable under the `jit` feature, which is on by +default. Contrary to what `beamr`'s own earlier release notes said, that +feature **cannot be disabled in any build that retains `threads`** — such a +build does not compile — so turning it off is not an available mitigation. + +That class is deliberately **not** the subject of this advisory: it has no fix +to point at and no action a consumer could take in response. It is recorded +here so that upgrading to `0.16.3` or `0.17.0` is not mistaken for a clean +bill of health. See "Correction to the 0.16.2 and 0.16.3 advisories" and +"Known remaining JIT sites" in the project's `CHANGELOG.md`. + +## References + +- Advisory and full class detail: + +- Site-level audit, including the forward-only amendments: + + +*Filed by the crate maintainers.*