Skip to content

Commit da34d9e

Browse files
committed
fix(wasi): replace global / preopen with auto-detected absolute path preopens
preopening `/` → `/` gave ripgrep access to the entire filesystem, causing permission errors when traversing system directories. Now only `.` → cwd is preopened by default, and absolute paths from args are added individually.
1 parent f5ff679 commit da34d9e

4 files changed

Lines changed: 15 additions & 5 deletions

File tree

AGENTS.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525

2626
### Runtime behavior
2727

28-
- Default preopens map `.``process.cwd()` and `/``/` so both relative and absolute paths work out of the box; override via `options.preopens`.
28+
- Default preopens map `.``process.cwd()`; absolute paths passed as args are auto-added as preopens so they work without extra configuration.
2929
- ripgrep's TTY auto-detection doesn't work through WASI preview1 (it always sees a non-TTY), so `ripgrep` auto-injects `--color=ansi` when `process.stdout.isTTY` and the caller hasn't specified a color flag. Detection checks `--color`, `--color=…`, and `--no-color`.
3030
- `nodeWasi: true` (or `ZIGREP_NODE_WASI=1`) swaps the custom shim for Node's built-in `node:wasi`. Same `{ imports, start }` shape either way. Node's version prints an `ExperimentalWarning` on every run — that's why the custom shim is the default.
3131
- `start()` returns `0` on clean exit or the exit code from `WASIExit`; `node:wasi`'s `start()` returns `undefined` on success, so the adapter coerces with `?? 0`. The public `ripgrep()` function wraps this into a `{ code }` result object.

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ Runs ripgrep with the given CLI arguments and returns a `{ code }` result object
3333
Options:
3434

3535
- `env` — environment variables passed to the WASI instance (default: `process.env`).
36-
- `preopens` — WASI preopened directories mapping guest paths to host paths (default: `{ ".": process.cwd(), "/": "/" }`). Both the current directory and the filesystem root are preopened by default so that relative and absolute paths work out of the box.
36+
- `preopens` — WASI preopened directories mapping guest paths to host paths (default: `{ ".": process.cwd() }`). Absolute paths passed as args are auto-added as preopens.
3737
- `returnOnExit` — when `true`, `proc_exit` returns the exit code instead of terminating the process (default: `true`).
3838
- `nodeWasi` — use Node's built-in `node:wasi` instead of the bundled WASI shim. Enabled by default on Node.js for best performance; automatically disabled on Bun and Deno where `node:wasi` is not available, falling back to the bundled shim. Can also be forced on via `ZIGREP_NODE_WASI=1`.
3939

lib/index.d.mts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ export interface ripgrepOptions {
6262
/**
6363
* WASI preopened directories, mapping guest paths to host paths.
6464
* Required for ripgrep to see any files on disk.
65-
* @default { ".": process.cwd(), "/": "/" }
65+
* @default { ".": process.cwd() }
6666
*/
6767
preopens?: Record<string, string>;
6868

lib/index.mjs

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
import { fileURLToPath } from "node:url";
2+
import { isAbsolute } from "node:path";
23

34
export const rgPath = fileURLToPath(new URL("./rg.mjs", import.meta.url));
45

56
export async function ripgrep(args = [], options = {}) {
67
const {
78
env = process.env,
8-
preopens = { ".": process.cwd(), "/": "/" },
9+
preopens = { ".": process.cwd() },
910
returnOnExit = true,
1011
nodeWasi = getDefaultNodeWasi(),
1112
} = options;
@@ -20,11 +21,20 @@ export async function ripgrep(args = [], options = {}) {
2021
args = ["--color=ansi", ...args];
2122
}
2223

24+
// Auto-add preopens for absolute paths found in args so they're accessible
25+
// without requiring the caller to manually configure preopens.
26+
const resolvedPreopens = { ...preopens };
27+
for (const arg of args) {
28+
if (isAbsolute(arg) && !(arg in resolvedPreopens)) {
29+
resolvedPreopens[arg] = arg;
30+
}
31+
}
32+
2333
const wasi = await createWasiRuntime({
2434
args,
2535
env,
2636
nodeWasi,
27-
preopens,
37+
preopens: resolvedPreopens,
2838
returnOnExit,
2939
});
3040

0 commit comments

Comments
 (0)