install: report an over-long relative path instead of a panic for --cafile, --cwd and add --filter

Closed
RO
1mo ago
+144-22

Problem

  • bun install --cafile=<relative path near PATH_MAX> crashes with panic: range end index 4109 out of range for slice of length 4095. bun install --cwd ./<long> and bun add --filter <ws> ./<long> crash the same way. An absolute path of the same length prints an error and exits 1.
  • The cause is join_abs_string_buf, which writes the joined path into a PATH_MAX buffer with no length check. Three sites join a user-supplied relative path onto the cwd with it: src/install/PackageManager.rs:2300 (cafile), src/install/PackageManager/CommandLineArguments.rs:1615 (--cwd), src/install/PackageManager/add_remove_with_filter.rs:405 (add --filter).

Fix

  • All three sites use join_abs_string_buf_checked. It returns None when the normalized result does not fit the buffer.
  • On None, each site prints the error it already prints for a bad path of that kind and exits 1: HTTPThread: could not find CA file: '<value>', failed to change directory to "<value>": ENAMETOOLONG, Dependency "<value>" has an unsafe folder path. The absolute --cwd branch copied into the buffer unchecked too. It now takes the same error path.
  • Verified: test/cli/install/bun-install-registry.test.ts (cafile at the exact buffer length, one byte past, far past, and the bunfig cafile key), test/cli/install/bun-install.test.ts (--cwd relative and absolute), test/cli/install/bun-add-filter.test.ts (add --filter local path). Each new test except the exact-fit one fails on the release build with the panic. Also ran all cafile, --cwd and --filter tests in those files.
  • Self-reviewed: the first commit was reviewed before the PR opened (3 concerns, all addressed). The review of the second commit did not return. I pushed it on the basis of the local test runs listed above.

Background

  • --cafile (and cafile in bunfig [install]) names a CA certificate bundle for registry TLS. PackageManager::init resolves a relative value against the original cwd before it starts the HTTP thread. The bunfig key feeds the same options.ca_file_name field.
  • bun_paths::resolve_path::join_abs_string_buf joins path parts into a caller buffer of MAX_PATH_BYTES (4096 on Linux, 1024 on macOS, about 98 KB on Windows). The _checked variant is the fallible form for user-controlled input. WorkspaceMap.rs, OverrideMap.rs and lockfile/Package.rs already use it.
  • Considered a check at only the cafile site: it leaves the same panic reachable from two other flags. The three sites share one mechanism, so the fix goes to all three.

Downsides

  • None found. The checked join takes the same fast path as the unchecked one when the joined length is below the buffer length (src/paths/resolve_path.rs:1690). Only an input that does not fit pays the slow path, and that input crashed before.
Notes

Repro on bun 1.4.2 and canary:

cd "$(mktemp -d)"; echo '{"name":"a","dependencies":{"x":"1"}}' > package.json
L=$(head -c 4090 /dev/zero | tr '\0' a)
bun install --cafile=$L
bun install --cwd ./$L
bun install --cwd /$(head -c 5000 /dev/zero | tr '\0' a)
bun add --filter b ./$L      # in a workspace root with a workspace named b

All four print panic: range end index N out of range for slice of length 4096 (4095 for the cafile case) on the release build.

The --cwd and add --filter sites came from a review comment on this PR. The cafile boundary tests and the bunfig entry point test came from another.


no test proof · iteration 0 · platform-specific test(s) that do not run on this machine, deferring to CI, which covers all platforms: test/cli/install/bun-install.test.ts, test/cli/install/bun-install-registry.test.ts, test/cli/install/bun-add-filter.test.ts