Skip to content

dotenv: expose auto-loaded .env values as non-enumerable on process.env - #35481

Closed
robobun wants to merge 14 commits into
mainfrom
farm/5353a8ba/dotenv-conditional-vars
Closed

dotenv: expose auto-loaded .env values as non-enumerable on process.env#35481
robobun wants to merge 14 commits into
mainfrom
farm/5353a8ba/dotenv-conditional-vars

address review: snapshot process.env via getOwnPropertyNames for Bun.…

b43fe85
Select commit
Loading
Failed to load commit list.
Claude / Claude Code Review completed Jul 25, 2026 in 39m 28s

Code review found 2 important issues

Found 3 candidates, confirmed 6. See review comments for details.

Details

Severity Count
🔴 Important 2
🟡 Nit 4
🟣 Pre-existing 0
Severity File:Line Issue
🔴 Important src/js/node/child_process.ts:1023-1032 cluster.fork() and the WASI runner drop auto-loaded .env values from child environments
🟡 Nit src/js/builtins/shell.ts:259-266 ShellPromise.prototype.env() bypasses snapshotProcessEnv, dropping auto-loaded .env values

Annotations

Check failure on line 1032 in src/js/node/child_process.ts

See this annotation in the file changed.

@claude claude / Claude Code Review

cluster.fork() and the WASI runner drop auto-loaded .env values from child environments

Two more default-env-inheritance siblings were missed by the `getOwnPropertyNames` compensation applied here (and its analogues in shell.ts / JSWorker.cpp / `ensureSharedEnvStoreForWorker`): **`cluster.fork()`** (src/js/internal/cluster/primary.ts:81 builds `{ ...process.env, ...env, NODE_UNIQUE_ID }` and passes it as `options.env` to `child_process.fork`, so the spread drops DontEnum `.env` keys and this branch's `env === process.env` check does not fire) and the built-in **WASI runner** (src/j

Check warning on line 266 in src/js/builtins/shell.ts

See this annotation in the file changed.

@claude claude / Claude Code Review

ShellPromise.prototype.env() bypasses snapshotProcessEnv, dropping auto-loaded .env values

`snapshotProcessEnv` is applied at the two template-tag `setEnv` sites (lines 324 and 344) but not at the third sibling in this file — `ShellPromise.prototype.env()` still calls `this.#args!.setEnv(newEnv)` directly. So ``await Bun.$`cmd`.env(undefined)`` (or `.env(process.env)`) passes the raw `process.env` to `ParsedShellScript::set_env`, which iterates enumerable-only and drops the now-DontEnum auto-loaded `.env` keys, overwriting the correct snapshot the template tag already installed. Apply