SpyBara
Go Premium

Documentation 2026-08-25 19:59 UTC to 2026-08-26 23:58 UTC

12 files changed +610 −35. View all changes and history on the product overview
2026
Mon 31 19:59 Sat 29 07:02 Fri 28 23:02 Thu 27 21:01 Wed 26 23:58 Tue 25 19:59 Mon 24 22:00 Fri 21 19:59 Thu 20 23:59 Wed 19 22:57 Tue 18 13:01 Mon 17 23:58 Sat 15 01:01 Fri 14 22:00 Thu 13 22:59 Wed 12 19:59 Tue 11 22:59 Mon 10 22:00 Sat 8 03:02 Fri 7 18:59 Thu 6 23:58 Wed 5 19:00 Tue 4 22:00 Mon 3 23:00 Sun 2 21:00

app-server.md +1 −1

Details

225- `mcpServerOpenaiFormElicitation` - allow downstream MCP servers to send the225- `mcpServerOpenaiFormElicitation` - allow downstream MCP servers to send the

226 OpenAI extended-form variant of `mcpServer/elicitation/request`.226 OpenAI extended-form variant of `mcpServer/elicitation/request`.

227 227 

228**Important**: Use `clientInfo.name` to identify your client for the OpenAI Compliance Logs Platform. If you are developing a new Codex integration intended for enterprise use, please contact OpenAI to get it added to a known clients list. For more context, see the [Codex logs reference](https://chatgpt.com/admin/api-reference#tag/Logs:-Codex).228**Important**: Use `clientInfo.name` to identify your client for the OpenAI Compliance Logs Platform. If you are developing a new Codex integration intended for enterprise use, please contact OpenAI to get it added to a known clients list. For more context, see the [Codex logs reference](https://chatgpt.com/public/admin/api-reference#tag/Codex).

229 229 

230Example (from the Codex VS Code extension):230Example (from the Codex VS Code extension):

231 231 

Details

496 description:496 description:

497 "Authentication fallback for an MCP HTTP server after configured bearer tokens and authorization headers. `oauth` (default) uses stored MCP OAuth credentials when available. `chatgpt` uses the current ChatGPT session for the trusted first-party ChatGPT origin, then falls back to stored OAuth. Both modes can connect without authentication if no credential source resolves.",497 "Authentication fallback for an MCP HTTP server after configured bearer tokens and authorization headers. `oauth` (default) uses stored MCP OAuth credentials when available. `chatgpt` uses the current ChatGPT session for the trusted first-party ChatGPT origin, then falls back to stored OAuth. Both modes can connect without authentication if no credential source resolves.",

498 },498 },

499 {

500 key: "mcp_servers.<id>.oauth.client_id",

501 type: "string",

502 description:

503 "Pre-registered OAuth client ID used for authorization and token exchange with this MCP server.",

504 },

505 {

506 key: "mcp_servers.<id>.oauth.callback_url",

507 type: "string",

508 description:

509 "Server-specific OAuth callback. Pre-registered clients reuse it when issuer identification is supported or the URL already ends in the server-specific callback ID. Otherwise, Codex uses the global or default callback with that ID appended. Clients without a pre-registered ID use this callback during client registration.",

510 },

511 {

512 key: "mcp_servers.<id>.oauth.callback_port",

513 type: "integer",

514 description:

515 "Fixed OAuth callback listener port for this MCP server. Overrides `mcp_oauth_callback_port`. For a direct loopback callback with an explicit URL port, configure the same listener port.",

516 },

499 {517 {

500 key: "mcp_servers.<id>.bearer_token_env_var",518 key: "mcp_servers.<id>.bearer_token_env_var",

501 type: "string",519 type: "string",


1407 key: "mcp_oauth_callback_port",1425 key: "mcp_oauth_callback_port",

1408 type: "integer",1426 type: "integer",

1409 description:1427 description:

1410 "Optional fixed port for the local HTTP callback server used during MCP OAuth login. When unset, Codex binds to an ephemeral port chosen by the OS.",1428 "Optional global fixed port for the local HTTP callback server used during MCP OAuth login. A server-specific `oauth.callback_port` takes precedence. When neither is set, Codex binds to an ephemeral port chosen by the OS.",

1411 },1429 },

1412 {1430 {

1413 key: "mcp_oauth_callback_url",1431 key: "mcp_oauth_callback_url",

1414 type: "string",1432 type: "string",

1415 description:1433 description:

1416 "Optional base callback URL override for MCP OAuth login (for example, a devbox ingress URL). Codex appends a server-specific callback ID before sending the final OAuth `redirect_uri`, so register the full derived URI with your provider. `mcp_oauth_callback_port` still controls the callback listener port.",1434 "Optional base callback URL for MCP OAuth login, such as a devbox ingress URL. Newly added pre-registered clients use this URL unchanged when the authorization server supports issuer identification; existing clients without a saved callback append a server-specific callback ID. Without issuer support, any pre-registered MCP server whose configured callback lacks the required ID falls back to this URL with the ID appended. Callback URL ports don't select the listener port.",

1417 },1435 },

1418 {1436 {

1419 key: "experimental_use_unified_exec_tool",1437 key: "experimental_use_unified_exec_tool",

Details

496 description:496 description:

497 "Authentication fallback for an MCP HTTP server after configured bearer tokens and authorization headers. `oauth` (default) uses stored MCP OAuth credentials when available. `chatgpt` uses the current ChatGPT session for the trusted first-party ChatGPT origin, then falls back to stored OAuth. Both modes can connect without authentication if no credential source resolves.",497 "Authentication fallback for an MCP HTTP server after configured bearer tokens and authorization headers. `oauth` (default) uses stored MCP OAuth credentials when available. `chatgpt` uses the current ChatGPT session for the trusted first-party ChatGPT origin, then falls back to stored OAuth. Both modes can connect without authentication if no credential source resolves.",

498 },498 },

499 {

500 key: "mcp_servers.<id>.oauth.client_id",

501 type: "string",

502 description:

503 "Pre-registered OAuth client ID used for authorization and token exchange with this MCP server.",

504 },

505 {

506 key: "mcp_servers.<id>.oauth.callback_url",

507 type: "string",

508 description:

509 "Server-specific OAuth callback. Pre-registered clients reuse it when issuer identification is supported or the URL already ends in the server-specific callback ID. Otherwise, Codex uses the global or default callback with that ID appended. Clients without a pre-registered ID use this callback during client registration.",

510 },

