What happened
I ran /design-consultation from the root of one of my projects. The project has a .env file with an OPENAI_API_KEY used by the project's own runtime (an unrelated app). I never told gstack about that key. I expected it to use ~/.gstack/openai.json or my Codex auth.
After about 5 image generations (≈$0.50 in gpt-image-1 calls), I noticed the charges hit the project's OpenAI account, not the account I'd associated with gstack via codex login.
Root cause
design.exe is a Bun-compiled single-file executable. Bun's runtime auto-loads .env from the current working directory at process start. So whenever the design binary is spawned from a directory containing .env with OPENAI_API_KEY=..., that key wins over the documented auth chain (~/.gstack/openai.json → OPENAI_API_KEY → ~/.codex/auth.json) — because the env var is already populated by the time the auth resolver runs.
The tool's --help output advertises:
Auth: ~/.gstack/openai.json or OPENAI_API_KEY env var
But it doesn't say which one wins, and it doesn't say that "env var" includes silently auto-loaded .env files.
Why this matters
- Billing surprise. Image generation gets charged to whichever OpenAI account a project's
.env happens to be tied to — not the one the user set up gstack with. Easy to accumulate spend on the wrong account.
- Cross-project key leakage. Many projects keep
.env for local dev — internal tools, side projects, contractor work, client codebases. Running gstack inside a client project would pull the client's key. That's a real footgun.
- No visibility. The tool never tells the user which key it picked or which account will be billed. The user has to dig into Bun runtime semantics to figure out what just happened.
.env is typically gitignored as a secret. Tools that auto-load it should disclose that they're doing so.
Suggested fixes
In rough order of effort:
- Disclose key source on every run. Print one line:
using OpenAI key from <source> (e.g., ~/.gstack/openai.json, OPENAI_API_KEY env, .env in cwd, ~/.codex/auth.json). Even just the source label, not the key, would have prevented this.
- Don't auto-load
.env. Either disable Bun's .env auto-load (Bun.env vs process.env, or set --no-env-file if Bun supports it), or filter OPENAI_API_KEY out of the inherited env unless it came from ~/.gstack/openai.json / a deliberate gstack-owned source.
- Require explicit opt-in to use cwd
.env. A flag like --allow-env-file or a config like gstack_use_cwd_env.
- Add the disclosure to
--help. Make it explicit that any .env in the working directory at invocation time is read.
Happy to test a fix.
What happened
I ran
/design-consultationfrom the root of one of my projects. The project has a.envfile with anOPENAI_API_KEYused by the project's own runtime (an unrelated app). I never told gstack about that key. I expected it to use~/.gstack/openai.jsonor my Codex auth.After about 5 image generations (≈$0.50 in
gpt-image-1calls), I noticed the charges hit the project's OpenAI account, not the account I'd associated with gstack viacodex login.Root cause
design.exeis a Bun-compiled single-file executable. Bun's runtime auto-loads.envfrom the current working directory at process start. So whenever the design binary is spawned from a directory containing.envwithOPENAI_API_KEY=..., that key wins over the documented auth chain (~/.gstack/openai.json→OPENAI_API_KEY→~/.codex/auth.json) — because the env var is already populated by the time the auth resolver runs.The tool's
--helpoutput advertises:But it doesn't say which one wins, and it doesn't say that "env var" includes silently auto-loaded
.envfiles.Why this matters
.envhappens to be tied to — not the one the user set up gstack with. Easy to accumulate spend on the wrong account..envfor local dev — internal tools, side projects, contractor work, client codebases. Running gstack inside a client project would pull the client's key. That's a real footgun..envis typically gitignored as a secret. Tools that auto-load it should disclose that they're doing so.Suggested fixes
In rough order of effort:
using OpenAI key from <source>(e.g.,~/.gstack/openai.json,OPENAI_API_KEY env,.env in cwd,~/.codex/auth.json). Even just the source label, not the key, would have prevented this..env. Either disable Bun's.envauto-load (Bun.envvsprocess.env, or set--no-env-fileif Bun supports it), or filterOPENAI_API_KEYout of the inherited env unless it came from~/.gstack/openai.json/ a deliberate gstack-owned source..env. A flag like--allow-env-fileor a config likegstack_use_cwd_env.--help. Make it explicit that any.envin the working directory at invocation time is read.Happy to test a fix.