Shell snapshots can trigger credential prompts and persist secret env vars in plaintext

Open 💬 5 comments Opened Jul 3, 2026 by swlee3108-hash

Summary

Codex Desktop's local shell snapshot feature can source user shell startup files and then persist exported secret environment variables in plaintext under ~/.codex/shell_snapshots. In environments where .zshrc invokes a credential helper such as op read, starting or using Codex can also trigger unexpected biometric authentication prompts.

Environment

  • LazyCodex version: 4.12.1
  • Codex version: codex-cli 0.142.5, Codex Desktop 26.623.101652 (com.openai.codex, build 4674)
  • OS: macOS 26.3.1, arm64
  • Install method: Codex Desktop app plus bundled CLI
  • Relevant config: local shell snapshot feature is enabled by default in upstream Codex; zsh is the user shell; 1Password CLI version observed was 2.34.0

Repository Decision

  • Target repository: openai/codex
  • Why this belongs there: the behavior is implemented in upstream Codex core shell snapshot code and reproduces without LazyCodex-specific code paths.
  • LazyCodex evidence (runtime + /tmp/lazycodex-source): current LazyCodex checkout 44aa8c4; searching for OP_SERVICE_ACCOUNT_TOKEN, op-sa, /opt/homebrew/bin/op, op read, and shell_snapshot found no LazyCodex implementation that owns shell snapshot creation or 1Password invocation.
  • Upstream Codex source evidence from /tmp/openai-codex-source: current upstream checkout da4c8ca; codex-rs/features/src/lib.rs marks shell_snapshot stable and default-enabled; codex-rs/core/src/shell_snapshot.rs creates the files, sources zsh startup files, and captures exports; runtime execution then sources the snapshot before shell commands.

Reproduction

  1. On macOS with zsh, configure a shell startup file with an exported secret-like value, for example export CODEX_REPRO_SECRET=secret-value. To reproduce the biometric prompt variant, use a .zshrc line that invokes a credential helper such as op read ....
  2. Start Codex Desktop or run a local Codex shell command in a project using the default shell snapshot feature.
  3. Inspect ~/.codex/shell_snapshots/*.sh while the session is active, or observe shell snapshot behavior during command execution.

Expected Behavior

Codex should not run interactive credential helper commands from shell startup files in a way that surprises the user with biometric prompts. It also should not persist exported secrets such as API keys, access tokens, or service-account tokens in plaintext snapshot files or session artifacts.

Actual Behavior

The local run that triggered this report produced unexpected macOS 1Password biometric prompts while using Codex. Runtime investigation showed that direct op calls were reachable from the Codex shell environment and that shell snapshot artifacts had contained a 1Password service-account token matching the ops_... token shape before local redaction. After local cleanup, a broad scan for long ops_... token patterns across .codex, .claude, and the workspace returned zero matches.

Evidence

  • Runtime evidence: op initially resolved to /opt/homebrew/bin/op; local shell startup contained export OPENAI_API_KEY=$(op read ...), which explains the unexpected 1Password prompt when Codex starts or snapshots a shell. Guarding bare op and changing startup/scripts to op-sa stopped the prompt path.
  • Runtime evidence: after redaction, the local system still had shell snapshot files under ~/.codex/shell_snapshots, but no remaining long ops_... token patterns were found by a targeted scan.
  • Source evidence: codex-rs/features/src/lib.rs:831-835 defines Feature::ShellSnapshot with key shell_snapshot, stage Stable, and default_enabled: true.
  • Source evidence: codex-rs/core/src/shell_snapshot.rs:43-47 defines three-day retention and only excludes PWD and OLDPWD from exports.
  • Source evidence: codex-rs/core/src/shell_snapshot.rs:320-325 sources ~/.zshrc/$ZDOTDIR/.zshrc before writing a zsh snapshot, so startup commands such as credential helper reads can run during snapshot creation.
  • Source evidence: codex-rs/core/src/shell_snapshot.rs:340-357, 384-399, and 438-466 capture exported variables via export -p, declare -xp, or env and write them into the snapshot.
  • Source evidence: codex-rs/core/src/shell_snapshot.rs:219-222 writes the captured snapshot to disk.
  • Source evidence: codex-rs/core/src/tools/runtimes/mod.rs:281-318 rewrites shell commands to source the snapshot file before executing the requested command.
  • Source evidence: codex-rs/core/src/tools/runtimes/mod_tests.rs:1069-1110 includes a test proving secret override values are kept out of argv but still passed through the shell environment; there is no analogous redaction for snapshot file contents.

Root Cause

The confirmed root cause is that shell snapshot creation treats exported environment variables as ordinary replayable shell state. For zsh, the snapshot script first sources user startup config, then serializes exported variables to a plaintext .sh file. The export filter only excludes PWD and OLDPWD, so variables with common secret names such as OPENAI_API_KEY, OP_SERVICE_ACCOUNT_TOKEN, *_TOKEN, *_SECRET, *_PASSWORD, and credential-helper-derived exports can be persisted.

The biometric prompt symptom is a second-order effect of the same path: sourcing .zshrc during snapshot creation can execute interactive credential-helper commands such as op read, causing macOS/1Password authentication UI to appear even though the user only interacted with Codex.

Proposed Fix

  • Add a denylist/redaction layer for shell snapshot exports before writing files. At minimum redact or omit common secret-bearing names: *_TOKEN, *_SECRET, *_PASSWORD, *_KEY, OPENAI_API_KEY, OP_SERVICE_ACCOUNT_TOKEN, cloud-provider credential variables, and similar patterns.
  • Consider a positive allowlist for snapshot exports instead of serializing all exported environment variables.
  • Avoid sourcing full interactive startup files for snapshot creation, or provide an opt-out / non-interactive snapshot mode that cannot invoke credential helpers.
  • Store snapshots with restrictive permissions and avoid copying raw snapshot contents into session logs or rollout artifacts.
  • Add regression tests in codex-rs/core/src/shell_snapshot_tests.rs proving secret-like env vars are omitted/redacted for zsh/bash/sh snapshots and that snapshot generation does not require executing credential-helper startup hooks.

Verification Plan

  • Add tests that set OPENAI_API_KEY, OP_SERVICE_ACCOUNT_TOKEN, EXAMPLE_TOKEN, EXAMPLE_SECRET, and EXAMPLE_PASSWORD; verify generated snapshots do not contain their values.
  • Add a zsh snapshot test with a controlled startup file that would emit or invoke a sentinel command; verify the new non-interactive mode avoids the prompt-triggering path or makes the behavior opt-in.
  • Run existing shell snapshot tests and runtime shell execution tests for zsh/bash/sh to ensure PATH, aliases, functions, and expected non-secret exports still replay correctly.
  • Manually verify on macOS that Codex no longer triggers 1Password Touch ID prompts from .zshrc during startup/shell command execution.

---
This issue or PR was generated by LazyCodex.
Tag: lazycodex-generated

View original on GitHub ↗

This issue has 5 comments on GitHub. Read the full discussion on GitHub ↗