# Risk map — oven-sh/bun

> Canonical page: https://codevetter.com/unpack/bun/risk-map

# Risk map — oven-sh/bun

Scanned commit bf80d21c69c355f6e5bae2749485674663ed13a1 (2026-09-22). Generated by codevetter codevetter 1.12.0 on 2026-09-22.

The dominant risk class is memory safety across a Rust/C++/JSC boundary where `unsafe` is routine, raw pointers are stored across event-loop turns, and GC interaction is manual — `REVIEW.md` names this the most-blocked review category. Security-sensitive paths include registry credential handling, lifecycle scripts and the out-of-process security scanner, runtime C compilation via TinyCC, `Bun.secrets` keychain access, S3 SigV4 signing, CSRF token HMACs, the dev server's Host-header check, and the self-upgrade download path. Fragile coupling shows up where a value must stay in sync with an out-of-repo consumer (crash-report tag chars and `bun.report`) or with generated code. Blast-radius hotspots are the very large single files: `bundle_v2.rs` (8,079 lines), `VirtualMachine.rs` (7,700), `DevServer.rs` (6,792), `RequestContext.rs` (4,794), `server/mod.rs` (4,372).
- `Run::start` holds the JSC API lock in a guard that is never dropped, justified only by the function's `-> !` return type — any future refactor that makes it return would leak or double-release the lock. — [src/runtime/cli/run_command.rs#L1283-1292](https://github.com/oven-sh/bun/blob/bf80d21c69c355f6e5bae2749485674663ed13a1/src/runtime/cli/run_command.rs#L1283-L1292)
- The run path deliberately leaks the entry path (`Box::leak(entry_path)`) because `vm.main` stores a raw backref into it and the hot reloader also retains it; correctness depends on the process never unwinding out of `start()`. — [src/runtime/cli/run_command.rs#L1175-1182](https://github.com/oven-sh/bun/blob/bf80d21c69c355f6e5bae2749485674663ed13a1/src/runtime/cli/run_command.rs#L1175-L1182)
- CPU/heap profiler config casts `ctx`-owned `Box<[u8]>` borrows to `'static` through `std::ptr::from_ref`, relying on the context being process-lifetime — a lifetime erasure that is correct only for this one caller. — [src/runtime/cli/run_command.rs#L1298-1330](https://github.com/oven-sh/bun/blob/bf80d21c69c355f6e5bae2749485674663ed13a1/src/runtime/cli/run_command.rs#L1298-L1330)
- `Tag::char()` must stay byte-for-byte in sync with a decoder in a separate repository (`oven-sh/bun.report`), and the comment pins a specific commit URL — a silent cross-repo coupling where adding a command breaks crash-report demangling with no local test. — [src/options_types/command_tag.rs#L50-56](https://github.com/oven-sh/bun/blob/bf80d21c69c355f6e5bae2749485674663ed13a1/src/options_types/command_tag.rs#L50-L56) [src/crash_handler/lib.rs#L570](https://github.com/oven-sh/bun/blob/bf80d21c69c355f6e5bae2749485674663ed13a1/src/crash_handler/lib.rs#L570) [src/crash_handler/lib.rs#L2611](https://github.com/oven-sh/bun/blob/bf80d21c69c355f6e5bae2749485674663ed13a1/src/crash_handler/lib.rs#L2611)
- Crash reports are uploaded to a default remote base URL (`https://bun.report`) encoding the command tag, platform, and address trace; there is an override and a disable path, but the default is outbound network on crash. — [src/crash_handler/lib.rs#L570](https://github.com/oven-sh/bun/blob/bf80d21c69c355f6e5bae2749485674663ed13a1/src/crash_handler/lib.rs#L570) [src/crash_handler/lib.rs#L3210](https://github.com/oven-sh/bun/blob/bf80d21c69c355f6e5bae2749485674663ed13a1/src/crash_handler/lib.rs#L3210) [src/crash_handler/lib.rs#L2322-2330](https://github.com/oven-sh/bun/blob/bf80d21c69c355f6e5bae2749485674663ed13a1/src/crash_handler/lib.rs#L2322-L2330)
- Registry credentials are parsed from `_authToken` segments and from bunfig scope objects into a single `NpmRegistry` value, meaning a bunfig or `.npmrc` parsing bug is directly a credential-disclosure or credential-confusion risk across registries. — [src/install/npm.rs#L390-440](https://github.com/oven-sh/bun/blob/bf80d21c69c355f6e5bae2749485674663ed13a1/src/install/npm.rs#L390-L440) [src/bunfig/bunfig.rs#L1193-1240](https://github.com/oven-sh/bun/blob/bf80d21c69c355f6e5bae2749485674663ed13a1/src/bunfig/bunfig.rs#L1193-L1240)
- `bun install` executes arbitrary package-authored lifecycle scripts via `bun_spawn`, gated by a `trustedDependencies` allowlist plus a checked-in `default-trusted-dependencies.txt` — the allowlist is the only thing between an install and arbitrary code execution. — [src/install/lifecycle_script_runner.rs#L1-45](https://github.com/oven-sh/bun/blob/bf80d21c69c355f6e5bae2749485674663ed13a1/src/install/lifecycle_script_runner.rs#L1-L45) [src/install/default-trusted-dependencies.txt](https://github.com/oven-sh/bun/blob/bf80d21c69c355f6e5bae2749485674663ed13a1/src/install/default-trusted-dependencies.txt) [src/install/PackageManager.rs#L160-168](https://github.com/oven-sh/bun/blob/bf80d21c69c355f6e5bae2749485674663ed13a1/src/install/PackageManager.rs#L160-L168)
- The security scanner runs third-party scanner modules in a child process communicating over fds 3 and 4; the child reads the packages JSON to EOF and a write failure only prints to stderr and exits 1, so protocol-level failures depend on the parent correctly distinguishing scan failure from clean scan. — [src/install/PackageManager/scanner-entry.ts#L12-45](https://github.com/oven-sh/bun/blob/bf80d21c69c355f6e5bae2749485674663ed13a1/src/install/PackageManager/scanner-entry.ts#L12-L45) [src/install/PackageManager/security_scanner.rs#L50-60](https://github.com/oven-sh/bun/blob/bf80d21c69c355f6e5bae2749485674663ed13a1/src/install/PackageManager/security_scanner.rs#L50-L60)
- `bun:ffi` compiles and executes attacker-influenced C at runtime through a vendored TinyCC fork, and `dlopen`s arbitrary shared libraries — an intentional capability with no sandbox, so any path that lets untrusted input reach `Bun.FFI.cc` is a full compromise. — [src/runtime/ffi/mod.rs#L1-25](https://github.com/oven-sh/bun/blob/bf80d21c69c355f6e5bae2749485674663ed13a1/src/runtime/ffi/mod.rs#L1-L25) [src/runtime/ffi/ffi_body.rs](https://github.com/oven-sh/bun/blob/bf80d21c69c355f6e5bae2749485674663ed13a1/src/runtime/ffi/ffi_body.rs) [src/tcc_sys](https://github.com/oven-sh/bun/blob/bf80d21c69c355f6e5bae2749485674663ed13a1/src/tcc_sys)
- `bun upgrade` downloads release tarballs from GitHub, verifies a `sha256:` digest only when `version.digest.tag.is_supported()`, and additionally shells out to an external verify step — so an unsupported digest tag silently degrades integrity checking to whatever the verify subprocess does. — [src/runtime/cli/upgrade_command.rs#L134-170](https://github.com/oven-sh/bun/blob/bf80d21c69c355f6e5bae2749485674663ed13a1/src/runtime/cli/upgrade_command.rs#L134-L170) [src/runtime/cli/upgrade_command.rs#L700-712](https://github.com/oven-sh/bun/blob/bf80d21c69c355f6e5bae2749485674663ed13a1/src/runtime/cli/upgrade_command.rs#L700-L712) [src/runtime/cli/upgrade_command.rs#L976-1050](https://github.com/oven-sh/bun/blob/bf80d21c69c355f6e5bae2749485674663ed13a1/src/runtime/cli/upgrade_command.rs#L976-L1050)
- The dev server's `is_allowed_host_header` allows any bare IP literal as a Host value; combined with binding to a non-loopback address this widens the accepted origin set beyond the configured hostname. — [src/runtime/bake/DevServer.rs#L1365-1396](https://github.com/oven-sh/bun/blob/bf80d21c69c355f6e5bae2749485674663ed13a1/src/runtime/bake/DevServer.rs#L1365-L1396)
- CSRF tokens are HMAC-signed with a caller-supplied secret and an optional `session_id`; an empty `session_id` slice explicitly means the token is bound to no principal, so a caller omitting it produces tokens valid for any session. — [src/csrf/lib.rs#L26-45](https://github.com/oven-sh/bun/blob/bf80d21c69c355f6e5bae2749485674663ed13a1/src/csrf/lib.rs#L26-L45)
- Analytics are on by default and gated by a `TriState` plus the `DO_NOT_TRACK` env var, with a packed feature bitset recording which APIs a run touched — telemetry that is opt-out rather than opt-in. — [src/analytics/lib.rs#L40-60](https://github.com/oven-sh/bun/blob/bf80d21c69c355f6e5bae2749485674663ed13a1/src/analytics/lib.rs#L40-L60) [src/analytics/lib.rs#L99-172](https://github.com/oven-sh/bun/blob/bf80d21c69c355f6e5bae2749485674663ed13a1/src/analytics/lib.rs#L99-L172)
- Five files exceed 4,000 lines and concentrate blast radius: `bundle_v2.rs` (8,079), `VirtualMachine.rs` (7,700), `DevServer.rs` (6,792), `RequestContext.rs` (4,794), and `server/mod.rs` (4,372); a change in any one touches most of a subsystem's invariants at once. — [src/bundler/bundle_v2.rs](https://github.com/oven-sh/bun/blob/bf80d21c69c355f6e5bae2749485674663ed13a1/src/bundler/bundle_v2.rs) [src/jsc/VirtualMachine.rs](https://github.com/oven-sh/bun/blob/bf80d21c69c355f6e5bae2749485674663ed13a1/src/jsc/VirtualMachine.rs) [src/runtime/bake/DevServer.rs](https://github.com/oven-sh/bun/blob/bf80d21c69c355f6e5bae2749485674663ed13a1/src/runtime/bake/DevServer.rs) [src/runtime/server/RequestContext.rs](https://github.com/oven-sh/bun/blob/bf80d21c69c355f6e5bae2749485674663ed13a1/src/runtime/server/RequestContext.rs)
- `RequestContext` cannot express its transport type through Rust's type system (the handle type varies with `(ssl_enabled, http3)` and stable Rust can't drive an associated type from a const-generic bool), and the file documents an abandoned trait-based approach — a known-fragile generic design that future transports must work around. — [src/runtime/server/RequestContext.rs#L41-48](https://github.com/oven-sh/bun/blob/bf80d21c69c355f6e5bae2749485674663ed13a1/src/runtime/server/RequestContext.rs#L41-L48)
- Dead code is policed by an external cross-crate analyzer (`hawk.toml`) configured to union reachability across all 11 shipped targets through a throwaway `bun_hawk_root` binary, implying ordinary `cargo` dead-code lints do not catch unreachable code in this workspace. — [hawk.toml#L1-25](https://github.com/oven-sh/bun/blob/bf80d21c69c355f6e5bae2749485674663ed13a1/hawk.toml#L1-L25) [tools/hawk](https://github.com/oven-sh/bun/blob/bf80d21c69c355f6e5bae2749485674663ed13a1/tools/hawk)

Every claim links to its cited files at the pinned commit. Citations identify source evidence; they do not establish runtime correctness. Independent CodeVetter scan — not reviewed by upstream maintainers.

## Public product links

- [CodeVetter](https://codevetter.com/)
- [Download](https://codevetter.com/download)
- [Documentation](https://codevetter.com/docs/)
- [Source](https://github.com/Codevetter/codevetter)
