Commit Graph

4910 Commits

Author SHA1 Message Date
Michael Fan
2c08f00f65 codex: gate create-api-key guidance to legacy TUI
Co-authored-by: Codex <noreply@openai.com>
2026-03-26 19:38:28 -04:00
Michael Fan
076310369b codex: update create-api-key success copy
Co-authored-by: Codex <noreply@openai.com>
2026-03-26 19:10:58 -04:00
Michael Fan
c27ee7ae9d codex: align unified exec test harness with dependency env
Co-authored-by: Codex <noreply@openai.com>
2026-03-26 17:15:32 -04:00
Michael Fan
14a169b4bb codex: propagate dependency env to unified exec
Co-authored-by: Codex <noreply@openai.com>
2026-03-26 16:59:03 -04:00
Michael Fan
5e054045aa codex: revert stale status_line_cwd visibility
Co-authored-by: Codex <noreply@openai.com>
2026-03-26 16:57:50 -04:00
Michael Fan
44d1bc54a5 codex: remove create-api-key process env mutation
Co-authored-by: Codex <noreply@openai.com>
2026-03-26 16:57:50 -04:00
Michael Fan
b54bfc88d5 codex: redact dependency env updates in session logs
Co-authored-by: Codex <noreply@openai.com>
2026-03-26 16:57:50 -04:00
Michael Fan
3d5965dad5 codex: target create-api-key env updates to source thread
Co-authored-by: Codex <noreply@openai.com>
2026-03-26 16:57:49 -04:00
Michael Fan
3d5d514b09 codex: update create-api-key snapshots
Co-authored-by: Codex <noreply@openai.com>
2026-03-26 16:57:49 -04:00
Michael Fan
39821795d4 codex: set created API keys in session env
Co-authored-by: Codex <noreply@openai.com>
2026-03-26 16:57:49 -04:00
Michael Fan
a19cf09ac5 codex: show created API keys in TUI
Co-authored-by: Codex <noreply@openai.com>
2026-03-26 16:57:49 -04:00
Michael Fan
64e57306e5 codex: restore fixed create-api-key callback port
Use the Hydra-registered localhost:5000 redirect URI for project API key
creation, but fail fast on port conflicts instead of sending /cancel to a
potentially unrelated local service.

Validation:
- cargo test -p codex-login
- just fmt
- just fix -p codex-login
- just argument-comment-lint

Co-authored-by: Codex <noreply@openai.com>
2026-03-26 16:57:49 -04:00
Michael Fan
bfd4a6e7fe codex: clean up create-api-key naming
Co-authored-by: Codex <noreply@openai.com>
2026-03-26 16:57:49 -04:00
Michael Fan
ec0ca67f78 codex: address create-api-key review feedback
Co-authored-by: Codex <noreply@openai.com>
2026-03-26 16:57:49 -04:00
Michael Fan
285c4926b5 codex: rename api-provision slash command
Co-authored-by: Codex <noreply@openai.com>
2026-03-26 16:57:49 -04:00
Michael Fan
cb37b3e641 codex: clean up shared OAuth callback handling
Co-authored-by: Codex <noreply@openai.com>
2026-03-26 16:57:49 -04:00
Michael Fan
86f87f3431 codex: harden API provisioning secret writes
Co-authored-by: Codex <noreply@openai.com>
2026-03-26 16:57:49 -04:00
Michael Fan
98481441df codex: restrict dotenv API key file permissions
Co-authored-by: Codex <noreply@openai.com>
2026-03-26 16:57:49 -04:00
Michael Fan
dfa9c641b6 codex: narrow API provisioning options
Co-authored-by: Codex <noreply@openai.com>
2026-03-26 16:57:49 -04:00
Michael Fan
dd93a89cd2 codex: clean up callback server on auth URL errors
Co-authored-by: Codex <noreply@openai.com>
2026-03-26 16:57:49 -04:00
Michael Fan
0275e40f6b codex: revert unrelated rust CI workflow change
Co-authored-by: Codex <noreply@openai.com>
2026-03-26 16:57:49 -04:00
Michael Fan
27e0ea5e48 codex: restore moved callback server comment
Co-authored-by: Codex <noreply@openai.com>
2026-03-26 16:57:48 -04:00
Michael Fan
7b601b4c3d codex: sort oauth callback server imports
Co-authored-by: Codex <noreply@openai.com>
2026-03-26 16:57:48 -04:00
Michael Fan
7a885b6a56 Extract shared OAuth callback server machinery
Co-authored-by: Codex <noreply@openai.com>
2026-03-26 16:57:48 -04:00
Michael Fan
7dc4b016a3 codex: tighten api provisioning implementation
Co-authored-by: Codex <noreply@openai.com>
2026-03-26 16:57:48 -04:00
Michael Fan
de5c66e9a8 codex: move dotenv api key helper to tui
Co-authored-by: Codex <noreply@openai.com>
2026-03-26 16:57:48 -04:00
Michael Fan
a4d68acd12 codex: remove api provision helper binary
Drop the standalone helper binary and the CLI-only auth.json sync path from codex-login.

