## https://sploitus.com/exploit?id=73E13021-2D12-5EE4-9FCE-2B677C01BCFB
# Bun Archive Extraction Traversal PoCs
Target: `oven-sh/bun` `HEAD e750984` observed on 2026-05-16.
Finding: buffered libarchive extraction rejects empty and `.` paths, but does not reject normalized POSIX paths that still begin with `../`. This can let a malicious tar entry write outside the extraction directory.
This is an arbitrary file write primitive, not a standalone RCE. Report it that way. RCE is only a follow-on chain if the attacker can overwrite a file that is later executed or trusted by CI/build tooling.
## PoC 1: Bun.Archive.extract()
Run on a machine that has Bun with `Bun.Archive` support:
```sh
bun run poc-archive-extract.ts
```
Vulnerable output:
```text
[vulnerable] outside file exists
```
Patched output:
```text
[patched] outside file was not created
```
The controlled outside target is under the system temp directory:
```text
/bun-archive-traversal-poc/outside-from-archive.txt
```
## PoC 2: bun install file: tarball
Run:
```sh
bun run poc-install-file-dependency.ts
```
This creates a temporary project and installs a local `file:` tarball with `--ignore-scripts`. It does not rely on lifecycle scripts. It also sets `BUN_INSTALL_CACHE_DIR` to a temporary cache and `BUN_FEATURE_FLAG_DISABLE_STREAMING_INSTALL=1` to force the buffered extraction path.
Vulnerable output:
```text
[vulnerable] install wrote outside target
```
Patched output:
```text
[patched] outside install target was not created
```
## Relevant Code
- `src/libarchive/libarchive.zig`: normalize then only skip empty/dot before `createFileZ`
- `src/libarchive/lib.rs`: Rust port mirrors the same behavior with `openat`
- `src/install/TarballStream.zig`: streaming path has the missing leading-`..` guard
- `src/runtime/api/Archive.zig`: public API calls `libarchive.Archiver.extractToDisk(... depth_to_skip = 0 ...)`
- `src/install/extract_tarball.zig`: package manager buffered path calls `Archiver.extractToDir(... depth_to_skip = 1 ...)`
## Expected Fix
Add the same guard used by the streaming extractor immediately after normalization and before any directory, symlink, or file operation:
```zig
if (path.len >= 2 and path[0] == '.' and path[1] == '.' and
(path.len == 2 or path[2] == std.fs.path.sep))
{
continue :loop;
}
```
Add the equivalent check in the Rust port.