From a0fbae2ee2c83efcfe939e06b0f0bde4ba833c37 Mon Sep 17 00:00:00 2001 From: pfg Date: Thu, 16 Oct 2025 14:46:09 -0700 Subject: [PATCH] Add bunfig.toml flag to disable automatic .env file loading MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds a new `dotenv` boolean field to bunfig.toml that controls whether Bun automatically loads .env files at runtime. When set to false, .env file loading is disabled while process.env still works normally. This is useful for preventing accidental .env file loading in production environments or when using alternative environment variable management. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- docs/runtime/bunfig.md | 13 +++++++++++++ docs/runtime/env.md | 14 ++++++++++++++ src/api/schema.zig | 3 +++ src/bunfig.zig | 12 ++++++++++++ src/transpiler.zig | 11 +++++++++++ test/cli/run/env.test.ts | 42 ++++++++++++++++++++++++++++++++++++++++ 6 files changed, 95 insertions(+) diff --git a/docs/runtime/bunfig.md b/docs/runtime/bunfig.md index ca0a36f7eb..47fbebd4d4 100644 --- a/docs/runtime/bunfig.md +++ b/docs/runtime/bunfig.md @@ -109,6 +109,19 @@ The `telemetry` field permit to enable/disable the analytics records. Bun record telemetry = false ``` +### `dotenv` + +Control whether Bun automatically loads `.env` files. Default `true`. + +```toml +# Disable automatic .env file loading +dotenv = false +``` + +When set to `false`, Bun will not automatically load `.env`, `.env.local`, `.env.production`, `.env.development`, or `.env.test` files at runtime. Environment variables set in your shell or passed to the process will still be available via `process.env`. + +See [Runtime > Environment variables](/docs/runtime/env#disabling-automatic-env-file-loading) for more details. + ### `console` Configure console output behavior. diff --git a/docs/runtime/env.md b/docs/runtime/env.md index 78da1e94d1..6de165ddd5 100644 --- a/docs/runtime/env.md +++ b/docs/runtime/env.md @@ -69,6 +69,20 @@ $ bun --env-file=.env.1 src/index.ts $ bun --env-file=.env.abc --env-file=.env.def run build ``` +### Disabling automatic `.env` file loading + +You can disable Bun's automatic `.env` file loading by setting `dotenv = false` in your [`bunfig.toml`](/docs/runtime/bunfig) configuration file. + +```toml#bunfig.toml +dotenv = false +``` + +When disabled, Bun will not automatically load `.env`, `.env.local`, `.env.production`, `.env.development`, or `.env.test` files. However, environment variables set in your shell or passed to the process will still be available via `process.env`. + +{% callout %} +**Note:** When `dotenv = false`, you can still manually load specific `.env` files using the `--env-file` flag. +{% /callout %} + ### Quotation marks Bun supports double quotes, single quotes, and template literal backticks: diff --git a/src/api/schema.zig b/src/api/schema.zig index f4f70201b9..2022c025de 100644 --- a/src/api/schema.zig +++ b/src/api/schema.zig @@ -1734,6 +1734,9 @@ pub const api = struct { /// from --unhandled-rejections, default is 'bun' unhandled_rejections: ?UnhandledRejections = null, + /// from bunfig.toml dotenv field, disables .env file loading when true + disable_dotenv: bool = false, + bunfig_path: []const u8, pub fn decode(reader: anytype) anyerror!TransformOptions { diff --git a/src/bunfig.zig b/src/bunfig.zig index 2041454161..c326e15046 100644 --- a/src/bunfig.zig +++ b/src/bunfig.zig @@ -779,6 +779,18 @@ pub const Bunfig = struct { } } } + + if (json.get("dotenv")) |dotenv_expr| { + if (dotenv_expr.asBool()) |value| { + // When dotenv is set to false, disable .env loading + // When true or not set, keep the default behavior + if (!value) { + this.bunfig.disable_dotenv = true; + } + } else { + try this.addError(dotenv_expr.loc, "Expected boolean"); + } + } } if (json.getObject("serve")) |serve_obj2| { diff --git a/src/transpiler.zig b/src/transpiler.zig index 668ee1a978..f2cd2c1b0f 100644 --- a/src/transpiler.zig +++ b/src/transpiler.zig @@ -474,6 +474,17 @@ pub const Transpiler = struct { } pub fn runEnvLoader(this: *Transpiler, skip_default_env: bool) !void { + // Check if dotenv is disabled via bunfig.toml + if (this.options.transform_options.disable_dotenv) { + // Skip .env loading but still load from process.env + try this.env.loadProcess(); + if (this.env.isProduction()) { + this.options.setProduction(true); + this.resolver.opts.setProduction(true); + } + return; + } + switch (this.options.env.behavior) { .prefix, .load_all, .load_all_without_inlining => { // Step 1. Load the project root. diff --git a/test/cli/run/env.test.ts b/test/cli/run/env.test.ts index 295c0e0056..1a4fd2b2ce 100644 --- a/test/cli/run/env.test.ts +++ b/test/cli/run/env.test.ts @@ -857,3 +857,45 @@ LARGE3="${"c".repeat(3000)}" expect(stdout).toBe("4096"); }); }); + +describe("bunfig.toml dotenv flag", () => { + test("dotenv = false disables .env loading", () => { + const dir = tempDirWithFiles("bunfig-dotenv-disable", { + ".env": "FOO=from_env\n", + "bunfig.toml": "dotenv = false\n", + "index.ts": "console.log(process.env.FOO || 'undefined');", + }); + const { stdout } = bunRun(`${dir}/index.ts`); + expect(stdout).toBe("undefined"); + }); + + test("dotenv = false still allows process.env to work", () => { + const dir = tempDirWithFiles("bunfig-dotenv-disable-processenv", { + ".env": "FOO=from_env\n", + "bunfig.toml": "dotenv = false\n", + "index.ts": "console.log(process.env.BAR || 'undefined');", + }); + const { stdout } = bunRun(`${dir}/index.ts`, { BAR: "from_process" }); + expect(stdout).toBe("from_process"); + }); + + test("dotenv = true allows .env loading (explicit)", () => { + const dir = tempDirWithFiles("bunfig-dotenv-enable", { + ".env": "FOO=from_env\n", + "bunfig.toml": "dotenv = true\n", + "index.ts": "console.log(process.env.FOO);", + }); + const { stdout } = bunRun(`${dir}/index.ts`); + expect(stdout).toBe("from_env"); + }); + + test("without bunfig.toml dotenv field, .env loads by default", () => { + const dir = tempDirWithFiles("bunfig-dotenv-default", { + ".env": "FOO=from_env\n", + "bunfig.toml": "# no dotenv field\n", + "index.ts": "console.log(process.env.FOO);", + }); + const { stdout } = bunRun(`${dir}/index.ts`); + expect(stdout).toBe("from_env"); + }); +});