Codex CLI
Codex CLI is OpenAI’s agentic coding tool: it reads your repository, runs commands,
and applies patches in a loop. It talks to a model provider defined in
~/.codex/config.toml, which means putting it behind the firewall is a matter of
defining one more provider — the gateway — and selecting it. No proxy, no plugin.
wire_api. On the gateway, only the openai provider serves the
responses surface. You cannot point Codex at groq, openrouter, mistral or
any other provider through the firewall: those serve chat only, and the gateway
will answer 404 unsupported_api.Why put Codex CLI behind the firewall
- Your provider key never sits in the agent’s config.
config.tomlreferencesVULNETIX_API_KEY. Your OpenAI key stays in the KMS-encrypted BYOK vault and is decrypted just-in-time by the gateway, on the server side of the request. - Every prompt the agent sends is screened by your guardrails — and for an agent, “prompt” means far more than what you typed. The contents of every file it reads and the output of every command it runs are fed back into the conversation as tool results, and those go through your guardrails too.
- Provider and model policy is enforced centrally. Codex cannot silently switch to a model your organisation has not approved: the decision is made at the gateway, on every request, not in a local config file a developer can edit.
Quick start
vulnetix ai-firewall key set openai --from-env OPENAI_KEY
vulnetix ai-firewall install codex --model gpt-4o-mini
That writes a managed block into ~/.codex/config.toml. The --model you pass is
validated against your organisation’s policy before the file is touched, so you
cannot wire a model the gateway would refuse at request time.
vulnetix ai-firewall install codex --dry-run
--dry-run prints the exact file and the exact block it would write, and changes
nothing.
Then make sure your Vulnetix API key is in the environment Codex inherits — the config block refers to it by name, it does not contain it:
export VULNETIX_API_KEY=vlx_...
vulnetix ai-firewall install shell adds a managed block to your shell rc that
exports VULNETIX_API_KEY for you, so every client on the machine picks it up.Edit ~/.codex/config.toml and define the gateway as a model provider, then select
it at the root of the file:
model = "gpt-4o-mini"
model_provider = "vulnetix-openai"
[model_providers.vulnetix-openai]
name = "Vulnetix AI Firewall"
base_url = "https://guardrails.vulnetix.com/openai/{orgUuid}/v1"
wire_api = "responses"
env_key = "VULNETIX_API_KEY"
Four things to get right:
wire_api = "responses". Codex requires the Responses API.chatwill not work here.- The base URL does end in
/v1— this is the OpenAI shape. (Anthropic’s is the one that does not; see base URLs.) - The provider slug in the URL is
openai, because it is the only provider that servesresponses. env_key = "VULNETIX_API_KEY"names an environment variable. Codex reads the key from your environment at run time — the key itself is never written intoconfig.toml.
export VULNETIX_API_KEY=vlx_...
How it works
Codex CLI sends POST /v1/responses to
https://guardrails.vulnetix.com/openai/{orgUuid}/v1 — the gateway’s responses
surface. The gateway authenticates the Vulnetix API key to your organisation,
applies provider and model policy, runs your guardrails over every text segment in
the request, decrypts your OpenAI key from the vault, and forwards the call. Prompts
and completions are never logged.
No local proxy is required. Codex is talking to the gateway directly, over the same protocol it would use to talk to OpenAI, using a provider mechanism it already has.
Guardrails behave identically on responses as they do on chat and messages. A
rule you wrote for a curl covers a Codex turn without modification.
Verify
vulnetix ai-firewall status
Codex should show as wired:
clients
codex wired ~/.codex/config.toml
https://guardrails.vulnetix.com/openai/{orgUuid}/v1
points elsewhere means config.toml exists but names a different base_url — an
OpenAI endpoint, or another gateway. That client raises the bypasses_firewall
check, and it is the one to act on.
Limitations
Once wired, every model request Codex CLI makes goes through the firewall.
Codex has no built-in completion or background feature that uses a different
credential; the model_provider you selected is the one it uses.
Two honest caveats:
- The arguments the model generates for a tool call are not scanned. Prompt content and tool results are; the shell commands and patches the model emits as tool-call arguments are not.
- A developer can edit
config.toml. Switchingmodel_providerback to OpenAI’s own is a one-line change. The firewall is a control, not a cage —vulnetix ai-firewall statusand itsbypasses_firewallcheck exist so you can find that machine.
Common errors
401 — invalid Vulnetix API key
{
"error": {
"message": "invalid Vulnetix API key",
"type": "authentication_error",
"code": "invalid_api_key"
}
}
Two causes, and they look identical from the outside.
The first is the two-keys confusion: VULNETIX_API_KEY is holding an OpenAI key
(sk-…) instead of your Vulnetix API key. The gateway authenticates you with
the Vulnetix key and supplies the OpenAI key itself, from the vault. Your provider
key belongs in the vault, never in the agent.
The second is that VULNETIX_API_KEY is not set at all in the shell Codex was
launched from — env_key names the variable, so an unset variable means an empty
credential. The CLI catches this locally as the key_env_unset check.
Fix:
- Store your OpenAI key in the vault:
vulnetix ai-firewall key set openai --from-env OPENAI_KEY. export VULNETIX_API_KEY=vlx_...— or runvulnetix ai-firewall install shellso it is exported for every session.- Confirm with
vulnetix ai-firewall status: nokey_env_unsetcheck should remain. - Start a new terminal session, so Codex inherits the variable.
403 — provider_key_missing
{
"error": {
"message": "no OpenAI API key configured for your organisation: add one with 'vulnetix ai-firewall key set openai' or at https://www.vulnetix.com/vdb-ai-firewall#byok",
"type": "permission_error",
"code": "provider_key_missing"
}
}
You are authenticated, but your organisation has no OpenAI key in the vault, so the gateway has nothing to forward the request with.
Fix:
export OPENAI_KEY=sk-...vulnetix ai-firewall key set openai --from-env OPENAI_KEYvulnetix ai-firewall status— theopenairow should now show a stored key.
Note that vulnetix ai-firewall install codex would have refused to wire a provider
with no stored key in the first place. Seeing this error usually means the key was
removed after the config was written.
403 — model_not_allowed
{
"error": {
"message": "model gpt-4.5-preview is not in the organisation allowlist",
"type": "permission_error",
"code": "model_not_allowed"
}
}
Your organisation runs an allowlist for openai, and the model in config.toml
is not on it. (A model that is explicitly denied returns model_denied instead.)
Fix:
- Run
vulnetix ai-firewall getto see which models your policy permits. - Re-wire with an approved model:
vulnetix ai-firewall install codex --model gpt-4o-mini. The CLI validates the model against policy before writing, so this cannot leave you in the same state. - If the model should be allowed, an administrator adds it to the policy.
404 — unsupported_api
{
"error": {
"message": "provider groq does not support the OpenAI Responses API (POST /v1/responses). Use POST /v1/chat/completions for groq, or use the openai provider, which serves the Responses API: https://guardrails.vulnetix.com/openai/{orgUuid}/v1",
"type": "not_found_error",
"code": "unsupported_api"
}
}
You pointed Codex at a provider that does not serve the responses surface. Only
openai does. The CLI catches this class of mistake locally, before you send a
request, as the wire_unsupported check.
The same code also appears if the base URL is missing its /v1 suffix — the OpenAI
shape requires it, unlike Anthropic’s.
Fix:
- Open
~/.codex/config.toml. - Confirm
base_urlishttps://guardrails.vulnetix.com/openai/{orgUuid}/v1— the slugopenai, and with the trailing/v1. - Confirm
wire_api = "responses". - Re-run
vulnetix ai-firewall install codexto have the CLI write it correctly.