Securing ChatGPT and Codex with AiriaNewEnterprise
Route the ChatGPT app's Codex and Work surfaces and the Codex CLI through the Airia AI Gateway for DLP, guardrails, budgets, and audit, and govern the surfaces that can't be routed.
OpenAI ships more than one desktop app, and they do not behave the same way. The current ChatGPT app has three surfaces: Chat, Work, and Codex. Its Codex and Work surfaces can be pointed at your Airia AI Gateway, along with the Codex CLI and IDE extension, and once they are, agent turns, tool calls, and computer use all travel through Airia. Chat inside the app talks to chatgpt.com directly and has no endpoint setting, so you govern it the same way as chatgpt.com in a browser.
This guide covers which surface is which, how to route the ones that can be routed, what governance you get once they are, and how to cover the rest.
Start here: which app and surface
The app name doesn't tell you whether it routes. The bundle ID and the surface do.
| App or surface | Bundle ID | Routes through Airia? |
|---|---|---|
| ChatGPT app, Codex and Work surfaces | com.openai.codex | Yes. Agent turns, tool calls, computer use. |
| ChatGPT app, Chat surface | com.openai.codex | No. Talks to chatgpt.com directly. |
| ChatGPT Classic | com.openai.chat | No. No endpoint setting at any version. |
| ChatGPT Atlas | com.openai.atlas | No. Browser surface. |
| Codex CLI and IDE extension | not applicable | Yes. Same configuration file as the app. |
| chatgpt.com in a browser | not applicable | No. Web session, no endpoint to repoint. |
The app labeled simply ChatGPT is the Codex app that absorbed ChatGPT, which is why its bundle ID is com.openai.codex and why its Codex and Work surfaces read Codex's configuration file.
Users may have two or three of these icons in the Dock. Confirm which app a user actually opened before you treat their ChatGPT as covered. On macOS the bundle ID is visible in the app's Info.plist, and your MDM inventory reports it for every managed device, which is the practical way to see the split across a fleet.
1 · Route Codex through the AI Gateway
The ChatGPT app's Codex and Work surfaces, the Codex CLI, and the Codex IDE extension all read the same configuration file and honor a custom model provider. Point that provider at your Airia AI Gateway and every model call from those surfaces travels through Airia.
ChatGPT app (Codex · Work) · Codex CLI · IDE → Airia AI Gateway → OpenAI
↓ DLP · Guardrails · Agent constraints · Budgets · AuditA · Build the gateway
OpenAI_Dev_Tools.Choose where OpenAI models come from. This choice decides who pays for tokens:
| Model access choice | Who pays for tokens | What the client sends |
|---|---|---|
| Airia Model Library (shared Airia key) | Airia handles billing, charged to your Airia account | The user's gateway key |
| Bring Your Own Keys → OpenAI → Use Customer's Key | Your organization's OpenAI account | The user's gateway key |
| Bring Your Own Keys → OpenAI → OAuth Passthrough | Each user's own ChatGPT plan; your Airia balance is not charged | The user's ChatGPT sign-in, plus the gateway key in an x-airia-key header |
Choose OAuth Passthrough when your developers already sign in to Codex with their own ChatGPT plan and you want Airia governance on that traffic without a second API bill.
Full configuration reference: AI Gateway.
Two credentials, two jobs. The gateway key lives on the developer's machine and authenticates the user to Airia. The upstream credential (Airia's key, your organization's OpenAI key, or the user's own ChatGPT sign-in with OAuth Passthrough) authenticates the request to OpenAI, and that is what gets billed.
B · Point Codex at the gateway
Codex has no settings screen for this. The configuration file is the interface, and every Codex surface reads the same one:
| OS | Path |
|---|---|
| macOS and Linux | ~/.codex/config.toml |
| Windows | %USERPROFILE%\.codex\config.toml |
Set the CODEX_HOME environment variable to use a different directory.
Find your base URL. In Secure → Gateway → AI Gateway, click Gateway URL to copy your tenant's gateway endpoint, then append /openai/v1.
Let Airia write the file. On the gateway configuration, choose Integrate, then Automate Codex Setup to download a setup script for the user's operating system. The script adds the Airia provider to the user's existing config.toml and supplies the key for the model access choice you made. To write the file by hand instead, use the tab that matches that choice:
For Airia Model Library and Use Customer's Key. Codex reads the gateway key from an environment variable, so the secret stays out of config.toml:
model_provider = "airia"
[model_providers.airia]
name = "Airia Gateway"
base_url = "https://<your-gateway-url>/openai/v1"
wire_api = "responses"
env_key = "AIRIA_GATEWAY_KEY"Then set the variable to the user's gateway key. For the desktop app, add it to ~/.codex/.env as a plain-text file (named exactly .env, not .env.txt):
AIRIA_GATEWAY_KEY=agk-your-gateway-keyFor terminal and IDE use, also export it from the shell profile. Store only the key value; do not prepend Bearer.
A few details decide whether this works:
model_provideris a top-level key. Keep it above every[table]in the file, and keep exactly one. A second or misplacedmodel_providermakes the whole file invalid, and Codex silently ignores it.- Add to the file, don't replace it. It likely already holds marketplace, plugin, MCP, and project sections that the app wrote. The setup script merges for you.
wire_api = "responses"is required. Codex speaks the OpenAI Responses API, not Chat Completions.- Environment variables alone don't route. Codex does not redirect traffic based on
OPENAI_BASE_URL. Theconfig.tomlprovider is the routing path; the environment variable carries only the key.
The app reads this file at launch. After any edit, quit the app completely (⌘Q on macOS; closing the window is not enough), reopen it, and start a new Codex session. An app left running keeps sending to the old endpoint, which looks exactly like the configuration not working.
C · Confirm it is actually routing
Send one turn from each surface you care about, then open Gateway → Analytics → Gateway Monitoring. Every routed call appears with the user, the model, the token count, and a userAgent that tells you which surface produced it.
| What produced the call | userAgent |
|---|---|
| ChatGPT app, Codex and Work surfaces | Codex Desktop/<version> |
| ChatGPT app, computer use | codex-computer-use/<version> |
| Codex CLI in a terminal | codex-tui/<version> |
| Codex CLI in an editor or script | codex_exec/<version> |
Read the userAgent, not the app's version number. These apps update their internal runtime independently of the outer app, so the version the feed reports and the version the App Store shows will not always agree. The feed is the one that describes what actually made the call.
| Symptom | Likely cause | Fix |
|---|---|---|
Missing environment variable AIRIA_GATEWAY_KEY | .env is missing, misnamed (.env.txt), saved as rich text, or not loaded yet | Check that ~/.codex/.env exists and holds AIRIA_GATEWAY_KEY=…, then quit and reopen the app |
| 401 Unauthorized | The gateway key is wrong or prefixed with Bearer | Create a new key on the gateway's Access & Keys tab and store the bare value |
| 404 on every request | The base URL is wrong | Use your Gateway URL with /openai/v1 appended |
| Some requests fail while chat turns work | A background model isn't in Allowed Models | Add the app's current model family to the allowlist |
| Changes appear ignored | The app wasn't fully restarted, or model_provider is duplicated or below a table | Quit and reopen the app; check that model_provider appears once, at the top |
| Every turn fails with a policy violation | A guardrail on the gateway is blocking the request | Match the correlation ID the client prints to the feed row to confirm |
To roll back, remove the model_provider = "airia" line from config.toml (the [model_providers.airia] table can stay) and restart the app.
D · Push it to the fleet
A configuration file each developer edits by hand is a pilot, not a rollout. Two ways to make it stick:
Deploy config.toml through Jamf, Intune, or Kandji, using a placeholder for the gateway key and your MDM's per-user secret substitution so no long-lived credential is embedded in the profile. Deploy the file owned by the user, with restrictive permissions.
This is the floor, not the ceiling. A user with write access to their own home directory can edit the file back. Pair it with Codex's admin-enforced requirements.toml (see section 2), which users cannot override, and pin the Airia provider there so it stays selected.
2 · What you get once it's routed
Everything attached to that gateway configuration now applies to every routed Codex and Work session:
| Control | What it does to routed traffic |
|---|---|
| DLP policies | Inspect prompts and completions for PII, PCI, secrets, and your own detectors before the call leaves. |
| Guardrails | Block prompt injection, jailbreaks, and off-policy content inline. |
| Agent constraints | Block or audit specific tool calls the model tries to make. |
| Budgets | Cap spend per gateway and cut off runaway usage. |
| Model allowlist | Restrict which models can be selected, regardless of what the client offers. |
| Audit | Every request, user, model, and token count in one feed alongside your other AI traffic. |
Scope agent constraints to the Gateway. A constraint scoped to All Agents covers Airia pipeline traffic only. Codex traffic is gateway traffic, so the constraint has to be scoped to Gateway to see them.
A blocked call looks like a client error. When a guardrail stops a turn, the client reports a policy violation and the feed shows the request with zero tokens. The correlation ID the client prints matches the execution ID on the feed row, so you can tie the two together and confirm the block was yours before anyone starts debugging the client.
Lock down local behavior
The gateway sees model traffic. Codex's local actions (file edits, shell commands, sandbox mode) are governed by OpenAI's own admin enforcement: a requirements.toml file that users cannot override. Deploy it with your MDM, or manage the same settings from the Codex Policies page if you have ChatGPT Business or Enterprise.
| OS | Path |
|---|---|
| macOS and Linux | /etc/codex/requirements.toml |
| Windows | C:\ProgramData\OpenAI\Codex\requirements.toml |
A typical enterprise baseline:
- Pin the Airia provider. Set
model_provider = "airia"and the same[model_providers.airia]table you use inconfig.toml. The admin file takes precedence, so every Codex surface stays routed through the gateway. - Block the unsandboxed mode (
danger-full-access) so Codex always runs sandboxed. - Disallow the "never ask" approval policy so destructive actions always require review.
- Allowlist MCP servers to your Airia MCP Gateway entry so unsanctioned local tools can't be added.
- Deny known-dangerous commands, for example unencrypted
curl http://calls.
When a user's own configuration conflicts with the admin file, the most restrictive setting wins and Codex tells the user. See OpenAI's Codex documentation for the full requirements.toml reference.
3 · Govern the tool side with the MCP Gateway
Routing inference does not govern the tools the model calls. Point Codex at the Airia MCP Gateway and every downstream credential is managed centrally, behind one authenticated URL, instead of scattered across local configurations in plaintext.
On your MCP gateway, open Client Setup → ChatGPT & Codex for the steps for each client: the desktop app, the IDE extension, the Codex CLI (codex mcp add), or config.toml directly. All of them write the same Codex MCP configuration on the device, so connecting once covers every Codex surface. Users authenticate through OAuth on first connect.
Setup and credential management: MCP Gateway.
4 · Cover the surfaces that don't route
Four surfaces sit outside the gateway's reach. Cover each one with a different control.
| Surface | Why it can't be routed | What to do instead |
|---|---|---|
| Chat in the ChatGPT app | Talks to chatgpt.com directly and reads no local configuration. | Network policy or a SASE path, and steer users to the Codex and Work surfaces for sensitive work. |
| chatgpt.com in a browser | A web session, not an API call. There is no base URL to change. | Browser extension policy, or a SASE path. |
| ChatGPT Classic and Atlas | No base-URL setting at any version. | Browser extension for Atlas, network policy for both, or remove them from managed devices. |
| ChatGPT on iOS and Android | No base-URL setting, and no interception hook short of network inspection. | Mobile device policy and network controls. |
The browser and shadow-AI answer
The Airia Browser Extension is the control point for chatgpt.com. It is domain-scoped, offering Block, Warn, Monitor, or Redirect at the AI-service domain, with optional request-body capture so your DLP detectors can run against what was actually typed. Redirect is the useful one here: send chatgpt.com to your sanctioned Airia deployment instead, so people keep working on a governed surface.
Configure under Secure → Runtime Security → Browser Extension Policies, and force-install it through your MDM so users can't remove it. Deployment steps: Browser Extension MDM Deployment.
For traffic you can see on the network but not on the endpoint, chain your secure web gateway into an Airia AI Gateway rather than blocking it outright. The user keeps working and the call picks up your policies. See SASE Integration.
Close the direct path
The gateway enforces on the traffic it receives, so close the direct paths from managed devices at the firewall or SASE layer. Codex uses a different OpenAI endpoint depending on how the user signs in:
| Sign-in | Direct endpoint to block |
|---|---|
| OpenAI API key | api.openai.com |
| ChatGPT account | chatgpt.com/backend-api/codex (a path rule, so apply it on a SASE path with TLS inspection) |
Block both. A block on api.openai.com alone covers API-key use only. The gateway calls OpenAI from Airia's side, not from the device, so gateway-routed traffic, including OAuth Passthrough, keeps working with both blocks in place.
Recommended build
- One AI Gateway configuration for OpenAI, with your DLP policies, guardrails, agent constraints, and a budget attached.
- Per-user gateway keys, so the audit trail names people.
config.tomlpushed by MDM withrequirements.tomlalongside it, then the endpoint agent in enforce mode to make it stick.- Agent constraints scoped to Gateway.
- The MCP Gateway for the tool side, replacing local server entries.
- Browser extension policy on
chatgpt.com, force-installed. - Egress blocks on
api.openai.comandchatgpt.com/backend-api/codex. - A weekly look at the gateway feed. An active developer with no gateway traffic for a week is worth a follow-up to confirm their client still routes through the gateway.
For the Anthropic equivalent of this build, see Securing Claude with Airia.
Claude Inference Hooks
Evaluate every governed Claude prompt against your Airia guardrails before it reaches the model — and deny the ones that violate policy.
Monitoring Codex with Airia
Send OpenAI Codex CLI telemetry to Airia AI App Monitoring over OpenTelemetry to see Codex sessions, events, and usage metrics next to your Claude activity.