Shell snapshots can trigger credential prompts and persist secret env vars in plaintext
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 Desktop26.623.101652(com.openai.codex, build4674) - 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 checkout44aa8c4; searching forOP_SERVICE_ACCOUNT_TOKEN,op-sa,/opt/homebrew/bin/op,op read, andshell_snapshotfound no LazyCodex implementation that owns shell snapshot creation or 1Password invocation. - Upstream Codex source evidence from
/tmp/openai-codex-source: current upstream checkoutda4c8ca;codex-rs/features/src/lib.rsmarksshell_snapshotstable and default-enabled;codex-rs/core/src/shell_snapshot.rscreates the files, sources zsh startup files, and captures exports; runtime execution then sources the snapshot before shell commands.
Reproduction
- 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.zshrcline that invokes a credential helper such asop read .... - Start Codex Desktop or run a local Codex shell command in a project using the default shell snapshot feature.
- Inspect
~/.codex/shell_snapshots/*.shwhile 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:
opinitially resolved to/opt/homebrew/bin/op; local shell startup containedexport OPENAI_API_KEY=$(op read ...), which explains the unexpected 1Password prompt when Codex starts or snapshots a shell. Guarding bareopand changing startup/scripts toop-sastopped the prompt path. - Runtime evidence: after redaction, the local system still had shell snapshot files under
~/.codex/shell_snapshots, but no remaining longops_...token patterns were found by a targeted scan. - Source evidence:
codex-rs/features/src/lib.rs:831-835definesFeature::ShellSnapshotwith keyshell_snapshot, stageStable, anddefault_enabled: true. - Source evidence:
codex-rs/core/src/shell_snapshot.rs:43-47defines three-day retention and only excludesPWDandOLDPWDfrom exports. - Source evidence:
codex-rs/core/src/shell_snapshot.rs:320-325sources~/.zshrc/$ZDOTDIR/.zshrcbefore 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, and438-466capture exported variables viaexport -p,declare -xp, orenvand write them into the snapshot. - Source evidence:
codex-rs/core/src/shell_snapshot.rs:219-222writes the captured snapshot to disk. - Source evidence:
codex-rs/core/src/tools/runtimes/mod.rs:281-318rewrites shell commands to source the snapshot file before executing the requested command. - Source evidence:
codex-rs/core/src/tools/runtimes/mod_tests.rs:1069-1110includes 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.rsproving 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, andEXAMPLE_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
.zshrcduring startup/shell command execution.
---
This issue or PR was generated by LazyCodex.
Tag: lazycodex-generated
This issue has 5 comments on GitHub. Read the full discussion on GitHub ↗