CodeVetter · Repo Unpack · Risk map
rolldown/rolldown
The main observed trust boundaries are executable configuration/plugins, output filesystem operations, worker IPC, and package acquisition. Source contains explicit protections and comments about lifecycle/deadlock constraints. The observations below identify behaviors and maintenance hazards; they do not establish exploitable vulnerabilities. Documentation and test limitations are scoped to the inspected files.
- Config loading executes imported JavaScript; default TS loading writes a hashed configuration bundle beside the original file and later unlinks it with ignored callback errors. It therefore requires filesystem and code-execution trust in the selected config.
- cleanDir removes entries recursively from the configured output directory before generation when no output.file is set; cleanup failures become warnings. Destination selection is consequently a high-impact filesystem boundary.
- Generated filenames are checked after generateBundle for escaping the output directory, and write rejects NUL bytes; these checks constrain bundler-emitted paths, while inspected plugin tests directly write files through Node fs.
- The WebContainer fallback uses a version-specific /tmp directory, removes/recreates it when the binding entry is missing, invokes pnpm i synchronously, and requires the installed binding. This introduces network/package-manager and outside-project filesystem effects on that branch.
- Parallel plugin workers dynamically import supplied file URLs; their adapter currently supplies empty input/output options, fresh isolated PluginContextData, and watchMode:false, with explicit TODOs for context sharing and watch metadata.
- Binding close deliberately uses a synchronous mutable-receiver method returning a spawned future because asynchronous NAPI mutable access is documented as unsafe; generation also pre-resolves external paths to avoid synchronous JS-callback deadlocks.
- CLI prototype-key filtering occurs after cac parsing; --environment writes process.env before help/version dispatch. These are observable input boundaries, not proof of complete pollution prevention or an identified exploit.
- Documentation drift is concrete: build() says array outputs run sequentially but uses Promise.all; the Rust bundler doc proposes removing close and describes cache-clearing behavior, whereas current close marks closed and closes the last handle.