511 {

512 key: "mcp_servers.<id>.oauth.callback_port",

513 type: "integer",

514 description:

515 "Fixed OAuth callback listener port for this MCP server. Overrides `mcp_oauth_callback_port`. For a direct loopback callback with an explicit URL port, configure the same listener port.",

516 },

499 {517 {

500 key: "mcp_servers.<id>.bearer_token_env_var",518 key: "mcp_servers.<id>.bearer_token_env_var",

501 type: "string",519 type: "string",


1407 key: "mcp_oauth_callback_port",1425 key: "mcp_oauth_callback_port",

1408 type: "integer",1426 type: "integer",

1409 description:1427 description:

1410 "Optional fixed port for the local HTTP callback server used during MCP OAuth login. When unset, Codex binds to an ephemeral port chosen by the OS.",1428 "Optional global fixed port for the local HTTP callback server used during MCP OAuth login. A server-specific `oauth.callback_port` takes precedence. When neither is set, Codex binds to an ephemeral port chosen by the OS.",

1411 },1429 },

1412 {1430 {

1413 key: "mcp_oauth_callback_url",1431 key: "mcp_oauth_callback_url",

1414 type: "string",1432 type: "string",

1415 description:1433 description:

1416 "Optional base callback URL override for MCP OAuth login (for example, a devbox ingress URL). Codex appends a server-specific callback ID before sending the final OAuth `redirect_uri`, so register the full derived URI with your provider. `mcp_oauth_callback_port` still controls the callback listener port.",1434 "Optional base callback URL for MCP OAuth login, such as a devbox ingress URL. Newly added pre-registered clients use this URL unchanged when the authorization server supports issuer identification; existing clients without a saved callback append a server-specific callback ID. Without issuer support, any pre-registered MCP server whose configured callback lacks the required ID falls back to this URL with the ID appended. Callback URL ports don't select the listener port.",

1417 },1435 },

