What version of Bun is running?
1.3.14+0d9b296af (also reproduces on 1.3.1+89fa0f343).
The relevant code path on main is unchanged: src/install/PackageManager.zig:794.
What platform is your computer?
Darwin 25.1.0 arm64 arm
What steps can reproduce the bug?
mkdir /tmp/bun-envleak-repro && cd /tmp/bun-envleak-repro
cat > package.json <<'EOF'
{
"name": "bun-envleak-repro",
"version": "0.0.0",
"scripts": {
"postinstall": "node -e \"console.log('postinstall sees SOME_API_SECRET =', JSON.stringify(process.env.SOME_API_SECRET))\""
}
}
EOF
echo 'SOME_API_SECRET=leaked-prod-value' > .env.production
bun install # postinstall sees "leaked-prod-value"
bun install --no-env-file # postinstall sees "leaked-prod-value" ❌
bun install --env-file=/dev/null # postinstall sees "leaked-prod-value" ❌
NODE_ENV=development bun install # postinstall sees "leaked-prod-value" ❌
bun install --production # postinstall sees "leaked-prod-value" ❌
echo 'env = false' > bunfig.toml && bun install # postinstall sees "leaked-prod-value" ❌
Knob matrix (all run against bun 1.3.14):
| Knob |
Suppresses default .env* load at install? |
bun install --no-env-file |
no |
bun install --env-file=/dev/null |
no |
bun install --production / -p / --omit=dev |
no |
NODE_ENV=development bun install |
no |
BUN_INSTALL_NODE_ENV=development bun install |
no |
bunfig.toml env = false |
no |
bunfig.toml [install] env = false |
no |
Rename file outside {.env, .env.production, .env.local} |
yes (workaround) |
What is the expected behavior?
bun install should honour the three knobs that PR #24767 added for the runtime / bundler:
--no-env-file → skip default .env* loading.
--env-file <path> → use only the explicit file(s).
bunfig.toml env = false (or env.file = false / null) → skip default .env* loading.
bun --help advertises --env-file and --no-env-file as global flags, but bun install --help doesn't mention them and install silently ignores them — no error, no warning, no effect.
What do you see instead?
Install always loads .env.production, .env.local, and .env regardless of every documented knob. The matching code on main is:
// src/install/PackageManager.zig:794
try env.loadProcess();
try env.load(entries_option.entries, &[_][]u8{}, .production, false);
Three hardcodes:
The Loader.load(...) API (src/dotenv/env_loader.zig:600) already accepts the right parameters. PR #24767 already added disable_default_env_files to api.TransformOptions (src/api/schema.zig) and the bunfig parser (src/bunfig.zig). The install path just never reads them.
Additional information
Why this matters
Every dependency's postinstall script runs with process.env populated by the loaded .env* files. Anyone keeping app secrets in .env.production and running bun install in CI is silently handing those secrets to every transitive trustedDependencies postinstall — meaningfully worse than the runtime case PR #24767 already fixed, because postinstall is 3rd-party code.
I have hit this on my own React Native / Expo app. I worked around it by renaming .env.production → .env.prod so the loader's hardcoded match misses, but that's a name-collision workaround, not a fix.
Suggested scope
Strictly mirror PR #24767's pattern for install:
- Wire
ctx.args.env_files and ctx.args.disable_default_env_files into the env.load(...) call at PackageManager.zig:794.
- Register
--env-file / --no-env-file on bun install's clap params if install uses its own parser (otherwise the global ones should flow through via ctx.args).
- Add
test/cli/install/no-env-file.test.ts mirroring test/cli/run/no-envfile.test.ts.
Happy to open the PR if maintainers are receptive. Would also like to know if there's appetite for a separate discussion on whether bun install should auto-load .env* at all by default — security argument above, but that's a default-behaviour change.
Related
What version of Bun is running?
1.3.14+0d9b296af(also reproduces on1.3.1+89fa0f343).The relevant code path on
mainis unchanged:src/install/PackageManager.zig:794.What platform is your computer?
Darwin 25.1.0 arm64 arm
What steps can reproduce the bug?
Knob matrix (all run against
bun 1.3.14):.env*load at install?bun install --no-env-filebun install --env-file=/dev/nullbun install --production/-p/--omit=devNODE_ENV=development bun installBUN_INSTALL_NODE_ENV=development bun installbunfig.tomlenv = falsebunfig.toml[install] env = false{.env, .env.production, .env.local}What is the expected behavior?
bun installshould honour the three knobs that PR #24767 added for the runtime / bundler:--no-env-file→ skip default.env*loading.--env-file <path>→ use only the explicit file(s).bunfig.tomlenv = false(orenv.file = false/null) → skip default.env*loading.bun --helpadvertises--env-fileand--no-env-fileas global flags, butbun install --helpdoesn't mention them and install silently ignores them — no error, no warning, no effect.What do you see instead?
Install always loads
.env.production,.env.local, and.envregardless of every documented knob. The matching code onmainis:Three hardcodes:
env_files: empty slice →--env-fileignored.suffix:.production→NODE_ENVignored. Also surfaced in Bun install - .env.development environment variables file is not recognised and defaults to .env.production or .env #12011.skip_default_env:false→--no-env-file/bunfig env = falseignored.The
Loader.load(...)API (src/dotenv/env_loader.zig:600) already accepts the right parameters. PR #24767 already addeddisable_default_env_filestoapi.TransformOptions(src/api/schema.zig) and the bunfig parser (src/bunfig.zig). The install path just never reads them.Additional information
Why this matters
Every dependency's
postinstallscript runs withprocess.envpopulated by the loaded.env*files. Anyone keeping app secrets in.env.productionand runningbun installin CI is silently handing those secrets to every transitivetrustedDependenciespostinstall — meaningfully worse than the runtime case PR #24767 already fixed, because postinstall is 3rd-party code.I have hit this on my own React Native / Expo app. I worked around it by renaming
.env.production→.env.prodso the loader's hardcoded match misses, but that's a name-collision workaround, not a fix.Suggested scope
Strictly mirror PR #24767's pattern for
install:ctx.args.env_filesandctx.args.disable_default_env_filesinto theenv.load(...)call atPackageManager.zig:794.--env-file/--no-env-fileonbun install's clap params if install uses its own parser (otherwise the global ones should flow through viactx.args).test/cli/install/no-env-file.test.tsmirroringtest/cli/run/no-envfile.test.ts.Happy to open the PR if maintainers are receptive. Would also like to know if there's appetite for a separate discussion on whether
bun installshould auto-load.env*at all by default — security argument above, but that's a default-behaviour change.Related
--no-env-filefor runtime + bundler. Did not touch install.--env-fileignored bybun install; suffix hardcoded to.production.NODE_ENV=production bun install≠bun install --production.