Skip to content

/codex and /autoplan shell out to codex with no auth-profile gate or consent prompt #965

@dgrant

Description

@dgrant

Problem

The /codex skill and /autoplan (plan-review phases) shell out to the codex CLI with no check for which account is currently authenticated in ~/.codex/. Whatever codex login was last run with is what gets used — silently, with no prompt.

Two things compound:

  1. codex/SKILL.md.tmpl:40-47 — the only pre-flight is which codex. No auth inspection, no per-project config, no CODEX_HOME awareness.
  2. autoplan/SKILL.md.tmpl:70 — "run codex" is classified as a mechanical decision ("one clearly right answer, auto-decide silently"). So during /autoplan, codex exec fires across multiple plan-review phases with zero user consent.

The net effect: if a user has more than one codex account (common — personal vs. employer-provided, separate orgs, compliance-isolated environments), gstack will happily use whichever one happens to be in ~/.codex/ against any repo, with no way for the user to approve or even know ahead of time.

Repro

  1. codex login as account A.
  2. cd into any repo — including ones where account A's credentials are the wrong choice.
  3. Run /autoplan (or /codex review).
  4. codex exec runs against account A. No prompt, no confirmation, no record of approval. The first the user knows is when they see the output (or a bill).

Expected

Before the first codex invocation in a project, gstack should prompt the user for which codex auth to use, remember the answer per-project, and route subsequent invocations through CODEX_HOME accordingly. /autoplan should not treat codex as a silent auto-yes decision.

Actual

  • codex/SKILL.md.tmpl:40-47 — binary-presence check only.
  • autoplan/SKILL.md.tmpl:70 — codex classified as mechanical auto-yes.
  • No per-project config, no CODEX_HOME plumbing anywhere in the codex-calling skills.

Suggested fix (minimal)

The codex CLI already supports CODEX_HOME as an env var pointing at an alternate auth/config directory. This makes isolation trivial — users can mv ~/.codex ~/.codex-work and CODEX_HOME=~/.codex-personal codex login to get two fully separate auth stores, and gstack just needs to pick which one to use per project.

Concretely:

  1. Per-project config file: ~/.gstack/projects/{slug}/codex.yaml with one field — codex_home: <path>.
  2. In codex/SKILL.md.tmpl Step 0: after the which codex check, read the config. If missing, AskUserQuestion listing the ~/.codex* directories found on the machine (glob), plus "Cancel." Save the chosen path to the config file. The prompt is the setup flow — no separate /setup-codex skill needed.
  3. Before every codex invocation in the skill (and in autoplan phases 1–4), export CODEX_HOME=<configured path>.
  4. In autoplan/SKILL.md.tmpl:70: delete "run codex (always yes)" from the mechanical examples. Codex invocation should go through the same per-project check as /codex itself.

Scope: ~20 lines of template changes, one config file, no new helper binary, no fingerprinting, no global flag. The same pattern likely applies to any other authenticated AI CLI gstack shells out to — worth a follow-up audit.

User-side mitigation available today

Users on affected machines can protect themselves immediately, before any fix ships:

mv ~/.codex ~/.codex-work
# ~/.codex/ no longer exists; any unprotected `codex` invocation now fails loudly
# instead of silently using the wrong auth.
CODEX_HOME=~/.codex-personal codex login   # set up personal auth separately

After this, /autoplan will fail at the binary-presence check rather than silently using the wrong account — a useful fail-safe while waiting for the proper fix.

Why this matters

Consent and credential isolation are separate issues, and gstack currently has neither for codex:

  • Consent: a user should know when their codex account is about to be billed and see what prompt is being sent.
  • Isolation: users with multiple codex accounts need a way to tell gstack which one is approved for which project.

Both are table-stakes for a tool that runs inside user repos and spends money on their behalf.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions