From 0353c6c4745d255f99c7037d0a9a3f1057b71448 Mon Sep 17 00:00:00 2001 From: Burak Yigit Kaya Date: Tue, 21 Apr 2026 23:23:25 +0000 Subject: [PATCH] build: disable Bun autoload of .env and bunfig.toml in compiled CLI Without these flags, Bun silently loads `.env` / `.env.local` / `.env.production` and `bunfig.toml` from the user's CWD into `process.env` before any of our code runs. That's dangerous for a global CLI: - `SENTRY_AUTH_TOKEN` in a project's `.env.local` would override the stored OAuth token via `getRawEnvToken()` in `src/lib/db/auth.ts`. - `SENTRY_ORG` / `SENTRY_PROJECT` / `SENTRY_DSN` would pre-empt our DSN auto-detection flow in `src/lib/resolve-target.ts`. - Any other `SENTRY_*` var from `src/lib/env-registry.ts` (30+ of them) set in a project `.env` would leak into the CLI with no indication. Verified via strace: baseline binary opens `bunfig.toml` + `.env` before our code runs; patched binary does not. End-to-end: baseline picked up `SENTRY_ORG=injected-from-dotenv` from a hostile `.env` and queried it; patched correctly ignored it and fell through to auto-detect. Shell-level env vars continue to work unchanged. Users who want directory- scoped env vars should use `direnv` or source their `.env` explicitly. Also leaves a NOTE about `bytecode: true`: it would move JS parse cost from startup to build time, but as of Bun 1.3.11 it crashes our ESM bundle at runtime with "Expected CommonJS module to have a function wrapper" before any of our code runs (likely related to oven-sh/bun#21097 / #23490). Revisit once Bun's bytecode path stabilizes for our two-step esbuild-then-compile pipeline. --- script/build.ts | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/script/build.ts b/script/build.ts index fe6737ecf..c60fcb6a2 100644 --- a/script/build.ts +++ b/script/build.ts @@ -303,6 +303,17 @@ async function compileTarget(target: BuildTarget): Promise { | "bun-linux-arm64-musl" | "bun-windows-x64", outfile, + // Deterministic runtime: don't let a `.env` or `bunfig.toml` in the + // user's CWD silently inject configuration into the compiled CLI. + // Our env vars (SENTRY_AUTH_TOKEN, SENTRY_ORG, SENTRY_DSN, ...) are + // documented as shell-level; picking them up from a project-local + // `.env.local` is a footgun — e.g. a Next.js project's file could + // override the stored OAuth token via `getRawEnvToken()` in + // `src/lib/db/auth.ts`, or pre-empt DSN auto-detection in + // `src/lib/resolve-target.ts`. Users who want these vars set in a + // directory can use `direnv` or source their `.env` explicitly. + autoloadDotenv: false, + autoloadBunfig: false, }, // "linked" embeds a sourcemap in the binary. At runtime, Bun's engine // auto-resolves Error.stack positions through this embedded map back to @@ -312,6 +323,12 @@ async function compileTarget(target: BuildTarget): Promise { // Minify whitespace and syntax but NOT identifiers to avoid Bun's // identifier renaming collision bug (oven-sh/bun#14585). minify: { whitespace: true, syntax: true, identifiers: false }, + // NOTE: `bytecode: true` would move JS parse cost from startup to + // build time, but as of Bun 1.3.11 it crashes our ESM bundle at + // runtime with "Expected CommonJS module to have a function wrapper" + // before any of our code runs. Likely related to oven-sh/bun#21097 / + // #23490. Revisit once Bun's bytecode path stabilizes for our two- + // step esbuild-then-compile pipeline. }); if (!result.success) {