Commit Graph

15294 Commits

Author SHA1 Message Date
Michael Bolin
c6975ba8f2 merge commit for archive created by Sapling 2026-05-12 01:26:15 -07:00
Michael Bolin
a35e4950a1 permissions: move workspace roots onto thread state 2026-05-12 01:25:56 -07:00
Michael Bolin
dda4a112b3 Merge 4d132d961b into sapling-pr-archive-bolinfest 2026-05-12 01:14:29 -07:00
Michael Bolin
4d132d961b permissions: move workspace roots onto thread state 2026-05-12 01:14:21 -07:00
Michael Bolin
3005eaa473 merge commit for archive created by Sapling 2026-05-12 01:01:37 -07:00
Michael Bolin
3de8c8050a permissions: move workspace roots onto thread state 2026-05-12 01:01:23 -07:00
Michael Bolin
a65d01cc43 merge commit for archive created by Sapling 2026-05-12 00:44:58 -07:00
Michael Bolin
c09cd6bb80 permissions: move workspace roots onto thread state 2026-05-12 00:44:50 -07:00
Michael Bolin
cec71ec922 merge commit for archive created by Sapling 2026-05-12 00:27:24 -07:00
Michael Bolin
1c8ec84334 permissions: move workspace roots onto thread state 2026-05-12 00:27:01 -07:00
Michael Bolin
6c2578fcd4 core: box multi-agent handler futures 2026-05-12 00:26:54 -07:00
Michael Bolin
d3272bf2cc Merge 64831d864e into sapling-pr-archive-bolinfest 2026-05-11 23:49:51 -07:00
Michael Bolin
64831d864e permissions: move workspace roots onto thread state 2026-05-11 23:34:10 -07:00
Michael Bolin
44831f4b8a core: box multi-agent handler futures 2026-05-11 23:25:32 -07:00
Michael Bolin
17caa3806c merge commit for archive created by Sapling 2026-05-11 23:15:16 -07:00
Michael Bolin
1d595488ff Move workspace roots onto thread/session state and stop using active permission profile modifications as an overlay for writable roots. Existing app-server threads no longer accept arbitrary PermissionProfile or SandboxPolicy replacements; permissions requests select a server-known profile id and apply the resolved server-owned profile together with active profile metadata. Workspace roots can be updated independently, and SandboxPolicy::WorkspaceWrite no longer stores its own writable_roots. 2026-05-11 23:15:10 -07:00
viyatb-oai
46f30d0282 feat(sandbox): add Windows deny-read parity (#18202)
## Why

The split filesystem policy stack already supports exact and glob
`access = none` read restrictions on macOS and Linux. Windows still
needed subprocess handling for those deny-read policies without claiming
enforcement from a backend that cannot provide it.

## Key finding

The unelevated restricted-token backend cannot safely enforce deny-read
overlays. Its `WRITE_RESTRICTED` token model is authoritative for write
checks, not read denials, so this PR intentionally fails that backend
closed when deny-read overrides are present instead of claiming
unsupported enforcement.

## What changed

This PR adds the Windows deny-read enforcement layer and makes the
backend split explicit:

- Resolves Windows deny-read filesystem policy entries into concrete ACL
targets.
- Preserves exact missing paths so they can be materialized and denied
before an enforceable sandboxed process starts.
- Snapshot-expands existing glob matches into ACL targets for Windows
subprocess enforcement.
- Honors `glob_scan_max_depth` when expanding Windows deny-read globs.
- Plans both the configured lexical path and the canonical target for
existing paths so reparse-point aliases are covered.
- Threads deny-read overrides through the elevated/logon-user Windows
sandbox backend and unified exec.
- Applies elevated deny-read ACLs synchronously before command launch
rather than delegating them to the background read-grant helper.
- Reconciles persistent deny-read ACEs per sandbox principal so policy
changes do not leave stale deny-read ACLs behind.
- Fails closed on the unelevated restricted-token backend when deny-read
overrides are present, because its `WRITE_RESTRICTED` token model is not
authoritative for read denials.

## Landed prerequisites

These prerequisite PRs are already on `main`:

1. #15979 `feat(permissions): add glob deny-read policy support`
2. #18096 `feat(sandbox): add glob deny-read platform enforcement`
3. #17740 `feat(config): support managed deny-read requirements`

This PR targets `main` directly and contains only the Windows deny-read
enforcement layer.

## Implementation notes

- Exact deny-read paths remain enforceable on the elevated path even
when they do not exist yet: Windows materializes the missing path before
applying the deny ACE, so the sandboxed command cannot create and read
it during the same run.
- Existing exact deny paths are preserved lexically until the ACL
planner, which then adds the canonical target as a second ACL target
when needed. That keeps both the configured alias and the resolved
object covered.
- Windows ACLs do not consume Codex glob syntax directly, so glob
deny-read entries are expanded to the concrete matches that exist before
process launch.
- Glob traversal deduplicates directory visits within each pattern walk
to avoid cycles, without collapsing distinct lexical roots that happen
to resolve to the same target.
- Persistent deny-read ACL state is keyed by sandbox principal SID, so
cleanup only removes ACEs owned by the same backend principal.
- Deny-read ACEs are fail-closed on the elevated path: setup aborts if
mandatory deny-read ACL application fails.
- Unelevated restricted-token sessions reject deny-read overrides early
instead of running with a silently unenforceable read policy.

## Verification

- `cargo test -p codex-core
windows_restricted_token_rejects_unreadable_split_carveouts`
- `just fmt`
- `just fix -p codex-core`
- `just fix -p codex-windows-sandbox`
- GitHub Actions rerun is in progress on the pushed head.

---------

Co-authored-by: Codex <noreply@openai.com>
2026-05-11 23:04:28 -07:00
Michael Bolin
384be7c401 merge commit for archive created by Sapling 2026-05-11 23:00:17 -07:00
Michael Bolin
f6eacf7452 Move workspace roots onto thread/session state and stop using active permission profile modifications as an overlay for writable roots. Existing app-server threads no longer accept arbitrary PermissionProfile or SandboxPolicy replacements; permissions requests select a server-known profile id and apply the resolved server-owned profile together with active profile metadata. Workspace roots can be updated independently, and SandboxPolicy::WorkspaceWrite no longer stores its own writable_roots. 2026-05-11 23:00:07 -07:00
Michael Bolin
0e1c85378d merge commit for archive created by Sapling 2026-05-11 22:45:11 -07:00
Michael Bolin
f7e604e277 Move workspace roots onto thread/session state and stop using active permission profile modifications as an overlay for writable roots. Existing app-server threads no longer accept arbitrary PermissionProfile or SandboxPolicy replacements; permissions requests select a server-known profile id and apply the resolved server-owned profile together with active profile metadata. Workspace roots can be updated independently, and SandboxPolicy::WorkspaceWrite no longer stores its own writable_roots. 2026-05-11 22:44:54 -07:00
Michael Bolin
5f9073fa9c Merge 9f47eab75f into sapling-pr-archive-bolinfest 2026-05-11 22:39:06 -07:00
Michael Bolin
9f47eab75f Move workspace roots onto thread/session state and stop using active permission profile modifications as an overlay for writable roots. Existing app-server threads no longer accept arbitrary PermissionProfile or SandboxPolicy replacements; permissions requests select a server-known profile id and apply the resolved server-owned profile together with active profile metadata. Workspace roots can be updated independently, and SandboxPolicy::WorkspaceWrite no longer stores its own writable_roots. 2026-05-11 22:38:59 -07:00
pakrym-oai
c9e46ed639 [codex] Make handlers own parallel tool support (#22254)
## Why

`ToolRouter::tool_supports_parallel()` was still consulting configured
specs when a handler lookup missed, even though parallel schedulability
is really a property of the executable handler. Keeping that metadata on
`ConfiguredToolSpec` duplicated state between the model-visible spec
layer and the runtime handler layer.

This change makes handlers the sole source of truth for parallel tool
support and removes the extra spec wrapper that only existed to carry
duplicated metadata.

## What changed

- removed `ConfiguredToolSpec` and store plain `ToolSpec` values in the
registry/router builder path
- changed `ToolRouter::tool_supports_parallel()` to consult only the
handler registry and fall back to `false`
- simplified spec collection and test helpers to operate directly on
`ToolSpec`
- updated router/spec tests to cover handler-owned parallel behavior and
the no-handler fallback

## Validation

- `cargo test -p codex-tools`
- `cargo test -p codex-core mcp_parallel_support_uses_handler_data`
- `cargo test -p codex-core
deferred_responses_api_tool_serializes_with_defer_loading`
- `cargo test -p codex-core
tools_without_handlers_do_not_support_parallel`
- `cargo test -p codex-core
request_plugin_install_can_be_registered_without_search_tool`

## Docs

No documentation updates needed.
2026-05-11 22:26:33 -07:00
Michael Bolin
423b398021 merge commit for archive created by Sapling 2026-05-11 22:23:08 -07:00
Michael Bolin
256e425968 Move workspace roots onto thread/session state and stop using active permission profile modifications as an overlay for writable roots. Existing app-server threads no longer accept arbitrary PermissionProfile or SandboxPolicy replacements; permissions requests select a server-known profile id and apply the resolved server-owned profile together with active profile metadata. Workspace roots can be updated independently, and SandboxPolicy::WorkspaceWrite no longer stores its own writable_roots. 2026-05-11 22:22:55 -07:00
Michael Bolin
bbc534fdf5 merge commit for archive created by Sapling 2026-05-11 20:48:56 -07:00
Michael Bolin
6952c687a7 Move workspace roots onto thread/session state and stop using active permission profile modifications as an overlay for writable roots. Existing app-server threads no longer accept arbitrary PermissionProfile or SandboxPolicy replacements; permissions requests select a server-known profile id and apply the resolved server-owned profile together with active profile metadata. Workspace roots can be updated independently, and SandboxPolicy::WorkspaceWrite no longer stores its own writable_roots. 2026-05-11 20:48:42 -07:00
Michael Bolin
583b323f30 merge commit for archive created by Sapling 2026-05-11 20:38:08 -07:00
Michael Bolin
56cf31709f Move workspace roots onto thread/session state and stop using active permission profile modifications as an overlay for writable roots. Existing app-server threads now preserve their persisted PermissionProfile value across resume, fork, and turn updates; permissions requests on existing threads only update the active named profile after validating it exists. Workspace roots can be updated independently, and SandboxPolicy::WorkspaceWrite no longer stores its own writable_roots. 2026-05-11 20:37:56 -07:00
Michael Bolin
4ca6efdba1 merge commit for archive created by Sapling 2026-05-11 20:08:33 -07:00
Michael Bolin
8210503007 Move workspace roots onto thread/session state and stop using active permission profile modifications as an overlay for writable roots. Existing app-server threads now preserve their persisted PermissionProfile value across resume, fork, and turn updates; permissions requests on existing threads only update the active named profile after validating it exists. Workspace roots can be updated independently, and SandboxPolicy::WorkspaceWrite no longer stores its own writable_roots. 2026-05-11 20:08:16 -07:00
Michael Bolin
c8ba58b46a Merge 5d0c7dea61 into sapling-pr-archive-bolinfest 2026-05-11 19:54:59 -07:00
Michael Bolin
5d0c7dea61 Move workspace roots onto thread/session state and stop using active permission profile modifications as an overlay for writable roots. Existing app-server threads now preserve their persisted PermissionProfile value across resume, fork, and turn updates; permissions requests on existing threads only update the active named profile after validating it exists. Workspace roots can be updated independently, and SandboxPolicy::WorkspaceWrite no longer stores its own writable_roots. 2026-05-11 19:54:51 -07:00
pakrym-oai
79c65f816c [codex] Filter legacy warning messages during compaction (#22243)
## Why

Older sessions can contain model-warning records persisted as `user`
messages, including the unified exec process-limit warning, the
`apply_patch`-via-`exec_command` warning, and the model-mismatch
high-risk cyber fallback warning. Those warnings are no longer produced
as conversation history items, but when old sessions compact they should
still be recognized as injected context rather than preserved as real
user turns.

## What changed

- Removed `record_model_warning` and the production paths that emitted
these warning messages into conversation history.
- Added `LegacyUnifiedExecProcessLimitWarning`,
`LegacyApplyPatchExecCommandWarning`, and `LegacyModelMismatchWarning`
contextual fragments that are used only for matching old persisted
messages.
- Registered the legacy fragments with contextual user message detection
so compaction filters them through the existing fragment path.
- Added focused compaction coverage for old warning messages being
dropped during compacted-history processing.

## Testing

- `cargo test -p codex-core warning`
- `just fix -p codex-core`
2026-05-11 19:51:51 -07:00
Michael Bolin
58af6a52c4 merge commit for archive created by Sapling 2026-05-11 19:50:03 -07:00
Michael Bolin
5801edb3eb Move workspace roots onto thread/session state and stop using active permission profile modifications as an overlay for writable roots. Existing app-server threads now preserve their persisted PermissionProfile value across resume, fork, and turn updates; permissions requests on existing threads only update the active named profile after validating it exists. Workspace roots can be updated independently, and SandboxPolicy::WorkspaceWrite no longer stores its own writable_roots. 2026-05-11 19:49:51 -07:00
Abhinav
d08906a944 Support PreToolUse updatedInput rewrites (#20527)
## Why

`PreToolUse` already exposes `updatedInput` in its hook output schema,
but Codex currently rejects it instead of applying the rewrite. That
leaves hook authors unable to make the documented pre-execution
adjustment to a tool call before it runs.

## What

- Accept `updatedInput` from `PreToolUse` hooks when paired with
`permissionDecision: "allow"`.
- Apply the rewritten input before dispatch so the tool executes the
updated payload, not the original one.
- Preserve the stable hook-facing compatibility shapes that
participating tool handlers expose:
- Bash-like tools (`shell`, `container.exec`, `local_shell`,
`shell_command`, `exec_command`) use `{ "command": ... }`.
- `apply_patch` exposes its patch body through the same command-shaped
hook contract.
  - MCP tools expose their JSON argument object directly.
- Keep each participating tool handler responsible for translating
hook-facing `updatedInput` back into its concrete invocation shape.

## Verification

Direct Bash-like rewrite coverage:

- `pre_tool_use_rewrites_shell_before_execution`
- `pre_tool_use_rewrites_container_exec_before_execution`
- `pre_tool_use_rewrites_local_shell_before_execution`
- `pre_tool_use_rewrites_shell_command_before_execution`
- `pre_tool_use_rewrites_exec_command_before_execution`

These cases assert that each supported Bash-like surface runs only the
rewritten command while the hook still observes the original `{
"command": ... }` input.

`pre_tool_use_rewrites_apply_patch_before_execution`

- Model emits one patch.
- Hook swaps in a different patch.
- Asserts only the rewritten file is created, and the hook saw the
original patch.

`pre_tool_use_rewrites_code_mode_nested_exec_command_before_execution`

- Model runs one nested shell command from code mode.
- Hook rewrites it.
- Asserts only the rewritten command runs, and the hook saw the original
nested input.

`pre_tool_use_rewrites_mcp_tool_before_execution`

- Model calls the RMCP echo tool.
- Hook rewrites the MCP arguments.
- Asserts the MCP server receives and returns the rewritten message, not
the original one.
2026-05-11 22:27:24 -04:00
Michael Bolin
1bd15bc24a merge commit for archive created by Sapling 2026-05-11 19:06:38 -07:00
Michael Bolin
d824faf0dc Move workspace roots onto thread/session state and stop using active permission profile modifications as an overlay for writable roots. Existing app-server threads now preserve their persisted PermissionProfile value across resume, fork, and turn updates; permissions requests on existing threads only update the active named profile after validating it exists. Workspace roots can be updated independently, and SandboxPolicy::WorkspaceWrite no longer stores its own writable_roots. 2026-05-11 19:06:28 -07:00
starr-openai
17ed5ad0b0 Apply sandbox context to local view_image reads (#21861)
## Summary
- create a selected-cwd filesystem sandbox context for view_image
metadata and file reads in both local and remote environments
- add a local restricted-profile regression test for the previously
unsandboxed read path

## Validation
- just fmt
- bazel test --bes_backend= --bes_results_url= --test_output=errors
--test_filter=view_image::tests::handle_passes_sandbox_context_for_local_filesystem_reads
//codex-rs/core:core-unit-tests

---------

Co-authored-by: Codex <noreply@openai.com>
2026-05-11 18:48:43 -07:00
Michael Bolin
c0a3e2bc63 merge commit for archive created by Sapling 2026-05-11 18:40:33 -07:00
Michael Bolin
448ea1b930 Move workspace roots onto thread/session state and stop using active permission profile modifications as an overlay for writable roots. Existing app-server threads now preserve their persisted PermissionProfile value across resume, fork, and turn updates; permissions requests on existing threads only update the active named profile after validating it exists. Workspace roots can be updated independently, and SandboxPolicy::WorkspaceWrite no longer stores its own writable_roots. 2026-05-11 18:40:24 -07:00
Michael Bolin
583117ffa1 merge commit for archive created by Sapling 2026-05-11 18:13:13 -07:00
Michael Bolin
bb9aa31ee5 Move workspace roots onto thread/session state and stop using active permission profile modifications as an overlay for writable roots. Existing app-server threads now preserve their persisted PermissionProfile value across resume, fork, and turn updates; permissions requests on existing threads only update the active named profile after validating it exists. Workspace roots can be updated independently, and SandboxPolicy::WorkspaceWrite no longer stores its own writable_roots. 2026-05-11 18:13:04 -07:00
efrazer-oai
fd24c00b0b feat(skills): default plugin creator to personal share flow (#22221)
## Summary
Plugin creation now defaults to the personal marketplace path and ends
with a readable handoff back into Codex after a marketplace-backed
scaffold.

Before this change, `plugin-creator` centered repo-local marketplace
updates and did not clearly guide the agent to return the user to the
created plugin afterward. This PR updates the bundled system skill so
marketplace-backed scaffolds default to `~/plugins/<plugin-name>` plus
`~/.agents/plugins/marketplace.json`, ask for user intent only when an
existing repo marketplace makes personal vs team scope ambiguous, and
end with named Markdown deeplinks labeled `View <plugin-name>` and
`Share <plugin-name>`.

## What changed
- default marketplace-backed creation to the personal plugin location
- document the explicit repo/team override path for codebases that
should own the plugin entry
- ask personal vs team only when the current Git repo already has
`.agents/plugins/marketplace.json` and the user has not stated scope
- require named Markdown deeplinks after marketplace-backed creation so
the final response returns the user to the exact plugin cleanly
- keep the deeplink targets precise with real absolute `marketplacePath`
and normalized `pluginName` values
- align the bundled prompt, scaffold help text, and marketplace
reference spec with the new default

## Testing
Tests: targeted skill validation, Python compile checks,
personal-default scaffold smoke, repo-override scaffold smoke, and
whitespace checks.
2026-05-11 17:58:48 -07:00
Michael Bolin
3bb2466299 merge commit for archive created by Sapling 2026-05-11 17:58:06 -07:00
Michael Bolin
4c0a41a53d Move workspace roots onto thread/session state and stop using active permission profile modifications as an overlay for writable roots. Existing app-server threads now preserve their persisted PermissionProfile value across resume, fork, and turn updates; permissions requests on existing threads only update the active named profile after validating it exists. Workspace roots can be updated independently, and SandboxPolicy::WorkspaceWrite no longer stores its own writable_roots. 2026-05-11 17:57:58 -07:00
Michael Bolin
9077a2d7dd merge commit for archive created by Sapling 2026-05-11 17:38:35 -07:00
Michael Bolin
b191b5e546 Move workspace roots onto thread/session state and stop using active permission profile modifications as an overlay for writable roots. Existing app-server threads now preserve their persisted PermissionProfile value across resume, fork, and turn updates; permissions requests on existing threads only update the active named profile after validating it exists. Workspace roots can be updated independently, and SandboxPolicy::WorkspaceWrite no longer stores its own writable_roots. 2026-05-11 17:38:18 -07:00