Skip to content
Betav0.70.1
All articles

Codex credential masking: placeholders in the shell, real keys at the proxy

Codex 0.164.0 extends credential masking to remote commands. How the design works, where it falls back to real credentials, and why it is not ready to rely on.

By The SpanDock team

4 min read

A diagram: a command in the sandbox sees only a placeholder credential, the local network proxy checks the destination and swaps in the real credential, and the upstream service receives the real one

An AI coding agent that runs shell commands usually runs them with the developer's environment, and that environment is full of credentials: API keys, cloud keys, tokens for code hosts. Anything the agent can run, it can also print, and anything it prints can end up in the model's context, a log or a prompt-injected request to somewhere it shouldn't go.

Codex, OpenAI's coding agent, has been building an answer to this: credential masking. Commands see placeholders instead of real credentials, and a local network proxy swaps the real values in only for requests to destinations that are allowed to receive them. The 0.164.0 release on 23 October 2026 extended it to remote Bash commands and Zsh snapshot sessions, including credentials from custom providers.

It is a design worth understanding, whatever agent you use. But it is not finished, and the release notes don't say so.

Not ready for external use yet

The release notes list masking among the new features. Codex's own feature registry (features/src/lib.rs) tells a different story: credential_masking is at the stage UnderDevelopment, which the code describes as "still under development, not ready for external use", and it is off by default. It does not appear in the /experimental menu, unlike the network proxy it depends on, which is marked experimental.

So treat what follows as a description of where Codex is heading, not as a control you can rely on today.

How it works

The pieces are spread across several pull requests and the network proxy README.

  1. It depends on the network proxy. Codex can run a local proxy that enforces an allow and deny list of domains for sandboxed commands. Pull request 52302 added the features.credential_masking flag, which turns on credential brokering through that proxy, only if the proxy is already enabled. If sandboxing or the proxy is off, masking stays inactive and Codex warns at startup.
  2. Commands get placeholders. Supported credentials in a command's environment, and in the protected shell snapshots that Codex uses to recreate the developer's shell, are replaced with dummy values.
  3. The proxy injects the real value. When a request leaves the sandbox for a matching destination, the proxy, which terminates HTTPS so that it can inspect requests, replaces the placeholder with the real credential. The model and the command only ever see the placeholder.
  4. AWS is a special case. AWS requests are signed with the secret key rather than carrying it, so swapping a header isn't enough. The README describes a placeholder access key that the AWS CLI or SDK signs with. The proxy recognises the placeholder, checks the host, method and path against its rules, and re-signs the request with the real key. Masked presigned URLs, SigV4a and AWS signed streams are denied.

Tightened on 21 October

Pull request 56003, included in 0.164.0, limits where real credentials can go. Substitution of a placeholder header happens only over HTTPS on port 443, and requires an exact whole-header placeholder: a missing, mismatched or duplicate value fails closed. Project-level configuration can no longer redefine trusted credential policies, secret files are limited to 64 KiB, and secrets can't be injected into User-Agent.

These options need network.mitm.version = 2 in the permissions profile. The README explains why: older clients reject that key, so rolling back to an older Codex cannot silently turn a scoped policy into unconditional header injection.

What 0.164.0 added: remote commands

Codex can run commands on a separate executor rather than the developer's machine. Pull request 54309 brings masking there: supported non-login Bash commands on Linux and macOS receive placeholders, the executor's own proxy injects real credentials, and the credentials and destination details stay on the executor. A later change added credentials from configured custom providers, which previously caused a fallback to unmasked execution.

Where it falls back to real credentials

The most important part of the design for anyone evaluating it is the fallback. The pull requests describe several cases where commands run with real, unmasked credentials and Codex emits a warning:

  • unsupported shells, and shell startup, for remote commands;
  • older executors that support only built-in providers, when custom providers are configured;
  • a protected shell snapshot that is disabled or fails to be created (pull request 55719). In that case the command still runs inside the filesystem sandbox and network policy, but with the real credentials.

That is a deliberate choice of availability over strictness: a broken snapshot shouldn't stop all work. But it means masking is a best-effort layer. A warning in a terminal is easy to miss, and an agent run in CI may have nobody watching it.

What to take from it

Whether or not you use Codex, the pattern is the right one. A few principles carry over:

  • Credentials an agent never sees can't leak from its context. Placeholders in the environment, with the real value added at the network edge, remove a whole class of mistakes and prompt-injection paths.
  • Bind each credential to its destination. The value of brokering comes from refusing to send a key anywhere but where it belongs. An unscoped substitution would be worse than none.
  • Fail visibly. If your own tooling falls back to real credentials, make that fallback something you can alert on, not only a message in a terminal.
  • Until then, give agents narrow credentials. Short-lived, scoped tokens for the repositories and services an agent needs remain the practical control while tools like this mature.

The same idea applies to model API keys. With SpanDock's model proxy, the provider keys are set on the server and stay there, in the operating system's credential store, while the tools on each computer authenticate only with a local proxy key that SpanDock sets up for them.

Sources

  1. openai/codex release 0.164.0
  2. openai/codex pull request 52302: Add opt-in credential masking for proxied sandboxed sessions
  3. openai/codex pull request 54309: Enable credential masking for remote exec-server commands
  4. openai/codex pull request 56003: Scope MITM credential substitution to trusted origins and placeholders
  5. codex-network-proxy README
  6. codex-rs/features/src/lib.rs: feature stages
Cookie categories

Details: Cookie Policy.