1418 {1436 {

1419 key: "experimental_use_unified_exec_tool",1437 key: "experimental_use_unified_exec_tool",

config-sample.md +33 −5

Details

225 225 

226mcp_oauth_credentials_store = "auto"226mcp_oauth_credentials_store = "auto"

227 227 

228# Optional fixed port for MCP OAuth callback: 1-65535. Default: unset.228# Optional global fixed port for MCP OAuth callback: 1-65535. Default: unset.

229 

230# A server-specific oauth.callback_port overrides this global listener port.

229 231 

230# mcp_oauth_callback_port = 4321232# mcp_oauth_callback_port = 4321

231 233 

232# Optional redirect URI override for MCP OAuth login (for example, remote devbox ingress).234# Optional callback URL override for MCP OAuth login (for example, remote devbox ingress).

235 

236# Newly added pre-registered clients use this URL unchanged when the authorization server

237 

238# advertises issuer support and provides a metadata issuer. Without issuer support,

239 

240# Codex appends a server-specific callback ID. Existing clients without a saved

241 

242# callback keep that suffix.

243 

244# Without issuer support, any pre-registered MCP server callback must already

245 

246# end in the correct callback ID. Otherwise, Codex ignores that callback and uses

233 247 

234# Codex appends a server-specific callback ID before OAuth login.248# this global URL (or its default) with the server-specific callback ID appended.

235 249 

236# Register the full derived URI with your provider, not just the base host or unsuffixed path.250# Malformed callback URLs and mismatched authorization response issuers fail.

237 251 

238# Custom callback paths are supported. `mcp_oauth_callback_port` still controls the listener port.252# If issuer support is advertised, missing metadata or response issuers also fail.

253 

254# Custom callback paths are supported. Callback URL ports don't select the

255 

256# listener port; configure oauth.callback_port or mcp_oauth_callback_port.

239 257 

240# mcp_oauth_callback_url = "https://devbox.example.internal/callback"258# mcp_oauth_callback_url = "https://devbox.example.internal/callback"

241 259 


845 863 

846# scopes = ["repo"] # optional OAuth scopes864# scopes = ["repo"] # optional OAuth scopes

847 865 

866# [mcp_servers.github.oauth]

867 

868# client_id = "my-pre-registered-client" # OAuth client registered with the provider

869 

870# callback_url = "http://127.0.0.1/callback" # saved registered callback for this client

871 

872# callback_port = 4321 # server-specific listener port; overrides the global setting

873 

874# For http://127.0.0.1:4321/callback, set callback_port = 4321 as well.

875 

848################################################################################876################################################################################

849 877 

850# Model Providers878# Model Providers

Details

5The Codex Analytics API provides aggregated Codex usage and activity metrics for5The Codex Analytics API provides aggregated Codex usage and activity metrics for

6a ChatGPT workspace.6a ChatGPT workspace.

7 7 

8The authenticated [Codex Analytics API reference](https://chatgpt.com/codex/cloud/settings/apireference)8The [Codex Analytics API reference](https://chatgpt.com/public/admin/api-reference#tag/Codex%20Enterprise%20Analytics)

9is the source of truth for current access requirements, routes, request and9is the source of truth for current access requirements, routes, request and

10response schemas, metrics, time semantics, and pagination.10response schemas, metrics, time semantics, and pagination.

11 11 


28authenticate with a Platform organization API key. The key's organization must28authenticate with a Platform organization API key. The key's organization must

29match the organization associated with the workspace.29match the organization associated with the workspace.

30 30 

31The authenticated reference owns current key provisioning, scope requirements,31The API reference owns current key provisioning, scope requirements,

32routes, schemas, fields, time semantics, and pagination behavior. This page32routes, schemas, fields, time semantics, and pagination behavior. This page

33doesn't duplicate that contract.33doesn't duplicate that contract.

34 34 

Details

6workflows that require auditable records. Use analytics, not compliance records,6workflows that require auditable records. Use analytics, not compliance records,

7to measure adoption and trends.7to measure adoption and trends.

8 8 

9The authenticated [Admin API reference](https://chatgpt.com/admin/api-reference)9The [Admin API reference](https://chatgpt.com/public/admin/api-reference)

10is the source of truth for current access requirements, event coverage, routes,10is the source of truth for current access requirements, event coverage, routes,

11schemas, filters, retention, and request behavior.11schemas, filters, retention, and request behavior.

12 12 


28 28 

29## Get started29## Get started

30 30 

311. Open the [Admin API reference](https://chatgpt.com/admin/api-reference) and311. Open the [Admin API reference](https://chatgpt.com/public/admin/api-reference) and

32 confirm that your administrator role can access the compliance resources32 confirm that your administrator role can access the compliance resources

33 you need.33 you need.

342. Use the append-only compliance log stream for ongoing collection. Check the342. Use the append-only compliance log stream for ongoing collection. Check the

35 authenticated reference for the currently supported resources and retrieval35 API reference for the currently supported resources and retrieval

36 patterns.36 patterns.

373. [Download log files](#download-logs) and test ingestion into a non-production373. [Download log files](#download-logs) and test ingestion into a non-production

38 security information and event management (SIEM) system or data lake.38 security information and event management (SIEM) system or data lake.


42 42 

43For example, a security team can stream immutable compliance events into its43For example, a security team can stream immutable compliance events into its

44SIEM for investigations, or route those events into an approved electronic44SIEM for investigations, or route those events into an approved electronic

45discovery workflow. Use the authenticated reference for the current routes and45discovery workflow. Use the API reference for the current routes and

46schemas rather than copying an endpoint contract from this guide.46schemas rather than copying an endpoint contract from this guide.

47 47 

48### Download logs48### Download logs


76## Confirm the administration boundaries76## Confirm the administration boundaries

77 77 

78Compliance coverage follows the ChatGPT workspace and the products represented78Compliance coverage follows the ChatGPT workspace and the products represented

79in the current authenticated reference. Platform API organization data follows79in the current API reference. Platform API organization data follows

80its own API data and administration controls.80its own API data and administration controls.

81 81 

82The authenticated reference owns the current routes, event coverage, schemas,82The API reference owns the current routes, event coverage, schemas,

83filters, retention behavior, permission requirements, and request mechanics.83filters, retention behavior, permission requirements, and request mechanics.

84This page doesn't duplicate that contract.84This page doesn't duplicate that contract.

85 85 

Details

23- Open [Workspace analytics](https://chatgpt.com/admin/usage) for interactive23- Open [Workspace analytics](https://chatgpt.com/admin/usage) for interactive

24 workspace reporting. The [Workspace analytics guide](https://help.openai.com/en/articles/10875114-workspace-analytics-for-chatgpt-enterprise-and-edu)24 workspace reporting. The [Workspace analytics guide](https://help.openai.com/en/articles/10875114-workspace-analytics-for-chatgpt-enterprise-and-edu)

25 describes the current roles and views.25 describes the current roles and views.

26- Open the authenticated [Codex Analytics API reference](https://chatgpt.com/codex/cloud/settings/apireference)26- Open the [Codex Analytics API reference](https://chatgpt.com/public/admin/api-reference#tag/Codex%20Enterprise%20Analytics)

27 when you need scheduled, programmatic reporting.27 when you need scheduled, programmatic reporting.

28- Open the authenticated [Admin API reference](https://chatgpt.com/admin/api-reference)28- Open the [Admin API reference](https://chatgpt.com/public/admin/api-reference)

29 and the [Compliance Platform guide](https://help.openai.com/en/articles/9261474-compliance-api-for-chatgpt-enterprise-edu-and-chatgpt-for-teachers)29 and the [Compliance Platform guide](https://help.openai.com/en/articles/9261474-compliance-api-for-chatgpt-enterprise-edu-and-chatgpt-for-teachers)

30 for audit and investigation integrations.30 for audit and investigation integrations.

31 31 


74appropriate for data warehouses, business intelligence systems, and internal74appropriate for data warehouses, business intelligence systems, and internal

75reporting that shouldn't depend on an interactive dashboard.75reporting that shouldn't depend on an interactive dashboard.

76 76 

77The authenticated API reference owns access requirements, routes, schemas,77The API reference owns access requirements, routes, schemas,

78fields, reporting windows, and pagination. See78fields, reporting windows, and pagination. See

79[Analytics API](https://learn.chatgpt.com/docs/enterprise/analytics-api) for the conceptual integration79[Analytics API](https://learn.chatgpt.com/docs/enterprise/analytics-api) for the conceptual integration

80boundary and the canonical reference link.80boundary and the canonical reference link.


91Use the Compliance API for security, legal, and governance workflows that need91Use the Compliance API for security, legal, and governance workflows that need

92auditable records. It's not an adoption or productivity dashboard.92auditable records. It's not an adoption or productivity dashboard.

93 93 

94The authenticated API reference owns event coverage, schemas, permissions,94The API reference owns event coverage, schemas, permissions,

95filters, retention, and request behavior. See95filters, retention, and request behavior. See

96[Compliance API](https://learn.chatgpt.com/docs/enterprise/compliance-api) for the conceptual96[Compliance API](https://learn.chatgpt.com/docs/enterprise/compliance-api) for the conceptual

97integration boundary and the canonical reference link.97integration boundary and the canonical reference link.

Details

97 97 

98If your workspace has access, use a ChatGPT Admin API key to manage accounts, tokens, and sharing. Read operations require `chatgpt.enterprise.service_account.read`; changes require `chatgpt.enterprise.service_account.write`. A service-account token can't authenticate Admin API requests.98If your workspace has access, use a ChatGPT Admin API key to manage accounts, tokens, and sharing. Read operations require `chatgpt.enterprise.service_account.read`; changes require `chatgpt.enterprise.service_account.write`. A service-account token can't authenticate Admin API requests.

99 99 

100Check the authenticated [Admin API reference](https://chatgpt.com/admin/api-reference) for available operations and current request paths.100Check the [Admin API reference](https://chatgpt.com/public/admin/api-reference) for available operations and current request paths.

101 101 

102### Accounts102### Accounts

103 103 


143- Revoke exposed tokens immediately and investigate the account's recent activity.143- Revoke exposed tokens immediately and investigate the account's recent activity.

144- Disable or delete unused accounts in the workspace or Admin API. Both actions revoke all active tokens. Disabled accounts can be re-enabled with new tokens; deletion can't be undone.144- Disable or delete unused accounts in the workspace or Admin API. Both actions revoke all active tokens. Disabled accounts can be re-enabled with new tokens; deletion can't be undone.

145 145 

146Runs are attributed to the service account. Available workspace analytics and audit records can also identify who created tokens or changed account settings. Confirm event coverage in the authenticated [Admin API reference](https://chatgpt.com/admin/api-reference).146Runs are attributed to the service account. Available workspace analytics and audit records can also identify who created tokens or changed account settings. Confirm event coverage in the [Admin API reference](https://chatgpt.com/public/admin/api-reference).

147 147 

148## Related docs148## Related docs

149 149 

Details

13## Choose a reporting surface13## Choose a reporting surface

14 14 

15| Surface | Use it for | Contract owner |15| Surface | Use it for | Contract owner |

16| --------------------------- | ------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------- |16| --------------------------- | ------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------- |

17| ChatGPT workspace analytics | Interactive, workspace-wide adoption and engagement reporting | [Workspace analytics Help Center guidance](https://help.openai.com/en/articles/10875114) |17| ChatGPT workspace analytics | Interactive, workspace-wide adoption and engagement reporting | [Workspace analytics Help Center guidance](https://help.openai.com/en/articles/10875114) |

18| Codex analytics | Interactive reporting focused on Codex adoption and activity | The authenticated [Codex analytics dashboard](https://admin.openai.com/analytics/codex) |18| Codex analytics | Interactive reporting focused on Codex adoption and activity | The authenticated [Codex analytics dashboard](https://admin.openai.com/analytics/codex) |

19| Analytics API | Programmatic, aggregated Codex reporting | The authenticated [Codex Analytics API reference](https://chatgpt.com/codex/cloud/settings/apireference) |19| Analytics API | Programmatic, aggregated Codex reporting | The [Codex Analytics API reference](https://chatgpt.com/public/admin/api-reference#tag/Codex%20Enterprise%20Analytics) |

20| Compliance API | Audit, security, legal, and investigation records | The authenticated [Admin API reference](https://chatgpt.com/admin/api-reference) |20| Compliance API | Audit, security, legal, and investigation records | The [Admin API reference](https://chatgpt.com/public/admin/api-reference) |

21 21 

22## Review ChatGPT workspace analytics22## Review ChatGPT workspace analytics

23 23 


40change independently of this page.40change independently of this page.

41 41 

42For automated reporting, use the [Analytics API](https://learn.chatgpt.com/docs/enterprise/analytics-api)42For automated reporting, use the [Analytics API](https://learn.chatgpt.com/docs/enterprise/analytics-api)

43and follow its authenticated reference. For auditable records, use the43and follow its API reference. For auditable records, use the

44[Compliance API](https://learn.chatgpt.com/docs/enterprise/compliance-api).44[Compliance API](https://learn.chatgpt.com/docs/enterprise/compliance-api).

45 45 

46## Interpret reporting data46## Interpret reporting data

mcp.md +119 −2

Details

186 `approve`. The `writes` mode prompts for tools that aren't marked read-only.186 `approve`. The `writes` mode prompts for tools that aren't marked read-only.

187- `tools.<tool>.approval_mode` (optional): Per-tool approval behavior override.187- `tools.<tool>.approval_mode` (optional): Per-tool approval behavior override.

188 188 

189If your OAuth provider requires a fixed callback port, set the top-level `mcp_oauth_callback_port` in `config.toml`. If unset, Codex binds to an ephemeral port.189#### OAuth client registration and callbacks

190 190 

191If your MCP OAuth flow must use a specific callback URL (for example, a remote Devbox ingress URL or a custom callback path), set `mcp_oauth_callback_url`. Codex uses this value as the base callback URL, then appends a server-specific callback ID to produce the OAuth `redirect_uri` it sends during login. Register the full derived `redirect_uri` with your OAuth provider, including the appended callback ID and any configured path, query, or port, rather than registering only the base host or path without that suffix. Local callback URLs (for example `localhost`) bind on the local interface; non-local callback URLs bind on `0.0.0.0` so the callback can reach the host.191When your authorization server requires a pre-registered OAuth client, provide

192its client ID when adding the MCP server:

193 

194```bash

195codex mcp add example --url https://mcp.example.com --oauth-client-id my-client

196```

197 

198Codex displays the complete callback URL to register with your provider:

199 

200```text

201OAuth callback URL: http://127.0.0.1/callback

202```

203 

204Codex saves the callback alongside the client ID in `config.toml` for later

205logins:

206 

207```toml

208[mcp_servers.example]

209url = "https://mcp.example.com"

210 

211[mcp_servers.example.oauth]

212client_id = "my-client"

213callback_url = "http://127.0.0.1/callback"

214```

215 

216Newly added pre-registered clients use a stable callback only when the

217authorization server advertises

218`authorization_response_iss_parameter_supported: true` and provides a metadata

219`issuer`. If issuer support isn't advertised, Codex appends a server-specific

220callback ID, such as `http://127.0.0.1/callback/XuuuHAzzHOni`. Existing clients

221without a saved callback continue using their callback-ID-specific redirect.

222 

223During login, callback selection depends on the OAuth configuration and

224authorization server metadata:

225 

226| OAuth configuration | Issuer support | Callback used |

227| ------------------------------------------------------------------ | ------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------- |

228| `callback_url` without `client_id` | Supported | The configured callback is used for client registration. |

229| `callback_url` without `client_id` | Unsupported | The configured callback is used for client registration with the server-specific callback ID appended. |

230| `client_id` and `callback_url` | Supported | The configured callback is reused; the authorization response must contain the matching `iss`. |

231| `client_id` and a `callback_url` ending in the correct callback ID | Unsupported | The configured callback is reused unchanged. |

232| `client_id` and a `callback_url` missing the correct callback ID | Unsupported | The configured callback is ignored. Codex uses `mcp_oauth_callback_url`, or `http://127.0.0.1/callback` when unset, with the callback ID appended. |

233| `client_id` without a configured `callback_url` | Supported or unsupported | Codex uses the global or default callback with the server-specific callback ID appended. |

234 

235The fallback doesn't modify the stored callback URL. Codex derives the callback

236ID from the MCP server URL, including its path and query string. The same

237selection rules apply to automatic and explicit login.

238 

239Set `mcp_oauth_callback_url` when you need a custom callback path or remote

240Devbox ingress URL. Newly added pre-registered clients use that URL unchanged

241when their provider supports issuer identification. Otherwise, they use the

242configured URL with the server-specific callback ID appended. Always register

243the exact callback displayed by `codex mcp add`.

244 

245For portless `http://127.0.0.1` callbacks, Codex omits the listener port from

246the URL it displays and stores, then inserts the active listener port during

247authorization. This substitution doesn't apply to `localhost`, IPv6 hosts,

248HTTPS URLs, or callbacks that already include a port. Authorization servers

249must accept variable loopback ports under

250[RFC 8252, Section 7.3](https://www.rfc-editor.org/rfc/rfc8252#section-7.3).

251 

252Set `mcp_oauth_callback_port` to choose a fixed global listener port, or set

253`mcp_servers.<server-name>.oauth.callback_port` to override it for one server.

254An explicit port in the callback URL doesn't configure the listener. For a

255direct loopback callback, use portless `http://127.0.0.1` or configure the same

256explicit port for both the callback URL and listener. A proxied callback can

257intentionally use an external URL port that differs from the local listener

258port. Local callback URLs bind to the local interface; non-local callback URLs

259bind to `0.0.0.0`.

260 

261Codex validates any returned `iss` before exchanging the authorization code. A

262mismatched `iss` always rejects the response. When issuer support is advertised,

263a missing `iss` also rejects it. Neither failure exchanges the code or falls

264back to another callback. A malformed callback URL or issuer support advertised

265without a metadata issuer also remains a hard failure. See

266[Authenticate users](https://developers.openai.com/plugins/build/auth).

192 267 

193If the MCP server advertises `scopes_supported`, Codex prefers those268If the MCP server advertises `scopes_supported`, Codex prefers those

194server-advertised scopes during OAuth login. Otherwise, Codex falls back to the269server-advertised scopes during OAuth login. Otherwise, Codex falls back to the


300approval_mode = "approve"375approval_mode = "approve"

301```376```

302 377 

378Plugin-provided HTTP MCP servers can also declare OAuth settings in `.mcp.json`.

379Plugin manifests use the camelCase field names `clientId`, `callbackUrl`, and

380`callbackPort`:

381 

382```json

383{

384 "mcpServers": {

385 "sample": {

386 "type": "http",

387 "url": "https://mcp.example.com/mcp",

388 "oauth": {

389 "clientId": "my-pre-registered-client",

390 "callbackUrl": "http://127.0.0.1/callback/registered"

391 }

392 }

393 }

394}

395```

396 

397Plugin-provided MCP servers follow the same callback-selection rules as other

398MCP servers. If a plugin provides a `clientId`, its provider doesn't support

399issuer-bound callbacks, and `callbackUrl` lacks the server-specific callback

400ID, Codex ignores that URL for the login and uses `mcp_oauth_callback_url`, or

401`http://127.0.0.1/callback` when unset, with the callback ID appended. The

402configured `callbackUrl` remains unchanged.

403 

404A plugin's `oauth.callbackPort` overrides the global

405`mcp_oauth_callback_port`; if neither is set, Codex chooses an ephemeral port.

406The port embedded in `callbackUrl` doesn't select the listener port. For a

407direct loopback callback with a fixed port, configure both values to match:

408 

409```json

410{

411 "callbackUrl": "http://127.0.0.1:4321/callback/registered",

412 "callbackPort": 4321

413}

414```

415 

416For remote ingress or another proxy, the callback URL port and local listener

417port can intentionally differ when the proxy forwards to the configured

418listener.

419 

303## Examples of useful MCP servers420## Examples of useful MCP servers

304 421 

305The list of MCP servers keeps growing. Here are a few common ones:422The list of MCP servers keeps growing. Here are a few common ones:

Details

173 173 

174## Add the GitLab CI/CD pipeline174## Add the GitLab CI/CD pipeline

175 175 

176For a production workflow with protected default-branch scans, opt-in scheduled

177deep scans, separate SARIF policy gating, and optional verified draft merge

178requests, use [Run Codex Security in GitLab

179CI/CD](https://learn.chatgpt.com/docs/security/cli/ci/gitlab).

180 

176GitLab can ingest181GitLab can ingest

177[SARIF 2.1.0 reports](https://docs.gitlab.com/ci/yaml/artifacts_reports/#artifactsreportssarif)182[SARIF 2.1.0 reports](https://docs.gitlab.com/ci/yaml/artifacts_reports/#artifactsreportssarif)

178on GitLab Ultimate 19.2 or later. Add a masked and hidden183on GitLab Ultimate 19.2 or later. Add a masked and hidden

179`CODEX_SECURITY_API_KEY` CI/CD variable before you run the pipeline.184`CODEX_SECURITY_API_KEY` CI/CD variable before you run the pipeline.

180 185 

181Add the `security` stage and Codex Security job to the root `.gitlab-ci.yml`.186The following minimal example adds a scan-only `security` job to the root

182Keep any existing stages and jobs in the file. The example scans merge-request187`.gitlab-ci.yml`. Keep any existing stages and jobs in the file. It scans

183changes by default. Set `CODEX_SECURITY_FULL_SCAN_DEFAULT_BRANCH` to `"true"`188merge-request changes by default. Set `CODEX_SECURITY_FULL_SCAN_DEFAULT_BRANCH`

184to also scan the complete default branch:189to `"true"` to also scan the complete default branch:

185 190 

186```yaml191```yaml

187variables:192variables:


218 --ignore-scripts \223 --ignore-scripts \

219 --no-audit \224 --no-audit \

220 --no-fund \225 --no-fund \

221 @openai/codex-security226 @openai/codex-security@0.1.20

222 export CODEX_SECURITY_BIN="$CODEX_SECURITY_CLI_DIR/node_modules/.bin/codex-security"227 export CODEX_SECURITY_BIN="$CODEX_SECURITY_CLI_DIR/node_modules/.bin/codex-security"

223 test -x "$CODEX_SECURITY_BIN"228 test -x "$CODEX_SECURITY_BIN"

224 "$CODEX_SECURITY_BIN" --version229 "$CODEX_SECURITY_BIN" --version


324GitLab makes it available only for same-project merge requests between329GitLab makes it available only for same-project merge requests between

325protected branches and only when the user can access the target branch.330protected branches and only when the user can access the target branch.

326 331 

332The dedicated GitLab guide expands this minimal job into the production

333workflow linked at the start of this section.

334 

327## Choose a severity policy335## Choose a severity policy

328 336 

329Both examples are report-only because they omit `--fail-on-severity`. Once you337Both examples are report-only because they omit `--fail-on-severity`. Once you

security/cli/ci/gitlab.md +386 −0 created

Details

1# Run Codex Security in GitLab CI/CD

2 

3> For the complete documentation index, see [llms.txt](https://learn.chatgpt.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to the page URL.

4 

5Run Codex Security in GitLab CI/CD to scan committed changes and protected

6branches, publish findings to GitLab Security, and optionally propose verified

7fixes in draft merge requests.

8 

9The workflow keeps scan credentials separate from repository-write access.

10Generated changes always require human review before merge.

11 

12Start with scan-only reporting. Enable remediation only after you check the

13runner, findings, and credential boundaries for your project.

14 

15## Before you begin

16 

17You need:

18 

19- A GitLab project with a trusted runner that supports the Codex sandbox's

20 user namespace.

21- The Maintainer or Owner role in the GitLab project so you can configure

22 [project CI/CD variables](https://docs.gitlab.com/ci/variables/) and protected

23 resources.

24- An OpenAI API key with Codex Security access. Organizations using Platform

25 API keys can [request Trusted Access for

26 Cyber](https://openai.com/form/enterprise-trusted-access-for-cyber/).

27 Individuals using ChatGPT authentication can use the [personal Trusted Access

28 flow](https://chatgpt.com/cyber). Some accounts or repositories require this

29 access for full-repository scans.

30- GitLab Ultimate 19.2 or later for [SARIF 2.1.0

31 ingestion](https://docs.gitlab.com/user/application_security/detect/sarif/).

32- Full Git history so merge request jobs can calculate the merge base.

33 

34The pipeline image installs Node.js 26, Python 3, Git, `rg`, and the pinned

35Codex Security CLI. Automated remediation additionally requires an existing

36regression test and a runner that can run repository-controlled commands

37without protected credentials.

38 

39## Start with a scan-only pipeline

40 

41Create a masked, hidden, protected GitLab CI/CD variable named

42`CODEX_SECURITY_API_KEY`. Use an OpenAI Platform API key with Codex Security

43access, and set its environment scope to `codex-security/openai`. See

44[environment-scoped CI/CD variables](https://docs.gitlab.com/ci/environments/#limit-the-environment-scope-of-a-cicd-variable).

45 

46Add this minimal pipeline to a test project first. It scans committed changes

47in eligible protected merge requests, publishes SARIF from a successful report

48job, and restores the scanner result in a separate gate:

49 

50```yaml

51stages:

52 - security_scan

53 - security_gate

54 

55.codex-security-merge-request:

56 rules:

57 - if: '$CI_PIPELINE_SOURCE == "merge_request_event" && $CI_MERGE_REQUEST_SOURCE_PROJECT_ID == $CI_PROJECT_ID && $CI_MERGE_REQUEST_SOURCE_BRANCH_PROTECTED == "true" && $CI_MERGE_REQUEST_TARGET_BRANCH_PROTECTED == "true"'

58 

59codex-security:

60 extends: .codex-security-merge-request

61 stage: security_scan

62 image: node:26-bookworm-slim

63 environment:

64 name: codex-security/openai

65 action: access

66 variables:

67 GIT_DEPTH: "0"

68 before_script:

69 - npm install --prefix /tmp/codex-security-cli --ignore-scripts --no-audit --no-fund @openai/codex-security@0.1.20

70 script:

71 - |

72 set -eu

73 test -n "${CODEX_SECURITY_API_KEY:-}"

74 

75 CODEX_SECURITY_BIN="/tmp/codex-security-cli/node_modules/.bin/codex-security"

76 RESULTS_DIR="/tmp/codex-security-results-$CI_JOB_ID"

77 ARTIFACT_DIR="codex-security-artifacts"

78 BASE_REVISION="$(git merge-base \

79 "$CI_MERGE_REQUEST_DIFF_BASE_SHA" "$CI_COMMIT_SHA")"

80 install -d -m 700 "$RESULTS_DIR" "$ARTIFACT_DIR/results"

81 

82 codex_security_api_key="$CODEX_SECURITY_API_KEY"

83 unset CODEX_SECURITY_API_KEY

84 set +e

85 OPENAI_API_KEY="$codex_security_api_key" \

86 "$CODEX_SECURITY_BIN" scan . \

87 --diff "$BASE_REVISION" \

88 --head "$CI_COMMIT_SHA" \

89 --auth api-key \

90 --output-dir "$RESULTS_DIR" \

91 --json

92 scan_exit="$?"

93 set -e

94 unset codex_security_api_key

95 

96 case "$scan_exit" in

97 0|1|2) ;;

98 *) exit "$scan_exit" ;;

99 esac

100 

101 "$CODEX_SECURITY_BIN" export "$RESULTS_DIR" \

102 --export-format sarif \

103 --source-root "$CI_PROJECT_DIR" \

104 --output "$ARTIFACT_DIR/results.sarif"

105 test -s "$ARTIFACT_DIR/results.sarif"

106 cp -R "$RESULTS_DIR"/. "$ARTIFACT_DIR/results/"

107 printf '%s\n' "$scan_exit" > "$ARTIFACT_DIR/scan-exit-code.txt"

108 exit 0

109 artifacts:

110 when: always

111 access: maintainer

112 expire_in: 7 days

113 paths:

114 - codex-security-artifacts/

115 reports:

116 sarif: codex-security-artifacts/results.sarif

117 

118codex-security-gate:

119 extends: .codex-security-merge-request

120 stage: security_gate

121 image: alpine:3.20

122 needs:

123 - job: codex-security

124 artifacts: true

125 script:

126 - exit "$(cat codex-security-artifacts/scan-exit-code.txt)"

127```

128 

129 

130 

131> Illustration: GitLab pipeline scans a committed diff, publishes a SARIF report, and restores the scan result in a policy gate

132 

133 

134 

135Review every change to `.gitlab-ci.yml` before running a secret-bearing job.

136The minimal example intentionally omits full scans and remediation.

137 

138## Adopt the production pipeline

139 

1401. [Download the complete GitLab pipeline](https://learn.chatgpt.com/docs/security/cli/ci/gitlab.yml)

141 and save it as `.gitlab-ci.yml` in the repository root. If your repository

142 already has a pipeline, merge the example's stages, hidden templates, and

143 jobs into the existing file.

1442. Preserve existing build, test, and deployment stages. If the project uses

145 `workflow: rules`, confirm that it allows the pipeline events you want to

146 scan.

147 

148The example adds `security_scan`, `security_remediation`, `security_publish`,

149and `security_gate` stages. Scan-only reporting requires only

150`CODEX_SECURITY_API_KEY`.

151 

152The scan job runs by default only for same-project merge requests between

153protected branches. Set `CODEX_SECURITY_FULL_SCAN_DEFAULT_BRANCH=true` to scan

154protected default-branch pushes and manual pipelines. Set

155`CODEX_SECURITY_SCHEDULED_DEEP_SCAN=true` and configure explicit time and cost

156budgets to enable scheduled deep scans on the protected default branch.

157 

158A merge request pipeline can access protected variables and runners only when:

159 

160- You protect the source and target branches in the same project.

161- The project [permits merge request pipelines to access protected variables and

162 runners](https://docs.gitlab.com/ci/pipelines/merge_request_pipelines/#control-access-to-protected-variables-and-runners).

163- The user who starts the pipeline can push or merge into the target branch.

164 

165Fork pipelines and unprotected merge requests don't receive the scan

166credential. Review every change to `.gitlab-ci.yml` before running a

167secret-bearing job. Masking and hiding a variable do not make untrusted CI code

168safe.

169 

170## Run a scan and review findings

171 

172Create an eligible protected merge request or run the pipeline on the

173protected default branch. Start with a small diff before running a paid

174full-repository scan.

175 

176Open the `codex-security` job and confirm that its artifacts include:

177 

178- `scan-manifest.json`

179- `findings.json`

180- `coverage.json`

181- `results.sarif`

182- `scan-exit-code.txt`

183 

184Then open the pipeline **Security** tab, review ingestion warnings, and confirm

185finding identifiers, severity levels, and source locations. Default-branch scans

186also create project vulnerability records. Merge request findings appear in

187the pipeline Security tab or merge request security widget but don't create

188project-wide vulnerability records.

189 

190Restrict artifact access because scan results can contain vulnerable source

191snippets, evidence, and remediation details.

192 

193## Choose a scan profile

194 

195The pipeline selects a profile from the trigger:

196 

197| Trigger | Target | Mode | Effort |

198| ---------------------------------------------- | --------------- | ---------- | ------- |

199| Protected same-project merge request | Committed diff | `standard` | `low` |

200| Opt-in protected default-branch push or manual | Full repository | `standard` | `high` |

201| Opt-in schedule on protected default branch | Full repository | `deep` | `xhigh` |

202 

203Merge request scans focus feedback on the committed change.

204Default-branch scans review the integrated repository. Scheduled deep scans

205provide broader periodic coverage. A completed diff scan applies only to that

206change and does not show that the entire repository is clean.

207 

208The workflow installs the CLI outside the repository and runs it by absolute

209path. Its dry-run preflight uses the process-scoped API key but does not start a

210paid scan or verify API authentication, Codex Security access, quota, or model

211availability.

212 

213The workflow writes scan state and results outside the worktree and scopes

214`OPENAI_API_KEY` to the scan process. The CLI receives a small, explicit

215environment instead of inheriting every GitLab variable. For diff scans, the

216workflow calculates the merge base and binds the scan to the reviewed base and

217head revisions.

218 

219The example pins `@openai/codex-security` to `0.1.20`. Retest authentication,

220artifacts, SARIF ingestion, and policy gating before changing the pin.

221 

222## Separate reporting from policy enforcement

223 

224GitLab ingests SARIF from a successful report job. The pipeline publishes the

225report first and restores the scanner's exit status in a separate

226`codex-security-gate` job.

227 

228The report job accepts findings from exit codes `0` and `1`. It accepts exit

229code `2` only when the scan manifest proves the scan completed, coverage is

230explicitly `partial`, and a non-empty SARIF report exists. Other runtime,

231configuration, or export failures remain blocking.

232 

233The final gate preserves these scanner exit codes:

234 

235| Exit | Meaning |

236| ---- | --------------------------------------------------------------------------- |

237| `0` | The scan completed with complete coverage and passed its policy. |

238| `1` | The scan completed and found an issue at or above the configured threshold. |

239| `2` | The scan had incomplete coverage or an input or runtime error. |

240 

241The example temporarily allows exit `2` while you calibrate partial coverage.

242Remove that allowance when incomplete coverage must block the pipeline.

243 

244Remediation and publishing run before the final policy gate. An eligible

245finding can produce a verified draft merge request even when the gate later

246fails the pipeline.

247 

248## Enable verified remediation

249 

250Automated remediation is optional and runs only for protected default-branch

251pipelines. The Codex remediation process and repository-controlled verification

252commands do not receive the GitLab project access token or runner-injected

253credentials.

254 

255The security contract has three parts: repository-controlled commands never

256receive OpenAI or GitLab credentials, only the publishing job receives

257repository-write access, and every generated change stays a draft until a

258human reviews and merges it.

259 

260The workflow:

261 

2621. Requires complete scan coverage and a `high`- or `critical`-severity

263 finding.

2642. Confirms that the configured regression test fails before patching.

2653. Generates a focused patch and rejects changes to CI, credential, binary, or

266 other protected files.

2674. Runs the regression test without OpenAI, GitLab, registry, deployment, or

268 job-token credentials.

2695. Uses `verify-fix` to return `fixed`, `still_vulnerable`, or `inconclusive`.

270 The job publishes a patch only when `verify-fix` returns `fixed` and the

271 verification process leaves the patch unchanged.

272 

273Set these protected variables to enable remediation:

274 

275- Set `CODEX_SECURITY_ENABLE_REMEDIATION` to `true`.

276- Set `CODEX_SECURITY_VERIFICATION_COMMAND` to an existing regression test that

277 exits `1` before the fix and `0` afterward.

278- Optionally, set `CODEX_SECURITY_SETUP_COMMAND` to a non-interactive dependency

279 setup command.

280 

281Choose a regression test that exercises the underlying security invariant, not

282a particular implementation. Apply the same scrutiny to generated test and

283source changes.

284 

285<details>

286 <summary>Advanced: repository command isolation</summary>

287 

288The `validate`, `patch`, and `verify-fix` commands receive a process-scoped

289`CODEX_API_KEY`. Repository-controlled setup and test commands run as a

290separate unprivileged user in a writable copy of the tracked source files.

291The copy intentionally excludes Git metadata, submodule contents, and

292downloaded artifacts. Setup and test commands that require `.git` or

293submodules must run in a separately designed credential-free job.

294 

295Only the root-owned Codex steps can access the canonical checkout or GitLab's

296adjacent file-variable directory. The copy's clean environment contains only

297`PATH`, `HOME`, `LANG`, `CI`, and `CI_PROJECT_DIR`. If a command needs another

298non-secret value, add it to the allowlist after reviewing the command. If your

299runner cannot change users, move verification into a separate credential-free

300job before enabling remediation.

301 

302</details>

303 

304## Publish a draft merge request

305 

306Create a [GitLab project access

307token](https://docs.gitlab.com/user/project/settings/project_access_tokens/#create-a-project-access-token)

308with the Developer role and the `api` and `write_repository` scopes. Store it as

309a protected, masked, hidden `GITLAB_REMEDIATION_TOKEN` scoped only to the

310`codex-security/publish` environment.

311 

312Set `CODEX_SECURITY_CREATE_MR=true` to enable publishing. Also set the non-secret

313`CODEX_SECURITY_MR_TEST_COMMAND` to the project-specific security regression

314test that every generated remediation branch must pass. Keep this variable

315unprotected so the generated unprotected merge request can read the command.

316The publishing workflow:

317 

318- Receives the repository-write token but no OpenAI credential.

319- Creates a `codex-security/fix-<finding-hash>` branch.

320- Opens a draft merge request and reuses an existing open draft instead of

321 creating a duplicate.

322- Runs the unprotected remediation branch's regression test as an unprivileged

323 user in a tracked-only copy without protected credentials.

324- Never merges the generated change automatically.

325 

326Don't substitute `CI_JOB_TOKEN` for the project access token. It cannot perform

327the required merge request creation operation. Review the proposed patch,

328verification evidence, and finding before merging.

329 

330## Configure optional variables

331 

332Configure only the variables needed for the features you enable:

333 

334| Variable | When needed | Default or purpose |

335| ----------------------------------------- | --------------------------------- | ----------------------------------------------------------- |

336| `CODEX_SECURITY_API_KEY` | Every scan | Protected, masked, hidden; scope to `codex-security/openai` |

337| `CODEX_SECURITY_VERSION` | CLI upgrade | Pinned to `0.1.20`; retest before changing |

338| `CODEX_SECURITY_FULL_SCAN_DEFAULT_BRANCH` | Default-branch full scans | Explicit opt-in; off by default |

339| `CODEX_SECURITY_SCHEDULED_DEEP_SCAN` | Scheduled deep scans | Explicit opt-in; off by default |

340| `CODEX_SECURITY_DEEP_MAX_TIME_HOURS` | Scheduled deep scans | Required time budget greater than `0` and less than `8` |

341| `CODEX_SECURITY_DEEP_MAX_COST` | Scheduled deep scans | Required estimated USD cost guardrail greater than `0` |

342| `CODEX_SECURITY_ENABLE_REMEDIATION` | Patch generation | Protected opt-in; off by default |

343| `CODEX_SECURITY_VERIFICATION_COMMAND` | Patch generation | Protected regression test |

344| `CODEX_SECURITY_SETUP_COMMAND` | Optional remediation setup | Protected dependency installation |

345| `CODEX_SECURITY_REMEDIATION_EFFORT` | Optional remediation tuning | `high` |

346| `CODEX_SECURITY_MAX_CHANGED_FILES` | Optional patch-size limit | `8`; allowed range `1` through `20` |

347| `CODEX_SECURITY_CREATE_MR` | Draft merge request creation | Protected opt-in; off by default |

348| `GITLAB_REMEDIATION_TOKEN` | Draft merge request creation | Developer project token scoped to `codex-security/publish` |

349| `CODEX_SECURITY_GITLAB_INTERNAL_URL` | Optional self-hosted publishing | GitLab origin reachable from the runner |

350| `CODEX_SECURITY_MR_TEST_COMMAND` | Draft merge request publishing | Required non-secret, project-specific regression test |

351| `CODEX_SECURITY_MR_SETUP_COMMAND` | Optional remediation branch setup | Non-secret dependency setup |

352 

353GitLab supplies the `CI_*` variables. The pipeline manages

354`CODEX_SECURITY_BIN`, `CODEX_SECURITY_EFFORT`, `CODEX_SECURITY_MODE`,

355`CODEX_SECURITY_STATE_DIR`, and `CODEX_SECURITY_TARGET`; don't configure them

356as project variables. For diff scans, the CLI derives the canonical target

357identity from the normalized base and head revisions.

358 

359## Tune enforcement and cost

360 

361Use focused diff scans for merge request feedback, standard repository scans

362for the default branch, and scheduled deep scans for broader coverage. Both

363full-repository profiles are off by default. A scheduled deep scan also requires

364`CODEX_SECURITY_DEEP_MAX_TIME_HOURS` and `CODEX_SECURITY_DEEP_MAX_COST`; keep the

365CLI time budget below the job's eight-hour timeout. Measure representative runs

366before setting a budget. Treat `--max-cost` as an estimated cost guardrail, not

367a hard billing cap.

368 

369Start with report-only scans. Add `--fail-on-severity` after your team has

370reviewed representative findings, coverage, cost, and runtime. See [Run Codex

371Security in CI](https://learn.chatgpt.com/docs/security/cli/ci) for severity policies and exit-code

372details.

373 

374When a job fails:

375 

376- Missing scan artifacts point to a configuration or runner problem.

377- Existing artifacts with partial coverage require reviewing `coverage.json`.

378- Missing GitLab findings require checking whether the SARIF report job

379 succeeded and whether GitLab accepted the report.

380- Skipped remediation requires checking the protected branch, complete

381 coverage, finding severity, verification command, and opt-in variables.

382- Publishing errors require checking the project token's role, scopes, and

383 environment restriction.

384 

385For every command, flag, and artifact, see the [Codex Security CLI

386reference](https://learn.chatgpt.com/docs/security/cli/reference).