## 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
## What changed
- Use `statx` for no-follow metadata on Linux so `created_at_ms` includes the birth time when the filesystem provides it, with a fallback for unavailable or blocked `statx` calls.
- Mark files and directories for deletion explicitly on Windows after opening them without traversing reparse points.
- Cover create, write, metadata, remove, and link-rejection behavior for local and remote filesystems, including sandboxed execution on Linux and Windows.
## Testing
- Add Linux coverage for preserving birth time in no-follow metadata.
- Add cross-platform coverage for sandboxed no-follow operations and removal of files and empty directories.
GitOrigin-RevId: 1bc531669839bf5d033aa4a215220ed1cc5f63d5
## 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
## Why
Filesystem permission paths can use a convention that differs from the host
running Codex. Converting them immediately to native absolute paths can change
the meaning of ambiguous paths such as `/C:/secret` or Windows UNC paths.
## What changed
- Store literal filesystem permission paths as `PathUri` values through the
runtime policy and execution protocol.
- Keep legacy string-based serialization at explicit protocol boundaries and
reject conversions that cannot be represented losslessly.
- Encode native paths as opaque URIs when a normal file URI would imply the
wrong path convention.
## Testing
Added coverage for cross-platform and ambiguous path round trips, UNC path
variants, permission-profile serialization, and deny-policy enforcement.
GitOrigin-RevId: 5247713796d1f2bb4e02f94eb9fc82d4698060f0
## Why
Filesystem helpers only need access to their own executables. Granting access to
the containing directories also makes unrelated sibling files readable.
## What changed
- Allow filesystem helpers to read the Codex and Linux sandbox executables
directly instead of their parent directories.
- Give macOS filesystem helpers a narrower Seatbelt profile that omits the
normal process sandbox's `/Applications` read access.
- Preserve the existing platform defaults for normal sandboxed processes.
## Testing
Add unit and integration coverage for direct and symlinked sibling-file access,
sandboxed copies, allowed workspace reads, and the macOS-specific Seatbelt
profiles.
GitOrigin-RevId: 9380c6868a695bdf2275baa74bd5e8a30a64ba1b
## Why
Streaming reads previously rejected requests that used a platform filesystem
sandbox.
## What changed
- Open streamed files in the sandbox helper and return the open file to the
exec-server by passing a file descriptor on Unix or duplicating a file handle
on Windows.
- Advertise support through the `sandboxedFileStreaming` environment capability.
- Preserve close-on-exec behavior for transferred descriptors, including the
required inherited-descriptor cleanup on macOS.
## Testing
- Cover bounded sandboxed streams, continued reads after path replacement, and
rejection of symlink escapes outside readable roots.
GitOrigin-RevId: 677b2444b74e834b78b87a8554bc119c1c6e08b2
## Why
Cross-platform remote `apply_patch` calls were rejected when filesystem writes
were restricted because patch verification and writes could not be safely
performed against executor files.
## What changed
- Route intercepted and direct remote patches through the executor-managed
filesystem sandbox, including the configured workspace roots.
- Select the restricted-token sandbox for Windows executor paths when no
Windows sandbox level was configured.
- Fail closed when an executor cannot enforce the requested sandbox, and treat
executor-managed access failures as sandbox denials so approval can retry the
patch without sandboxing.
## Testing
- Cover sandboxed remote patches, denied writes, approval retries, Windows
sandbox selection, and executor filesystem enforcement.
GitOrigin-RevId: caddeed0b266c456a689080a14a3a58e2bd7887c
## Why
Default read-only protections for project metadata should apply when paths such
as `.git`, `.agents`, and `.codex` exist, without causing sandbox setup to
materialize missing paths as ACL targets.
## What changed
- Add an optional `missing_path_behavior` to filesystem sandbox entries and
mark default project-metadata protections with `skip`.
- Preserve the behavior through permission transforms and exec/MCP protocol
serialization while keeping existing path wire variants stable.
- Ignore skip-missing entries when projecting configuration or Windows sandbox
overrides, while retaining explicit metadata carveouts.
## Testing
- Cover protocol round trips for path and special-path entries.
- Verify default metadata protections and Windows explicit carveout handling.
GitOrigin-RevId: 6df13dadacdd131c44aab9f15a967c81051355c1
Why
Filtering hidden directories after a walk is too late: their descendants
consume traversal limits, and canonical directory deduplication can let
a hidden path claim a target before a visible symlink reaches it.
What this changes
- Add an optional pruneHiddenDirectories walk option. It defaults to
false and is omitted from the wire when disabled.
- Return hidden directory entries, but do not traverse them or add their
canonical identities to the visited set.
- Cover the visible-symlink-to-hidden-directory case through both local
and remote filesystem implementations.
This is the small filesystem prerequisite for #31566. Skill-specific
behavior remains in that PR.
Stack 3 of 3. Stacked on #29842.
## What changes
Adds an opt-in `followDirectorySymlinks` setting to `fs/walk`.
When enabled, the walk follows directory symlinks but continues to
ignore symlinked files. Canonical directory identities prevent symlink
cycles, while normal paths keep their existing spelling.
Environment skill discovery enables the setting so symlinked skill
directories continue to work with the new single-RPC scan.
Stack 1 of 3. Follow-ups: #29842 and #29844.
## What changes
Adds a general bounded `fs/walk` operation to the exec server.
The operation returns file and directory entries plus recoverable
per-path errors. It skips symlinks, preserves the existing filesystem
sandbox routing, and enforces depth, directory, entry, and response-size
limits.
This PR only defines and wires the filesystem operation. It does not
change any callers yet.
## Why
Downstream refactors are producing confusing code with this
functionality having a very generic name. Encoding the specific
conversion approach in the method name makes it clearer.
## What
Rename `PathUri::from_path` to `PathUri::from_host_native_path` and
update its Rust call sites.
## Why
`fs/readFile` buffers the entire file in one response, which makes large
remote reads expensive and prevents callers from applying backpressure.
We need an opt-in streaming path with bounded block sizes while
preserving the existing single-call API for small and sandboxed reads.
## What changed
- Add `ExecServerClient::stream`, returning a named `FileReadStream`
that implements `futures::Stream` and yields immutable 1 MiB byte
blocks.
- Add internal `fs/open`, `fs/readBlock`, and `fs/close` RPCs.
`fs/readBlock` accepts an explicit offset and length.
- Keep unsandboxed files open between block reads, cap open handles per
connection, and clean them up on EOF, error, stream drop, explicit
close, or connection shutdown.
- Reject platform-sandboxed streaming opens instead of turning the
one-shot sandbox helper into a persistent server. Existing `fs/readFile`
behavior is unchanged.
## Testing
- `just test -p codex-exec-server`
- Integration coverage for 1 MiB chunking, exact block-boundary EOF,
sandbox rejection, and continued reads from the opened file after path
replacement.
- Handle-manager coverage for non-sequential offsets, variable block
lengths, the 128-handle limit, and capacity release after close.
The workspace denies `clippy::expect_used` in production. Although
`clippy.toml` allows `expect` in tests, Bazel Clippy compiles
integration-test helper code in a way that does not receive that
exemption, which encouraged verbose `unwrap_or_else(... panic!(...))`
and equivalent `match`/`let else` forms.
This allows `clippy::expect_used` once at each integration-test crate
root (including aggregated suites and test-support libraries), then
replaces manual panic-based Result and Option unwraps with
`expect`/`expect_err`. Standalone `tests/*.rs` files remain their own
crate roots. Intentional assertion and unexpected-variant panics remain
unchanged, and the production `expect_used = "deny"` lint remains in
place.
The cleanup is mechanical and net-negative in line count.
## Why
Progress towards letting app-server and exec-server run on different
platforms, specifically for sandbox configuration.
## What
- Make the filesystem path containment hierarchy generic, defaulting to
`AbsolutePathBuf` for now.
- Have clients specify `AbsolutePathBuf` or `PathUri` directly where
needed.
- Use `PathUri` throughout exec-server filesystem protocol and trait
boundaries.
- Implement `From` for conversion to path URIs and `TryFrom` for
fallible conversion to absolute paths through the generic type
hierarchy.
## Why
`ExecutorFileSystem::get_metadata` reports file kind and timestamps but
not size. Internal callers that need to enforce a size limit therefore
have to read the complete file first, which is especially wasteful for
remote filesystems.
This adds the missing internal metadata so consumers can reject
oversized files before transferring or buffering them. The field is
named `size`, matching VS Code's `FileStat.size` filesystem convention.
## What changed
- add `size: u64` to internal `FileMetadata`
- populate it from the underlying filesystem metadata
- carry it through sandbox-helper and remote exec-server responses
- cover files, directories, symlink targets, and sandboxed reads across
local and remote filesystem implementations
The new field is intentionally not exposed through the app-server API.
## Testing
- `just test -p codex-exec-server get_metadata`
- `just test -p codex-exec-server
file_system_sandboxed_metadata_and_read_allow_readable_root`
- `just test -p codex-core-plugins`
- `just test -p codex-skills-extension`
## Why
We're moving exec-server to use PathUri for its internal path
representations.
## What
Move `ExecutorFileSystem` APIs to use `PathUri` instead of
`AbsolutePathBuf`. Future changes will convert higher-level parts of
exec-server.
## Why
The exec-server's existing filesystem tests only run on `#[cfg(unix)]`.
We should be running the applicable ones on Windows, and also include
the basic filesystem operations that will be modified by migrating to
`PathUri`.
## What
Split platform-neutral local/remote tests into a shared Unix/Windows
suite while keeping the existing `AbsolutePathBuf` API, and add Windows
junction canonicalization coverage.