Co-authored-by: Codex <noreply@openai.com>
2026-03-26 16:57:48 -04:00
Michael Fan
b802f49ca2 codex: remove stale api provision alias
Drop the old run_onboard_oauth_helper_from_env re-export after the module rename.

Co-authored-by: Codex <noreply@openai.com>
2026-03-26 16:57:48 -04:00
Michael Fan
0dbda0e71b codex: reorganize api provision modules
Move the TUI slash command into the chatwidget module and rename the login helper module to match API provisioning behavior.

Co-authored-by: Codex <noreply@openai.com>
2026-03-26 16:57:48 -04:00
Michael Fan
3ed105cbdb Fix clippy warning in auth code server
Remove the redundant Arc clone in the shared authorization-code server loop.

Validation:
- cargo check -p codex-login --lib

Co-authored-by: Codex <noreply@openai.com>
2026-03-26 16:57:48 -04:00
Michael Fan
2a021f889f Format api-provision rebase merge
Apply rustfmt after resolving the api_provision rebase conflict.

Validation:
- cargo fmt --all --manifest-path /home/dev-user/code/codex/codex-rs/Cargo.toml

Co-authored-by: Codex <noreply@openai.com>
2026-03-26 16:57:48 -04:00
Michael Fan
97c8d8fa00 Refactor api-provision browser auth reuse
Move the reusable authorization-code callback server into codex-login::server, switch api-provision over to the shared PKCE/state/callback flow, and keep the TUI browser path alive even when auto-open fails.

Validation:
- cargo check -p codex-login --lib
- cargo fmt --all --manifest-path /home/dev-user/code/codex/codex-rs/Cargo.toml
- git diff --check

Co-authored-by: Codex <noreply@openai.com>
2026-03-26 16:57:48 -04:00
Michael Fan
e33a5b3570 changes 2026-03-26 16:57:48 -04:00
Michael Fan
a70ec9b26e codex: fix remaining CI failures on PR #15561
Skip redundant cargo-home cache saves in Windows test jobs to avoid post-test timeouts, and add the required argument comments in the login OAuth helper.

Co-authored-by: Codex <noreply@openai.com>
2026-03-26 16:57:48 -04:00
Michael Fan
b54ee4952e codex: fix CI failure on PR #15561 2026-03-26 16:57:48 -04:00
Michael Fan
9b034e7b46 .env -> .env.local 2026-03-26 16:57:47 -04:00
Michael Fan
62d24d13e3 Use OPENAI_API_KEY for api provisioning
Skip /api-provision when the current Codex process already inherited
OPENAI_API_KEY, and otherwise persist the provisioned key to .env under
OPENAI_API_KEY instead of CODEX_API_KEY.

Validation:
- cargo test -p codex-login
- cargo test -p codex-tui
- just fix -p codex-login
- just fix -p codex-tui
- just fmt

Co-authored-by: Codex <noreply@openai.com>
2026-03-26 16:57:47 -04:00
Michael Fan
fa7beabaff Add CLI api-provision slash command
Extract the browser-based provisioning flow from codex-login so the plain TUI can
reuse it. Add /api-provision to the CLI, persist CODEX_API_KEY to .env, and
hot-apply the key via ephemeral auth without touching auth.json.

Validation:
- cargo test -p codex-login
- cargo test -p codex-tui
- just fix -p codex-login
- just fix -p codex-tui
- just fmt

