Commit Graph

248 Commits

Author SHA1 Message Date
Matthew Zeng
af1fc2dbff Honor canonical plugin disables for shared connectors (#45755)
## Why

Disabling a connector's canonical plugin could leave its tools available when another enabled plugin contributed the same connector.

## What changed

Retain `canonical_app_id` in the remote installed-plugin cache and use ownership metadata for the current account when building connector snapshots. A disabled canonical owner now excludes its connector even when another plugin contributes it or the owner's bundle is absent from the host. Match owners by plugin name and marketplace, and ignore ownership metadata when the cache no longer matches the current authentication.

Build these snapshots through `PluginsManager` when the plugins feature is enabled; otherwise use an empty snapshot.

## Testing

Add manager coverage for combined local and canonical exclusions, marketplace matching, and authentication changes. Add an integration test showing that disabling a noncanonical contributor preserves shared calendar tools, disabling the canonical owner hides them, and clearing the exclusion restores them.

GitOrigin-RevId: ee2981d1277825fefb671dd7d1078cd7ea5c0ea5
2026-09-15 18:23:08 +00:00
Nick Steele
374c4b2d82 Resolve enterprise-managed MCP registrations in the catalog (#45459)
## What changed

- Retain the trusted enterprise identity provider in runtime configuration and bind winning MCP registrations during catalog finalization. Require `features.use_xaa` and a configured identity provider for activation, while preserving existing server restrictions.
- Apply plugin `ema_auth` client, issuer, resource, and scope settings to installed and selected plugins. Disable registrations with mismatched endpoints or empty resources without rewriting plugin endpoints.
- Preserve enterprise auth policy across catalog rebuilds and rebind registrations when materialized server settings change. Keep registration rejection separate from persistent server-name vetoes so it does not disable replacement hosted apps.

## Testing

Add coverage for activation gates, configuration ownership, plugin endpoint validation, catalog rebuilds, and skipping interactive OAuth during installation of enterprise-managed plugins. Stabilize the sandbox network proxy test by reading request headers before closing the loopback connection.

GitOrigin-RevId: 3374f507d120835b285767cedbbb511fc7b0fba2
2026-09-14 16:30:00 +00:00
Nick Steele
654b0a77d0 Add trusted enterprise MCP auth configuration (#44832)
## Why

Enterprise MCP authorization must remain controlled by host, user, or managed configuration. Project settings and plugin declarations must not redirect enterprise credentials or downgrade the selected authentication mode.

## What changed

- Add `auth = "ema_auth"`, shared `mcp_enterprise_managed_auth` IdP configuration, and per-plugin enterprise registration settings.
- Require enterprise registrations to come from one non-project configuration layer, preserve managed IdP precedence, and reject project overrides that change authorization or re-enable disabled enterprise servers.
- Add the disabled-by-default `use_xaa` feature flag and require non-project opt-in or a managed requirement.
- Reject plugin declarations that select `ema_auth`. Keep EMA connections unsupported and block ordinary MCP OAuth login and credential fallback for this mode.
- Extend the configuration schema and serialization for the new settings.

## Testing

Add coverage for IdP precedence, incomplete registrations, alternate credential validation, project-only opt-in, plugin self-declaration rejection, configuration round-tripping, and trusted-project attempts to downgrade enterprise auth to OAuth or ChatGPT auth.

GitOrigin-RevId: f193bdfda74208c98e496a23bf2916955b131a1c
2026-09-11 14:25:56 +00:00
Felipe Coury
637c3227b3 Avoid executing PATH helpers before workspace trust (#42324)
## Why

Automatic startup work and `codex doctor` can run before a workspace is
trusted. A repository-controlled `PATH` must not be able to make those flows
execute workspace-provided helpers.

## What changed

- Resolve helpers used by automatic startup from trusted system installation
  directories, and give plugin-sync Git subprocesses a sanitized environment.
- Make terminal detection environment-only and have doctor inspect executable
  locations without running them. Fetch update metadata with the HTTP client
  instead of `curl`.
- Fall back conservatively when trusted terminal helpers are unavailable,
  including for tmux keyboard enhancement flags.

## Testing

Add black-box coverage with hostile workspace `PATH` entries for startup,
interactive tmux startup, support log collection, doctor, and curated plugin
sync. Add unit coverage for trusted executable resolution and bounded update
HTTP responses.

GitOrigin-RevId: 3b8995eb422b60ed53b0386951de59e8f9bfc542
2026-09-02 18:34:27 +00:00
jif
50fffd5ed3 Refresh plugin skills after out-of-process version changes (#42284)
## Why

Another process sharing `CODEX_HOME` can replace an installed plugin version
without invalidating the current process's caches. This could leave skill
listings tied to stale plugin paths and retain obsolete plugin generations.

## What changed

- Reject cached plugin loads when their roots no longer match the active
  installation, so skills are reloaded after upgrades or rollbacks.
- Keep the 32 most recently used configuration-based skill snapshots while
  allowing callers to continue using snapshots that have been evicted.

## Testing

- Cover external plugin upgrades and rollbacks through `skills/list`, including
  a subsequent warm-cache read.
- Cover cache eviction, reuse, and the lifetime of caller-held snapshots.

GitOrigin-RevId: ca00f9539c01461e3945d340bf63f8436665220b
2026-09-02 14:14:44 +00:00
willwang-openai
6b59cefcbb Support remote marketplaces in the plugin CLI (#42150)
## What changed

- Include remote catalog entries in `codex plugin list`, including their source,
  version, install policy, and authentication policy in JSON output.
- Support adding and removing remote plugins through the existing plugin CLI.
- Cache remote catalogs by scope and collection. Prefer fresh cached results, and
  refetch once when an add request misses a plugin in the cache.
- Preserve the local curated catalog when an unfiltered remote listing fails,
  while surfacing errors for explicitly selected remote marketplaces.

## Testing

- Cover remote listing, installation, removal, catalog fallback, cache refresh,
  collection isolation, and install failure behavior.

GitOrigin-RevId: 09796b2c393d102e00ba9289f784d78a2e166a54
2026-09-01 22:51:14 +00:00
willwang-openai
68c9556cdf Upgrade Git marketplaces from merged configuration (#42149)
## Why

Configured Git marketplaces may be defined outside the user config, but those definitions could not download or update their snapshots.

## What changed

- Select marketplace source, ref, and sparse-path settings from the effective merged configuration for startup synchronization and explicit upgrades.
- Preserve the initiating operation's configuration loader and overrides when reloading before activation.
- Roll back activation if the marketplace definition changed or configuration can no longer be loaded, without copying settings into the user config.

## Testing

- Cover system-defined marketplaces, CLI overrides, startup fallback after invalid user configuration, and rollback after configuration changes.

GitOrigin-RevId: 53d1eecf68a91ce2aa8430e5749d78697bfcd821
2026-09-01 22:37:26 +00:00
willwang-openai
ef76e6ac30 Centralize remote plugin mutations in PluginsManager (#42114)
## What changed

- Move remote plugin install and uninstall orchestration from the app server into shared `PluginsManager` APIs.
- Keep cache and backend mutations coordinated by the installed-plugin sync gate, and retain install outcomes long enough to protect newly materialized bundles during downstream setup.
- Return structured operation errors and outcomes so callers can preserve JSON-RPC error mapping, telemetry, cache refreshes, and OAuth setup.

## Testing

- Add regression coverage that verifies uninstall holds the mutation gate, preserves the local cache when the backend operation fails, and refreshes installed state after a successful uninstall.

GitOrigin-RevId: de39f19a4e61c6e9c76ddc2c65d2ac130a4b7f88
2026-09-01 18:35:00 +00:00
teddywyly-oai
c7c824dce4 Treat bundled cleanup hooks as built-ins (#42110)
## What changed

- Centralize the allowlist for bundled MCP cleanup hooks and use it for both local and executor-discovered plugins, including `unified-computer-use` cleanup through `cua_repl`.
- Mark matching cleanup hooks as trusted built-ins so they run without saved hook trust and remain active when regular hooks or their per-hook state are disabled. Plugin enablement and managed-only policy still apply.
- Hide built-in cleanup hooks from hook listings and lifecycle notifications while retaining their metrics. Keep the built-in classification out of serialized protocol data.

## Testing

- Cover allowlist boundaries, trust and enablement behavior, inline and file-based hook declarations, MCP success and error responses, hook listing, lifecycle notifications, metrics, and protocol serialization.

GitOrigin-RevId: f93b7bc99f4ed9694f529def8ec383b45f31430e
2026-09-01 18:02:27 +00:00
Jiwon Kim
b6ab99ed87 Prefer remote Sites over the bundled plugin (#42100)
## Why

When the remote Sites plugin is installed and its local bundle is available, exposing the bundled copy as well creates duplicate catalog entries and can load the wrong skills.

## What changed

- Persist an account- and backend-scoped exclusion for `sites@openai-bundled` once the remote replacement is installed and loadable.
- Apply the exclusion to plugin catalogs, search, direct reads and installs, runtime loading, hooks, and skill caches while preserving the remote plugin's server-owned enabled state.
- Restore the bundled fallback when the remote plugin is absent or its local files are unavailable, and throttle repeated availability checks for 60 seconds.

## Testing

- Added manager tests for persistence across restarts, account/backend isolation, fallback restoration, concurrent checks, and refresh throttling.
- Added app-server and agent-turn tests confirming that catalog, search, and skill loading prefer remote Sites.

GitOrigin-RevId: bc1154f79d3107910fee9fa27389a0ddb48ce6cf
2026-09-01 16:58:54 +00:00
willwang-openai
633ab199cf Enforce marketplace source policy for curated plugins (#41953)
## Why

Marketplace source restrictions should cover curated plugins backed by the OpenAI plugins repository, not only user-configured marketplaces.

## What changed

- Validate both local curated catalogs against the existing OpenAI plugins Git source allowlist.
- Apply that policy to catalog discovery, installation, cached plugin and skill loading, and startup repository sync.
- Keep bundled and remote installed plugins independent of the curated Git source policy.

## Testing

Added coverage for exact and shorthand Git allowlist entries, host patterns, blocked and invalid rules, curated catalog variants, plugin skills, startup sync, and remote installed plugins.

GitOrigin-RevId: 04617acb4a93040c70a13759eb4ce872877ba211
2026-09-01 01:37:15 +00:00
Samuel Yuan
2181224dad Support app targets in executor plugin hooks (#41456)
## What changed

- Admit the curated remote Browser plugin's `Stop` and `SubagentStop` hooks when its listed `browser.turn_ended` tool matches the expected connector and is enabled by app policy.
- Carry trusted app routing metadata and the MCP environment through hook registration and execution.
- Register hooks from multiple executor environments, while deduplicating cleanup calls that share an event, MCP environment, server, and tool.

## Testing

- Cover Browser and Computer Use cleanup through separate MCP routes, including user- and managed-policy disablement.
- Verify routing metadata, environment selection, multi-environment registration, and target deduplication.

GitOrigin-RevId: 66de088fd201b9ed0db8b97c23d33de88135120d
2026-08-29 03:14:35 +00:00
Krish Chainani
c6bf330b42 Allow bundled browser cleanup hooks on subagent stop (#41435)
## What changed

Allow bundled browser and computer-use plugins to invoke the existing
`node_repl.turn_ended` cleanup hook for `SubagentStop` events, matching the
allowlist behavior for `Stop` and `Interrupt` events.

GitOrigin-RevId: 0fe1784321e793e9861e728b40a48662625b7dca
2026-08-28 23:19:01 +00:00
Krish Chainani
c2abf869d5 Run executor hooks for interrupted turns (#41432)
## Why

Executor-scoped cleanup hooks need to observe an interrupted turn as well as a
normally completed one.

## What changed

- Allow bundled executor plugins to register the allowlisted `Interrupt` hook
  alongside `Stop`, while preserving multiple allowed hook entries from the
  selected executor environment.
- Run interrupt hooks with the interrupted turn's last step discovery and turn
  metadata. Turns without a step context do not reuse discovery from an earlier
  turn.
- Keep executor-scoped interrupt hooks asynchronous and omit public hook
  lifecycle events for them, matching executor `Stop` hook behavior.

## Testing

Added coverage for hook filtering and registration, interrupt execution and
metadata propagation, environment selection, and turns without a step context.

GitOrigin-RevId: f0c536b3382a37cf3bf693c4573d21f6f66ace4e
2026-08-28 23:03:05 +00:00
pakrym-oai
f742dabc6f Support per-tool MCP output limits (#41421)
## What changed

- Add a positive `output_token_limit` setting to each entry under an MCP server's `tools` configuration.
- Apply the most restrictive limit when plugin and user policies overlap, while keeping approval policy independent.
- Carry the effective MCP output budget in conversation history so tool output, post-tool hook responses, and resumed sessions use the same truncation limit.

## Testing

- Cover configuration parsing, serialization, schema validation, and plugin policy merging.
- Cover MCP output below and above the configured limit, post-tool hook responses, and session resume.

GitOrigin-RevId: d0beb4fca9ba6055d9e1d31c137373b465d50d61
2026-08-28 21:40:23 +00:00
Matthew Zeng
bb998aeb8e Refresh runtimes for remote plugin state changes (#41396)
## Why

Enabling, disabling, or reinstalling a cached remote plugin can change its
effective MCP servers, hooks, and skills without materializing a new bundle.
These transitions need to invalidate plugin consumers just like bundle updates
and removals do.

## What changed

- Report a unified set of changed remote plugins and their affected
  capabilities for materializations, removals, and installed-state changes.
- Derive enablement and reinstall changes by comparing installed snapshots,
  while keeping materialization metadata separate for hook trust handling.
- Preserve removal notifications even when stale cache cleanup fails, and use
  all reported changes to refresh loaded plugin state and runtime consumers.

## Testing

Added coverage for cached plugin enablement, disablement, removal, and
reinstallation, including removal when cache cleanup cannot complete.

GitOrigin-RevId: 86d9c1356f7cf70b3c85effebc3e5986b931bdba
2026-08-28 19:12:34 +00:00
Matthew Zeng
8bcac28f93 Preload plugin recommendations during session startup (#41375)
## Why

Fetching plugin recommendations while building the first-turn context delays that
context when the recommendation catalog is not already cached.

## What changed

- Start fetching recommendations during session initialization, in parallel with
  MCP and plugin setup, and reuse the in-flight request when building context.
- Centralize the feature checks that enable plugin recommendations.
- Prevent an invalidated recommendation request from repopulating the cache after
  a newer request has completed.

## Testing

Added coverage for startup feature gating, reuse of the in-flight fetch, legacy
behavior when recommendations are unavailable, and cache invalidation races.

GitOrigin-RevId: 708774b9bfc472c9847973ae8b2774b66e7321e4
2026-08-28 17:33:10 +00:00
willwang-openai
91c66024c7 Instrument the loaded plugin cache (#41231)
## What changed

- Count loaded-plugin cache requests by `hit`, `hit_after_wait`, or `load` outcome.
- Record time spent waiting for the load semaphore and loading plugins.
- Count cache clears and capacity evictions.
- Remove the unused force-reload path from `PluginsManager::plugins_for_config`.

GitOrigin-RevId: db7829e7bd9b1414a263d9a7100c05dfdd832777
2026-08-28 00:17:08 +00:00
willwang-openai
e9a6d731b7 Apply app routing policy to unauthenticated plugin reads (#41230)
## What changed

Apply the legacy plugin app/MCP routing policy even when no authentication mode is available. Unauthenticated plugin reads now omit unavailable app declarations while retaining their MCP server alternatives.

## Testing

Extend plugin manager coverage for unauthenticated reads and provide ChatGPT authentication in the app-server bundle-details test.

GitOrigin-RevId: d90d29d0702488eb7413c6779254a9e6aae615c0
2026-08-28 00:07:32 +00:00
willwang-openai
c4c51c56e4 Honor per-repository plugin configuration in catalog requests (#41208)
## What changed

- Load the effective plugin configuration for every requested `cwd` in
  `plugin/list` and `plugin/installed`.
- Combine local marketplaces in request order, keeping the first source for
  duplicates while merging installed and enabled state across repositories.
- Report invalid project configurations through `marketplaceLoadErrors` without
  dropping valid local catalogs or globally enabled remote catalogs.
- Use the combined marketplace context for forced and background cache refreshes,
  while keeping remote plugin feature gating request-wide.

## Testing

- Cover distinct and duplicate marketplaces, cross-repository enabled state,
  invalid project configuration, local cache refresh, and global versus
  project-local feature flags.

GitOrigin-RevId: 53c8e0e9c760dc2b969ab10d0e63fb439673c230
2026-08-27 21:10:10 +00:00
Matthew Zeng
56239d7a61 Report affected capabilities from remote plugin syncs (#41193)
## Why

Remote plugin sync results need to identify which runtime categories may require
invalidation when a cached bundle changes.

## What changed

- Add `RemotePluginCapabilities` hints for MCP servers, Apps, hooks, and skills.
- Attach capability hints to materialized and removed plugins. Updates union the
  declarations from the old and new bundles, while removals inspect the active
  bundle before deleting its cache.
- Discover declarations without applying runtime policy or creating runtime
  data directories.

## Testing

- Cover Agent Plugin capability discovery with an unavailable runtime data
  directory.
- Cover capability accumulation across bundle versions and removal reporting.

GitOrigin-RevId: 338075d22d86f30f52be5785a2d87c77b33609c6
2026-08-27 19:54:40 +00:00
Krish Chainani
0340e12f5d Allow bundled browser plugins to run executor cleanup hooks (#40993)
## Why

Executor plugin manifests are unsigned, so cleanup hooks must remain limited to
explicitly trusted plugin identities and MCP targets.

## What changed

- Allow the bundled Browser, Chrome, Chrome Dev, and Chrome Internal plugins to
  run the existing `Stop` hook for `node_repl.turn_ended`.
- Continue allowing the bundled Computer Use plugin and rejecting unlisted or
  lookalike marketplace identities.

## Testing

- Extend manifest-filtering coverage for unlisted bundled plugins and marketplace
  name variants.

GitOrigin-RevId: 1ad5d679a1530994df5a9628c2117ce509fec9ad
2026-08-26 22:58:54 +00:00
willwang-openai
6ac012a0d4 Honor layered configuration when loading plugins (#40954)
## What changed

- Resolve plugin activation, MCP server policy, and marketplace definitions from the effective configuration stack, including system settings and trusted project overrides.
- Load plugin skills independently for each working directory passed to `skills/list`.
- Exclude project configuration from catalog requests whose `cwds` are omitted or empty.
- Cache up to eight loaded plugin configurations with least-recently-used eviction so requests for different working directories can reuse their results.

## Testing

- Cover layered plugin and MCP policy across trusted and untrusted projects.
- Cover per-directory skill and plugin catalog results, cache reuse and eviction, and system-defined marketplaces.

GitOrigin-RevId: cb68b2b1bdab1da48e05ca7562bc05014431fc71
2026-08-26 19:02:02 +00:00
stevenlee-oai
9be8d6e1c3 Harden MCP OAuth callback handling (#40691)
## Why

MCP servers can share an OAuth callback URL. Without a validated issuer or a
server-specific callback path, an authorization response could be associated
with the wrong server.

## What changed

- Use stable callbacks when authorization metadata advertises issuer-bound
  responses, and validate the returned issuer before exchanging the code.
- Retain server-specific callback IDs for providers without issuer support,
  including fallback to the global or default callback for legacy registered
  clients.
- Persist registered callback URLs for MCP servers and plugins, and insert the
  active listener port into portless loopback redirects.

## Testing

Add coverage for issuer validation, callback-mode discovery, registered and
legacy clients, plugin OAuth, CLI persistence, and loopback listener ports.

GitOrigin-RevId: 2878c92e237fc17fd3def0bd2e1cce3e104a3db8
2026-08-25 20:26:23 +00:00
willwang-openai
a6e63f9f32 Respect config layers when removing plugin marketplaces (#40683)
## Why

Removing a base-user marketplace must not delete a snapshot that is still
referenced by another enabled configuration layer.

## What changed

- Load the current configuration stack for marketplace commands in the CLI and
  app server.
- Reject removal when a matching marketplace is defined by another enabled
  layer, and identify the configuration source that must be updated instead.
- Allow cleanup of an installed marketplace snapshot even when no base-user
  entry exists.

## Testing

Cover project, enterprise-managed, system, and session-flag configurations, as
well as snapshot-only removal through the CLI and app server.

GitOrigin-RevId: 4f0853a40c2b5fae0410696b79eee4284239c7a9
2026-08-25 19:38:39 +00:00
alexsong-oai
4f6d43c267 Support managed AWS access keys for Amazon Bedrock (#40481)
## What changed

- Add the experimental `amazonBedrockAccessKeys` app-server login flow, persist its credentials in the configured auth store, and use them for SigV4-signed Bedrock requests.
- Report `bedrockAccessKeys` as a distinct auth mode and document access-key login alongside AWS profile and environment credential setup.
- Clear the selected Bedrock provider, AWS settings, and Bedrock-specific model on logout while leaving external AWS credentials and `.env` untouched.
- Reject managed access-key login when higher-precedence configuration would prevent its region or profile settings from taking effect.

## Testing

- Cover access-key login, storage, request signing, configuration conflicts, status reporting, and logout cleanup.

GitOrigin-RevId: bbf297887c6503d3651ceb2aad85c4d626e32723
2026-08-24 21:39:48 +00:00
jif
cd25b81c65 Strengthen Agent Plugin MCP environment overlay tests (#40410)
## What changed

- Cover forwarding a legacy `env_vars` entry when the portable MCP server has no `env` map.
- Use the test workspace variable instead of `PATH` in the stdio round-trip test, keeping overlay forwarding distinct from portable environment expansion.

GitOrigin-RevId: c5cfb333e553581fc856d43a04e5be0abd9f65ef
2026-08-24 14:37:48 +00:00
jif
40b7560169 Forward local env vars to Agent Plugin MCP servers (#40363)
## What changed

- Apply local `env_vars` declarations from `.codex-plugin/plugin.json` to matching stdio servers loaded from an Agent Plugin manifest.
- Replace matching `${NAME}` entries in the portable server environment with host environment forwarding while preserving the portable command, arguments, and unrelated servers.
- Ignore remote-sourced environment variables and support both inline and file-based Codex MCP declarations.

## Testing

- Cover matching-server filtering, local and remote sources, inline declarations, and an end-to-end `PATH` forwarding round trip.

GitOrigin-RevId: 843e1232a084fa5f571fe56e07266995b87fd53d
2026-08-24 08:43:25 +00:00
Matthew Zeng
e6a3877e95 Harden remote installed plugin cache reconciliation (#40015)
## What changed

- Scope remote installed-plugin and loaded-plugin snapshots to the active account, and discard in-flight loads when the account changes.
- Serialize bundle reconciliation with direct installs and uninstalls, and use cache generations to prevent stale refreshes from overwriting newer state.
- Validate the complete installed-plugin snapshot before downloading bundles or removing stale cache entries, while retaining valid installed metadata when materialization fails.

## Testing

- Cover account changes during plugin loading, incomplete snapshots, refresh/reconciliation races, and reconciliation cancellation recovery.

GitOrigin-RevId: 694c25577b420b93dacc6c65e3c0ecb7b8cc64c3
2026-08-21 21:28:16 +00:00
Krish Chainani
8b61c50ebe Run allowlisted executor plugin stop hooks (#40009)
## What changed

- Discover inline hooks from executor-provided plugin manifests and accept only
  the bundled Computer Use `Stop` hook for `node_repl.turn_ended`.
- Add the accepted hook to the current step's hook engine with
  executor-scoped provenance.
- Run executor-scoped hooks in the background after regular stop-hook
  decisions, without delaying turn completion, applying control effects, or
  exposing them in hook summaries. Skip them when regular hooks only block
  continuation.

## Testing

- Added coverage for manifest filtering and option preservation.
- Added coverage for background execution, interaction with regular stop
  hooks, and non-blocking turn completion.

GitOrigin-RevId: c0f75f83a23ba8a83bb3a5d5997c4882aacc32d6
2026-08-21 21:01:59 +00:00
cgst-oai
a26d50852a Require filesystem backends to implement directory walks (#39749)
## What changed

- Make `ExecutorFileSystem::walk` a required backend operation instead of
  providing a fallback built from directory reads and metadata requests.
- Implement bounded local walks on a blocking task with cancellation, symlink
  cycle detection, deterministic ordering, error collection, and response-size
  limits.
- Have remote filesystems use the server's walk operation directly.

## Testing

- Cover local and remote handling of invalid roots and limits, directory
  symlinks, non-UTF-8 names, cancellation, sandbox contexts, and response
  budgets.

GitOrigin-RevId: 7499bf05080c3f9965a5eb7ffd593de604d62c2a
2026-08-20 17:16:52 +00:00
rhan-oai
8c828b18d6 Remove private executor directory creation (#39736)
## What changed

- Create remote plugin metrics directories through the standard executor filesystem API.
- Remove the `private` directory-creation protocol option and its platform-specific handling.
- Update the executor temporary-directory documentation to describe child-visible sidecars without an owner-private guarantee.

GitOrigin-RevId: 9a8532403a3ad2bf998281735be0b668893918c9
2026-08-20 16:22:45 +00:00
pakrym-oai
e3e5ad2847 Harden unsandboxed patch filesystem access (#39659)
## Why

An `apply_patch` path can be replaced with a symlink after verification, allowing an unsandboxed patch operation to reach a different file than the one that was approved.

## What changed

- Add `follow_symlinks` options to executor filesystem reads, writes, metadata lookups, directory creation, and removal, including the corresponding `followSymlinks` protocol fields.
- Implement no-follow filesystem operations on Unix and Windows that reject links in any path component and restrict file access to regular files.
- Run `apply_patch` with symlink traversal disabled when an otherwise-required sandbox is bypassed, while retaining the existing follow-symlink default for standalone callers.

## Testing

- Cover leaf and ancestor symlinks across patch add, update, delete, and move operations, including a path swap after verification.
- Exercise local and remote no-follow filesystem behavior, concurrent directory creation, special-file rejection, and Windows reparse points.

GitOrigin-RevId: 43fd479084891493ce13564fbd894b98f329c6dd
2026-08-20 08:10:08 +00:00
willwang-openai
8f4a48a6ad Keep marketplace upgrade state out of config (#39595)
## What changed

- Stop writing `last_updated` and `last_revision` to marketplace entries in
  `config.toml`; keep the activated revision in
  `.codex-marketplace-install.json` instead.
- Use installed marketplace metadata to detect up-to-date checkouts.
- Snapshot the installed marketplace before activation and roll back a stale
  upgrade if another installation changed the destination concurrently.

## Testing

- Verify marketplace add and upgrade operations leave `config.toml` unchanged.
- Cover restoring a newer concurrently installed marketplace when a stale
  activation is rejected.

GitOrigin-RevId: 10942c3fc7c6c3f68b7d5953e8c1b5e86bf71866
2026-08-20 05:24:56 +00:00
xli-oai
e7c0e8eb9f Harden plugin manifest handling during installation (#39590)
## Why

Plugin installation skips symlinks while copying a plugin into the cache. A
symlinked manifest could therefore be used during source validation but omitted
from the staged copy, allowing a lower-precedence manifest to take its place.

## What changed

- Require discoverable manifests and their parent directories to be regular
  files and directories, rejecting symlinks and other non-regular entries at a
  higher-precedence manifest path.
- Verify that staging preserves the selected manifest path and contents before
  activating the cached plugin.
- Preserve generated fallback manifests by injecting and validating them in the
  staged plugin.

## Testing

Add coverage for symlinked manifest files and directories, precedence changes,
and fallback-manifest staging.

GitOrigin-RevId: 1b69c1e75cdfecb8cab4070a32aa9739833a70de
2026-08-20 05:10:57 +00:00
jif
6141747444 Test plugin sync isolation from repository Git config (#39585)
## Why

The pre-trust remote lookup must not inherit Git configuration from the
repository that launched Codex, where URL rewrites can invoke custom transport
helpers during an automatic plugin sync.

## What changed

- Add a Unix regression test that runs the startup lookup from a repository
  with a local `insteadOf` rewrite to an `ext` transport and verifies that the
  helper is not executed.
- Reuse `OPENAI_PLUGINS_GIT_URL` for the lookup so the production command and
  regression fixture target the same remote.

GitOrigin-RevId: e53af4a82a4206c31bf0f4733f908dcc064a4795
2026-08-20 04:59:20 +00:00
Charlie Marsh
ffad922340 Isolate automatic plugin Git operations (#39520)
## Why

Background marketplace and plugin refreshes can otherwise inherit repository-local or command-scoped Git configuration from the project that launched Codex. That configuration can redirect remotes or invoke Git helpers during an automatic operation.

## What changed

- Run automatic marketplace upgrades, plugin cache refreshes, and curated marketplace lookups with repository-scoped Git environment variables removed and a temporary trusted repository under the Codex home.
- Carry the automatic/manual trust mode through marketplace upgrades and plugin materialization.
- Preserve the caller's Git configuration for explicit marketplace upgrades, plugin installs, and refreshes.

## Testing

- Add regression coverage for repository URL rewrites, protocol helpers, command-scoped configuration, and manual Git filters.

GitOrigin-RevId: 957f45fa3bd7ce7e1b83355f276cf65dc5e99c8e
2026-08-19 17:34:00 +00:00
Matthew Zeng
a998c7a1ce Deduplicate remote plugin bundle syncs with shared semaphores (#39240)
## What changed

- Give plugin managers for the same cache root a shared semaphore that permits
  only one background installed-plugin bundle sync at a time.
- Hold the permit for the lifetime of the spawned sync task and refresh the
  installed-plugin cache after a successful local cache change.

## Testing

- Add a test that starts bundle syncs from two plugin managers sharing a Codex
  home and verifies that only one request is made.

GitOrigin-RevId: 86c39476c3a9015b9862ab75e8f11f110b0284fc
2026-08-18 17:42:48 +00:00
Eric Traut
0acf302db5 Prevent marketplace identity spoofing (#39165)
## Why

Repository manifests and user-configured sources must not be able to claim names reserved for managed or remote marketplaces.

## What changed

- Reject reserved marketplace names from unmanaged sources during discovery, installation, configuration projection, and configured marketplace upgrades, even when source restrictions are disabled.
- Recognize managed marketplaces only at their expected paths. Preserve the required macOS and Windows path equivalences without allowing symlink aliases to inherit managed provenance.

## Testing

- Cover reserved-name rejection for plugin list and install RPCs, configured upgrades, unrestricted policy, and remote marketplace names.
- Cover symlink spoofing and Windows managed-path normalization.

GitOrigin-RevId: a610bdc382857f306dd3e244f0992de2ec279673
2026-08-18 07:56:41 +00:00
Dylan Hurd
4216123b3d Require approval for commands with dynamic shell words (#39159)
## Why

Tree-sitter can represent brace expansions, globs, and escaped text as plain
words even though the shell changes them at runtime. Treating their source text
as literal argv could let a command match a safe-command check or allow rule
that does not match what will actually execute.

## What changed

- Reject unquoted Bash and Zsh words containing expansion, glob, or escape
  syntax from literal command parsing, including heredoc command prefixes.
- Reject double-quoted escape sequences that the shell removes or interprets,
  while continuing to accept quoted metacharacters that remain literal.
- Require approval for affected commands under `UnlessTrusted`, even when a
  policy contains an allow rule for the unexpanded source text.

## Testing

Add parser and approval scenarios covering brace expansion, globs, escapes,
Zsh-specific syntax, heredocs, and quoted literals.

GitOrigin-RevId: 31f2c6062680c42ac65362e3f3eebfaaf4eb71da
2026-08-18 07:26:21 +00:00
Matthew Zeng
de7bbb0481 Hydrate recommended plugin metadata on selection (#39143)
## What changed

- Fetch recommendations from the Codex-specific `/ps/plugins/suggested/codex` endpoint and parse its compact response shape.
- Fetch the selected plugin's details before presenting an install request, using them to verify availability and populate connector metadata.
- Skip install elicitation when the selected recommendation is no longer available, and return a retryable response when its metadata cannot be verified.

## Testing

- Cover the new recommendation route and response shape.
- Cover metadata hydration for available plugins and rejection of unavailable plugins.

GitOrigin-RevId: 2b0e2d70572aae2b7cd8e458b42e9dd14be3dbaf
2026-08-18 05:42:39 +00:00
willwang-openai
fc6268ad38 Read plugin authentication state from AuthManager (#39087)
## What changed

- Give `PluginsManager` a shared `AuthManager` instead of a separately mutable authentication-mode snapshot.
- Read the current authentication mode and credentials from that shared manager for plugin discovery, startup tasks, CLI commands, MCP setup, and external-agent migration.
- Update test helpers and coverage to exercise plugin projections and curated marketplace selection as authentication changes.

GitOrigin-RevId: 600c94de5130eda2da5727e1a0b4d39083fefc56
2026-08-17 22:26:27 +00:00
jif
8ef139667f Apply user MCP policy to selected executor plugins (#39079)
## What changed

- Resolve MCP server policy directly from the effective user configuration for selected executor-plugin roots.
- Apply server enablement, tool allow/deny lists, and default and per-tool approval modes while preserving stricter plugin-declared restrictions.
- Cover policy merging and opaque selected-root IDs in the executor-plugin MCP integration tests.

GitOrigin-RevId: dce3021969ba71e642de52312449cab6277515c3
2026-08-17 20:55:04 +00:00
felixxia-oai
d24507a59b Remove skill model delegation support (#39068)
## What changed

- Stop parsing and exposing the `model` field from skill frontmatter.
- Remove the skill model delegation types and instruction generation.

GitOrigin-RevId: 01198c68c095da5062e8abec417cc3539099d9d5
2026-08-17 20:19:04 +00:00
Abhinav
e5470f1bce Refresh hook runtimes after plugin changes (#38703)
## What changed

- Rebuild hook runtimes for loaded sessions when effective plugins change or a marketplace upgrade installs new plugin content.
- Refresh plugin-related caches and MCP runtimes alongside hooks after plugin mutations.
- Preserve each loaded session's current configuration while rebuilding its hooks.

## Testing

- Cover direct plugin upgrades, including subsequent turn and session-end hooks.
- Cover automatic marketplace upgrades for an already loaded session.

GitOrigin-RevId: fef64c68d652f300c7f3d88e81c5017459aa9a18
2026-08-15 05:28:53 +00:00
felixxia-oai
3711943d11 Parse model annotations from skill frontmatter (#38467)
## What changed

- Add an optional `model` field to parsed and loaded skill metadata.
- Recognize `model: luna` while ignoring unsupported model values without
  preventing the rest of the skill metadata from loading.

## Testing

- Cover supported, absent, unsupported, and repaired frontmatter model values.

GitOrigin-RevId: 376b65555e81d29a5eae93cc4c2633aacf7cd7c8
2026-08-14 00:54:45 +00:00
willwang-openai
1da59ad257 Support per-server MCP OAuth callback ports (#38448)
## What changed

- Add `oauth.callback_port` to MCP server configuration and preserve it when
  serializing configuration edits.
- Accept `oauth.callbackPort` from plugin MCP declarations and skill dependency
  metadata.
- Prefer the server-specific callback port over `mcp_oauth_callback_port` for
  CLI login, app-server, plugin installation, executor, and skill dependency
  OAuth flows.

## Testing

- Cover configuration parsing, serialization, and fallback behavior.
- Verify plugin, executor, and skill OAuth registrations use their configured
  callback ports instead of the global port.

GitOrigin-RevId: 7f65e5e7869358307e49779f1b75e8672b607736
2026-08-13 22:42:12 +00:00
willwang-openai
f898ebcafd Route curated plugin catalogs by authentication mode (#38429)
## Why

The model provider does not reliably identify which curated plugin catalog is
available. ChatGPT authentication can be used with a custom provider, while an
unauthenticated session should use the API-compatible catalog regardless of its
provider.

## What changed

- Select the ChatGPT curated catalog only for authentication modes that use the
  Codex backend; use the API curated catalog for API-key and unauthenticated
  sessions.
- Initialize standalone plugin managers with the current authentication mode
  across CLI, app-server, MCP, and external-agent migration paths.
- Preserve authentication mode while detecting and importing migrated plugins.

## Testing

- Cover catalog and skill routing across ChatGPT, API-key, unauthenticated,
  Bedrock, and custom-provider configurations.
- Verify authenticated plugin migration uses the ChatGPT curated marketplace.

GitOrigin-RevId: 660a339ee8891c33aad961078d3a979242a6a166
2026-08-13 20:20:01 +00:00
Kyle Brown
9579479d28 Collect plugin metrics from remote executors (#38283)
## What changed

- Resolve manifest-declared metric operations against the executor filesystem for remote plugin commands.
- Create the measurement sidecar in an executor-native, owner-private temporary directory, stream its bounded output back for validation, and clean up the directory afterward.
- Extend the exec-server protocol with the executor temporary directory and atomic private-directory creation.

## Testing

- Cover remote unified-exec measurements for foreground and background commands.
- Verify private directories use owner-only permissions on Unix and fail closed on unsupported platforms.

GitOrigin-RevId: dbbd0a84717b91237fc5728e510e18994eb46dd4
2026-08-13 00:39:04 +00:00
Kyle Brown
9ca0337dbf Collect metrics from plugin shell commands (#38252)
## What changed

- Provide matching local plugin commands with a sandbox-writable temporary output file through `CODEX_PLUGIN_METRICS_OUTPUT` when analytics is enabled.
- Validate successful command output against the plugin's `analytics.yaml` declaration, including measurement names, enum dimensions, finite values, duplicate rows, and size limits, before publishing analytics events.
- Keep the output path reserved from user overrides and clean up the temporary file after execution.

## Testing

- Cover output validation, limits, cleanup, sandbox permissions, environment handling, and path replacement.
- Verify measurement collection through both classic and zsh-fork shell runtimes.

GitOrigin-RevId: 88af0f87dc2f207fcbcca6af498f5c940d79349d
2026-08-12 21:23:21 +00:00