dotenv: expose auto-loaded .env values as non-enumerable on process.env - #35481
Closed
robobun wants to merge 14 commits into
Closed
dotenv: expose auto-loaded .env values as non-enumerable on process.env#35481robobun wants to merge 14 commits into
robobun wants to merge 14 commits into
Claude / Claude Code Review
completed
Jul 24, 2026 in 18m 4s
Code review found 1 important issue
Found 5 candidates, confirmed 3. See review comments for details.
Details
| Severity | Count |
|---|---|
| 🔴 Important | 1 |
| 🟡 Nit | 2 |
| 🟣 Pre-existing | 0 |
| Severity | File:Line | Issue |
|---|---|---|
| 🔴 Important | src/jsc/bindings/JSEnvironmentVariableMap.cpp:891-897 |
SHARE_ENV worker founding drops auto-loaded .env values from main thread's process.env |
| 🟡 Nit | src/jsc/bindings/JSEnvironmentVariableMap.cpp:831-841 |
Special-cased and integer-keyed env vars ignore the conditional flag |
| 🟡 Nit | test/cli/run/env.test.ts:722-729 |
'empty string disables default dotenv behavior' test is now vacuous |
Annotations
Check failure on line 897 in src/jsc/bindings/JSEnvironmentVariableMap.cpp
claude / Claude Code Review
SHARE_ENV worker founding drops auto-loaded .env values from main thread's process.env
Marking auto-loaded `.env` keys `DontEnum` breaks the SHARE_ENV worker path: `ensureSharedEnvStoreForWorker` seeds the shared store via `getOwnPropertyNames(..., DontEnumPropertiesMode::Exclude)` and then swaps the main thread's `process.env` to a `JSSharedEnvMap` that reads only from that store. After the first `new Worker(url, { env: SHARE_ENV })`, `process.env.API_KEY` on the **main thread** returns `undefined` for any key that came only from an auto-discovered `.env*` file — a regression tha
Check warning on line 841 in src/jsc/bindings/JSEnvironmentVariableMap.cpp
claude / Claude Code Review
Special-cased and integer-keyed env vars ignore the conditional flag
The `conditional` flag isn't honored by every arm of the per-key loop: the special-cased names (`TZ`, `NODE_TLS_REJECT_UNAUTHORIZED`, `BUN_CONFIG_VERBOSE_FETCH`, and the six proxy vars) set `hasXXX = true; continue;` before it's consulted, and the integer-index fast path passes attributes `0` to `putDirectIndex` unconditionally. So a `.env`-only `HTTP_PROXY`, `TZ`, or `123=foo` is still installed *enumerable* on POSIX — while on Windows the `if (!conditional)` guard on `keyArray->push` correctly
Check warning on line 729 in test/cli/run/env.test.ts
claude / Claude Code Review
'empty string disables default dotenv behavior' test is now vacuous
The `empty string disables default dotenv behavior` test (and `should ignore a file that doesn't exist` at line 741) still uses the shared `index.ts` that enumerates via `Object.entries(process.env)`. After this PR, if `--env-file=''` regressed and auto-loaded `.env` again, `BUNTEST_DOTENV` would be installed `DontEnum` and `Object.entries` would still emit `""` — the assertion can no longer fail for the property it protects. Apply the same direct-read fix used just above: spawn with `-e 'consol
Loading