Co-authored-by: Codex <noreply@openai.com>
2026-03-26 16:57:47 -04:00
Michael Bolin
dfb36573cd sandboxing: use OsString for SandboxCommand.program (#15897)
## Why

`SandboxCommand.program` represents an executable path, but keeping it
as `String` forced path-backed callers to run `to_string_lossy()` before
the sandbox layer ever touched the command. That loses fidelity earlier
than necessary and adds avoidable conversions in runtimes that already
have a `PathBuf`.

## What changed

- Changed `SandboxCommand.program` to `OsString`.
- Updated `SandboxManager::transform` to keep the program and argv in
`OsString` form until the `SandboxExecRequest` conversion boundary.
- Switched the path-backed `apply_patch` and `js_repl` runtimes to pass
`into_os_string()` instead of `to_string_lossy()`.
- Updated the remaining string-backed builders and tests to match the
new type while preserving the existing Linux helper `arg0` behavior.

## Verification

- `cargo test -p codex-sandboxing`
- `just argument-comment-lint -p codex-core -p codex-sandboxing`
- `cargo test -p codex-core` currently fails in unrelated existing
config tests: `config::tests::approvals_reviewer_*` and
`config::tests::smart_approvals_alias_*`
2026-03-26 20:38:33 +00:00
Michael Bolin
b23789b770 [codex] import token_data from codex-login directly (#15903)
## Why
`token_data` is owned by `codex-login`, but `codex-core` was still
re-exporting it. That let callers pull auth token types through
`codex-core`, which keeps otherwise unrelated crates coupled to
`codex-core` and makes `codex-core` more of a build-graph bottleneck.

## What changed
- remove the `codex-core` re-export of `codex_login::token_data`
- update the remaining `codex-core` internals that used
`crate::token_data` to import `codex_login::token_data` directly
- update downstream callers in `codex-rs/chatgpt`,
`codex-rs/tui_app_server`, `codex-rs/app-server/tests/common`, and
`codex-rs/core/tests` to import `codex_login::token_data` directly
- add explicit `codex-login` workspace dependencies and refresh lock
metadata for crates that now depend on it directly

## Validation
- `cargo test -p codex-chatgpt --locked`
- `just argument-comment-lint`
- `just bazel-lock-update`
- `just bazel-lock-check`

## Notes
- attempted `cargo test -p codex-core --locked` and `cargo test -p
codex-core auth_refresh --locked`, but both ran out of disk while
linking `codex-core` test binaries in the local environment
2026-03-26 13:34:02 -07:00
rreichel3-oai
86764af684 Protect first-time project .codex creation across Linux and macOS sandboxes (#15067)
## Problem

Codex already treated an existing top-level project `./.codex` directory
as protected, but there was a gap on first creation.

If `./.codex` did not exist yet, a turn could create files under it,
such as `./.codex/config.toml`, without going through the same approval
path as later modifications. That meant the initial write could bypass
the intended protection for project-local Codex state.

## What this changes

This PR closes that first-creation gap in the Unix enforcement layers:

- `codex-protocol`
- treat the top-level project `./.codex` path as a protected carveout
even when it does not exist yet
- avoid injecting the default carveout when the user already has an
explicit rule for that exact path
- macOS Seatbelt
- deny writes to both the exact protected path and anything beneath it,
so creating `./.codex` itself is blocked in addition to writes inside it
- Linux bubblewrap
- preserve the same protected-path behavior for first-time creation
under `./.codex`
- tests
- add protocol regressions for missing `./.codex` and explicit-rule
collisions
- add Unix sandbox coverage for blocking first-time `./.codex` creation
  - tighten Seatbelt policy assertions around excluded subpaths

## Scope

This change is intentionally scoped to protecting the top-level project
`.codex` subtree from agent writes.

It does not make `.codex` unreadable, and it does not change the product
behavior around loading project skills from `.codex` when project config
is untrusted.

## Why this shape

The fix is pointed rather than broad:
- it preserves the current model of “project `.codex` is protected from
writes”
- it closes the security-relevant first-write hole
- it avoids folding a larger permissions-model redesign into this PR

## Validation

- `cargo test -p codex-protocol`
- `cargo test -p codex-sandboxing seatbelt`
- `cargo test -p codex-exec --test all
sandbox_blocks_first_time_dot_codex_creation -- --nocapture`

---------

Co-authored-by: Michael Bolin <mbolin@openai.com>
2026-03-26 16:06:53 -04:00
Ruslan Nigmatullin
9736fa5e3d app-server: Split transport module (#15811)
`transport.rs` is getting pretty big, split individual transport
implementations into separate files.
2026-03-26 13:01:35 -07:00
Michael Bolin
b3e069e8cb skills: remove unused skill permission metadata (#15900)
## Why

Skill metadata accepted a `permissions` block and stored the result on
`SkillMetadata`, but that data was never consumed by runtime behavior.
Leaving the dead parsing path in place makes it look like skills can
widen or otherwise influence execution permissions when, in practice,
declared skill permissions are ignored.

This change removes that misleading surface area so the skill metadata
model matches what the system actually uses.

## What changed

- removed `permission_profile` and `managed_network_override` from
`core-skills::SkillMetadata`
- stopped parsing `permissions` from skill metadata in
`core-skills/src/loader.rs`
- deleted the loader tests that only exercised the removed permissions
parsing path
- cleaned up dependent `SkillMetadata` constructors in tests and TUI
code that were only carrying `None` for those fields

## Testing

- `cargo test -p codex-core-skills`
- `cargo test -p codex-tui
submission_prefers_selected_duplicate_skill_path`
- `just argument-comment-lint`
2026-03-26 19:33:23 +00:00
viyatb-oai
b6050b42ae fix: resolve bwrap from trusted PATH entry (#15791)
## Summary
- resolve system bwrap from PATH instead of hardcoding /usr/bin/bwrap
- skip PATH entries that resolve inside the current workspace before
launching the sandbox helper
- keep the vendored bubblewrap fallback when no trusted system bwrap is
found

## Validation
- cargo test -p codex-core bwrap --lib
- cargo test -p codex-linux-sandbox
- just fix -p codex-core
- just fix -p codex-linux-sandbox
- just fmt
- just argument-comment-lint
- cargo clean
2026-03-26 12:13:51 -07:00
Matthew Zeng
3360f128f4 [plugins] Polish tool suggest prompts. (#15891)
- [x] Polish tool suggest prompts to distinguish between missing
connectors and discoverable plugins, and be very precise about the
triggering conditions.
2026-03-26 18:52:59 +00:00
Matthew Zeng
25134b592c [mcp] Fix legacy_tools (#15885)
- [x] Fix legacy_tools
2026-03-26 11:08:49 -07:00
Felipe Coury
2c54d4b160 feat(tui): add terminal title support to tui app server (#15860)
## TR;DR

Replicates the `/title` command from `tui` to `tui_app_server`.

## Problem

The classic `tui` crate supports customizing the terminal window/tab
title via `/title`, but the `tui_app_server` crate does not. Users on
the app-server path have no way to configure what their terminal title
shows (project name, status, spinner, thread, etc.), making it harder to
identify Codex sessions across tabs or windows.

## Mental model

The terminal title is a *status surface* -- conceptually parallel to the
footer status line. Both surfaces are configurable lists of items, both
share expensive inputs (git branch lookup, project root discovery), and
both must be refreshed at the same lifecycle points. This change ports
the classic `tui`'s design verbatim:

1. **`terminal_title.rs`** owns the low-level OSC write path and input
sanitization. It strips control characters and bidi/invisible codepoints
before placing untrusted text (model output, thread names, project
paths) inside an escape sequence.

2. **`title_setup.rs`** defines `TerminalTitleItem` (the 8 configurable
items) and `TerminalTitleSetupView` (the interactive picker that wraps
`MultiSelectPicker`).

3. **`status_surfaces.rs`** is the shared refresh pipeline. It parses
both surface configs once per refresh, warns about invalid items once
per session, synchronizes the git-branch cache, then renders each
surface from the same `StatusSurfaceSelections` snapshot.

4. **`chatwidget.rs`** sets `TerminalTitleStatusKind` at each state
transition (Working, Thinking, Undoing, WaitingForBackgroundTerminal)
and calls `refresh_terminal_title()` whenever relevant state changes.

5. **`app.rs`** handles the three setup events (confirm/preview/cancel),
persists config via `ConfigEditsBuilder`, and clears the managed title
on `Drop`.

## Non-goals

- **Restoring the previous terminal title on exit.** There is no
portable way to read the terminal's current title, so `Drop` clears the
managed title rather than restoring it.
- **Sharing code between `tui` and `tui_app_server`.** The
implementation is a parallel copy, matching the existing pattern for the
status-line feature. Extracting a shared crate is future work.

## Tradeoffs

- **Duplicate code across crates.** The three core files
(`terminal_title.rs`, `title_setup.rs`, `status_surfaces.rs`) are
byte-for-byte copies from the classic `tui`. This was chosen for
consistency with the existing status-line port and to avoid coupling the
two crates at the dependency level. Future changes must be applied in
both places.

- **`status_surfaces.rs` is large (~660 lines).** It absorbs logic that
previously lived inline in `chatwidget.rs` (status-line refresh, git
branch management, project root discovery) plus all new terminal-title
logic. This consolidation trades file size for a single place where both
surfaces are coordinated.

- **Spinner scheduling on every refresh.** The terminal title spinner
(when active) schedules a frame every 100ms. This is the same pattern
the status-indicator spinner already uses; the overhead is a timer
registration, not a redraw.

## Architecture

```
/title command
  -> SlashCommand::Title
  -> open_terminal_title_setup()
  -> TerminalTitleSetupView (MultiSelectPicker)
  -> on_change:  AppEvent::TerminalTitleSetupPreview  -> preview_terminal_title()
  -> on_confirm: AppEvent::TerminalTitleSetup         -> ConfigEditsBuilder + setup_terminal_title()
  -> on_cancel:  AppEvent::TerminalTitleSetupCancelled -> cancel_terminal_title_setup()

Runtime title refresh:
  state change (turn start, reasoning, undo, plan update, thread rename, ...)
  -> set terminal_title_status_kind
  -> refresh_terminal_title()
  -> status_surface_selections()  (parse configs, collect invalids)
  -> refresh_terminal_title_from_selections()
     -> terminal_title_value_for_item() for each configured item
     -> assemble title string with separators
     -> skip if identical to last_terminal_title (dedup OSC writes)
     -> set_terminal_title() (sanitize + OSC 0 write)
     -> schedule spinner frame if animating

Widget replacement:
  replace_chat_widget_with_app_server_thread()
  -> transfer last_terminal_title from old widget to new
  -> avoids redundant OSC clear+rewrite on session switch
```

## Observability

- Invalid terminal-title item IDs in config emit a one-per-session
warning via `on_warning()` (gated by
`terminal_title_invalid_items_warned` `AtomicBool`).
- OSC write failures are logged at `tracing::debug` level.
- Config persistence failures are logged at `tracing::error` and
surfaced to the user via `add_error_message()`.

## Tests

- `terminal_title.rs`: 4 unit tests covering sanitization (control
chars, bidi codepoints, truncation) and OSC output format.
- `title_setup.rs`: 3 tests covering setup view snapshot rendering,
parse order preservation, and invalid-ID rejection.
- `chatwidget/tests.rs`: Updated test helpers with new fields; existing
tests continue to pass.

---------

Co-authored-by: Eric Traut <etraut@openai.com>
2026-03-26 11:59:12 -06:00
jif-oai
970386e8b2 fix: root as std agent (#15881) 2026-03-26 18:57:34 +01:00
evawong-oai
0bd34c28c7 Add wildcard in the middle test coverage (#15813)
## Summary
Add a focused codex network proxy unit test for the denylist pattern
with wildcard in the middle `region*.some.malicious.tunnel.com`. This
does not change how existing code works, just ensure that behavior stays
the same and we got CI guards to guard existin behavior.

## Why
The managed Codex denylist update relies on this mid label glob form,
and the existing tests only covered exact hosts, `*.` subdomains, and
`**.` apex plus subdomains.

## Validation
`cargo test -p codex-network-proxy
compile_globset_supports_mid_label_wildcards`
`cargo test -p codex-network-proxy`
`./tools/argument-comment-lint/run-prebuilt-linter.sh -p
codex-network-proxy`
2026-03-26 17:53:31 +00:00
Adrian
af04273778 [codex] Block unsafe git global options from safe allowlist (#15796)
## Summary
- block git global options that can redirect config, repository, or
helper lookup from being auto-approved as safe
- share the unsafe global-option predicate across the Unix and Windows
git safety checks
- add regression coverage for inline and split forms, including `bash
-lc` and PowerShell wrappers

## Root cause
The Unix safe-command gate only rejected `-c` and `--config-env`, even
though the shared git parser already knew how to skip additional
pre-subcommand globals such as `--git-dir`, `--work-tree`,
`--exec-path`, `--namespace`, and `--super-prefix`. That let those
arguments slip through safe-command classification on otherwise
read-only git invocations and bypass approval. The Windows-specific
safe-command path had the same trust-boundary gap for git global
options.
2026-03-26 10:46:04 -07:00