feat: initial import of Rust implementation of Codex CLI in codex-rs/ (#629)
As stated in `codex-rs/README.md`:
Today, Codex CLI is written in TypeScript and requires Node.js 22+ to
run it. For a number of users, this runtime requirement inhibits
adoption: they would be better served by a standalone executable. As
maintainers, we want Codex to run efficiently in a wide range of
environments with minimal overhead. We also want to take advantage of
operating system-specific APIs to provide better sandboxing, where
possible.
To that end, we are moving forward with a Rust implementation of Codex
CLI contained in this folder, which has the following benefits:
- The CLI compiles to small, standalone, platform-specific binaries.
- Can make direct, native calls to
[seccomp](https://man7.org/linux/man-pages/man2/seccomp.2.html) and
[landlock](https://man7.org/linux/man-pages/man7/landlock.7.html) in
order to support sandboxing on Linux.
- No runtime garbage collection, resulting in lower memory consumption
and better, more predictable performance.
Currently, the Rust implementation is materially behind the TypeScript
implementation in functionality, so continue to use the TypeScript
implmentation for the time being. We will publish native executables via
GitHub Releases as soon as we feel the Rust version is usable.
2025-04-24 13:31:40 -07:00
|
|
|
|
use std::collections::HashMap;
|
|
|
|
|
|
use std::collections::HashSet;
|
|
|
|
|
|
use std::path::Component;
|
|
|
|
|
|
use std::path::Path;
|
|
|
|
|
|
use std::path::PathBuf;
|
|
|
|
|
|
|
|
|
|
|
|
use codex_apply_patch::ApplyPatchFileChange;
|
|
|
|
|
|
|
|
|
|
|
|
use crate::exec::SandboxType;
|
|
|
|
|
|
use crate::is_safe_command::is_known_safe_command;
|
|
|
|
|
|
use crate::protocol::AskForApproval;
|
|
|
|
|
|
use crate::protocol::SandboxPolicy;
|
|
|
|
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
|
|
pub enum SafetyCheck {
|
|
|
|
|
|
AutoApprove { sandbox_type: SandboxType },
|
|
|
|
|
|
AskUser,
|
|
|
|
|
|
Reject { reason: String },
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
pub fn assess_patch_safety(
|
|
|
|
|
|
changes: &HashMap<PathBuf, ApplyPatchFileChange>,
|
|
|
|
|
|
policy: AskForApproval,
|
|
|
|
|
|
writable_roots: &[PathBuf],
|
2025-05-04 10:57:12 -07:00
|
|
|
|
cwd: &Path,
|
feat: initial import of Rust implementation of Codex CLI in codex-rs/ (#629)
As stated in `codex-rs/README.md`:
Today, Codex CLI is written in TypeScript and requires Node.js 22+ to
run it. For a number of users, this runtime requirement inhibits
adoption: they would be better served by a standalone executable. As
maintainers, we want Codex to run efficiently in a wide range of
environments with minimal overhead. We also want to take advantage of
operating system-specific APIs to provide better sandboxing, where
possible.
To that end, we are moving forward with a Rust implementation of Codex
CLI contained in this folder, which has the following benefits:
- The CLI compiles to small, standalone, platform-specific binaries.
- Can make direct, native calls to
[seccomp](https://man7.org/linux/man-pages/man2/seccomp.2.html) and
[landlock](https://man7.org/linux/man-pages/man7/landlock.7.html) in
order to support sandboxing on Linux.
- No runtime garbage collection, resulting in lower memory consumption
and better, more predictable performance.
Currently, the Rust implementation is materially behind the TypeScript
implementation in functionality, so continue to use the TypeScript
implmentation for the time being. We will publish native executables via
GitHub Releases as soon as we feel the Rust version is usable.
2025-04-24 13:31:40 -07:00
|
|
|
|
) -> SafetyCheck {
|
|
|
|
|
|
if changes.is_empty() {
|
|
|
|
|
|
return SafetyCheck::Reject {
|
|
|
|
|
|
reason: "empty patch".to_string(),
|
|
|
|
|
|
};
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
match policy {
|
|
|
|
|
|
AskForApproval::OnFailure | AskForApproval::AutoEdit | AskForApproval::Never => {
|
|
|
|
|
|
// Continue to see if this can be auto-approved.
|
|
|
|
|
|
}
|
|
|
|
|
|
// TODO(ragona): I'm not sure this is actually correct? I believe in this case
|
|
|
|
|
|
// we want to continue to the writable paths check before asking the user.
|
|
|
|
|
|
AskForApproval::UnlessAllowListed => {
|
|
|
|
|
|
return SafetyCheck::AskUser;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-05-04 10:57:12 -07:00
|
|
|
|
if is_write_patch_constrained_to_writable_paths(changes, writable_roots, cwd) {
|
feat: initial import of Rust implementation of Codex CLI in codex-rs/ (#629)
As stated in `codex-rs/README.md`:
Today, Codex CLI is written in TypeScript and requires Node.js 22+ to
run it. For a number of users, this runtime requirement inhibits
adoption: they would be better served by a standalone executable. As
maintainers, we want Codex to run efficiently in a wide range of
environments with minimal overhead. We also want to take advantage of
operating system-specific APIs to provide better sandboxing, where
possible.
To that end, we are moving forward with a Rust implementation of Codex
CLI contained in this folder, which has the following benefits:
- The CLI compiles to small, standalone, platform-specific binaries.
- Can make direct, native calls to
[seccomp](https://man7.org/linux/man-pages/man2/seccomp.2.html) and
[landlock](https://man7.org/linux/man-pages/man7/landlock.7.html) in
order to support sandboxing on Linux.
- No runtime garbage collection, resulting in lower memory consumption
and better, more predictable performance.
Currently, the Rust implementation is materially behind the TypeScript
implementation in functionality, so continue to use the TypeScript
implmentation for the time being. We will publish native executables via
GitHub Releases as soon as we feel the Rust version is usable.
2025-04-24 13:31:40 -07:00
|
|
|
|
SafetyCheck::AutoApprove {
|
|
|
|
|
|
sandbox_type: SandboxType::None,
|
|
|
|
|
|
}
|
|
|
|
|
|
} else if policy == AskForApproval::OnFailure {
|
|
|
|
|
|
// Only auto‑approve when we can actually enforce a sandbox. Otherwise
|
|
|
|
|
|
// fall back to asking the user because the patch may touch arbitrary
|
|
|
|
|
|
// paths outside the project.
|
|
|
|
|
|
match get_platform_sandbox() {
|
|
|
|
|
|
Some(sandbox_type) => SafetyCheck::AutoApprove { sandbox_type },
|
|
|
|
|
|
None => SafetyCheck::AskUser,
|
|
|
|
|
|
}
|
|
|
|
|
|
} else if policy == AskForApproval::Never {
|
|
|
|
|
|
SafetyCheck::Reject {
|
|
|
|
|
|
reason: "writing outside of the project; rejected by user approval settings"
|
|
|
|
|
|
.to_string(),
|
|
|
|
|
|
}
|
|
|
|
|
|
} else {
|
|
|
|
|
|
SafetyCheck::AskUser
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
pub fn assess_command_safety(
|
|
|
|
|
|
command: &[String],
|
|
|
|
|
|
approval_policy: AskForApproval,
|
fix: overhaul SandboxPolicy and config loading in Rust (#732)
Previous to this PR, `SandboxPolicy` was a bit difficult to work with:
https://github.com/openai/codex/blob/237f8a11e11fdcc793a09e787e48215676d9b95b/codex-rs/core/src/protocol.rs#L98-L108
Specifically:
* It was an `enum` and therefore options were mutually exclusive as
opposed to additive.
* It defined things in terms of what the agent _could not_ do as opposed
to what they _could_ do. This made things hard to support because we
would prefer to build up a sandbox config by starting with something
extremely restrictive and only granting permissions for things the user
as explicitly allowed.
This PR changes things substantially by redefining the policy in terms
of two concepts:
* A `SandboxPermission` enum that defines permissions that can be
granted to the agent/sandbox.
* A `SandboxPolicy` that internally stores a `Vec<SandboxPermission>`,
but externally exposes a simpler API that can be used to configure
Seatbelt/Landlock.
Previous to this PR, we supported a `--sandbox` flag that effectively
mapped to an enum value in `SandboxPolicy`. Though now that
`SandboxPolicy` is a wrapper around `Vec<SandboxPermission>`, the single
`--sandbox` flag no longer makes sense. While I could have turned it
into a flag that the user can specify multiple times, I think the
current values to use with such a flag are long and potentially messy,
so for the moment, I have dropped support for `--sandbox` altogether and
we can bring it back once we have figured out the naming thing.
Since `--sandbox` is gone, users now have to specify `--full-auto` to
get a sandbox that allows writes in `cwd`. Admittedly, there is no clean
way to specify the equivalent of `--full-auto` in your `config.toml`
right now, so we will have to revisit that, as well.
Because `Config` presents a `SandboxPolicy` field and `SandboxPolicy`
changed considerably, I had to overhaul how config loading works, as
well. There are now two distinct concepts, `ConfigToml` and `Config`:
* `ConfigToml` is the deserialization of `~/.codex/config.toml`. As one
might expect, every field is `Optional` and it is `#[derive(Deserialize,
Default)]`. Consistent use of `Optional` makes it clear what the user
has specified explicitly.
* `Config` is the "normalized config" and is produced by merging
`ConfigToml` with `ConfigOverrides`. Where `ConfigToml` contains a raw
`Option<Vec<SandboxPermission>>`, `Config` presents only the final
`SandboxPolicy`.
The changes to `core/src/exec.rs` and `core/src/linux.rs` merit extra
special attention to ensure we are faithfully mapping the
`SandboxPolicy` to the Seatbelt and Landlock configs, respectively.
Also, take note that `core/src/seatbelt_readonly_policy.sbpl` has been
renamed to `codex-rs/core/src/seatbelt_base_policy.sbpl` and that
`(allow file-read*)` has been removed from the `.sbpl` file as now this
is added to the policy in `core/src/exec.rs` when
`sandbox_policy.has_full_disk_read_access()` is `true`.
2025-04-29 15:01:16 -07:00
|
|
|
|
sandbox_policy: &SandboxPolicy,
|
feat: initial import of Rust implementation of Codex CLI in codex-rs/ (#629)
As stated in `codex-rs/README.md`:
Today, Codex CLI is written in TypeScript and requires Node.js 22+ to
run it. For a number of users, this runtime requirement inhibits
adoption: they would be better served by a standalone executable. As
maintainers, we want Codex to run efficiently in a wide range of
environments with minimal overhead. We also want to take advantage of
operating system-specific APIs to provide better sandboxing, where
possible.
To that end, we are moving forward with a Rust implementation of Codex
CLI contained in this folder, which has the following benefits:
- The CLI compiles to small, standalone, platform-specific binaries.
- Can make direct, native calls to
[seccomp](https://man7.org/linux/man-pages/man2/seccomp.2.html) and
[landlock](https://man7.org/linux/man-pages/man7/landlock.7.html) in
order to support sandboxing on Linux.
- No runtime garbage collection, resulting in lower memory consumption
and better, more predictable performance.
Currently, the Rust implementation is materially behind the TypeScript
implementation in functionality, so continue to use the TypeScript
implmentation for the time being. We will publish native executables via
GitHub Releases as soon as we feel the Rust version is usable.
2025-04-24 13:31:40 -07:00
|
|
|
|
approved: &HashSet<Vec<String>>,
|
|
|
|
|
|
) -> SafetyCheck {
|
|
|
|
|
|
let approve_without_sandbox = || SafetyCheck::AutoApprove {
|
|
|
|
|
|
sandbox_type: SandboxType::None,
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// Previously approved or allow-listed commands
|
|
|
|
|
|
// All approval modes allow these commands to continue without sandboxing
|
|
|
|
|
|
if is_known_safe_command(command) || approved.contains(command) {
|
|
|
|
|
|
// TODO(ragona): I think we should consider running even these inside the sandbox, but it's
|
|
|
|
|
|
// a change in behavior so I'm keeping it at parity with upstream for now.
|
|
|
|
|
|
return approve_without_sandbox();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Command was not known-safe or allow-listed
|
fix: overhaul SandboxPolicy and config loading in Rust (#732)
Previous to this PR, `SandboxPolicy` was a bit difficult to work with:
https://github.com/openai/codex/blob/237f8a11e11fdcc793a09e787e48215676d9b95b/codex-rs/core/src/protocol.rs#L98-L108
Specifically:
* It was an `enum` and therefore options were mutually exclusive as
opposed to additive.
* It defined things in terms of what the agent _could not_ do as opposed
to what they _could_ do. This made things hard to support because we
would prefer to build up a sandbox config by starting with something
extremely restrictive and only granting permissions for things the user
as explicitly allowed.
This PR changes things substantially by redefining the policy in terms
of two concepts:
* A `SandboxPermission` enum that defines permissions that can be
granted to the agent/sandbox.
* A `SandboxPolicy` that internally stores a `Vec<SandboxPermission>`,
but externally exposes a simpler API that can be used to configure
Seatbelt/Landlock.
Previous to this PR, we supported a `--sandbox` flag that effectively
mapped to an enum value in `SandboxPolicy`. Though now that
`SandboxPolicy` is a wrapper around `Vec<SandboxPermission>`, the single
`--sandbox` flag no longer makes sense. While I could have turned it
into a flag that the user can specify multiple times, I think the
current values to use with such a flag are long and potentially messy,
so for the moment, I have dropped support for `--sandbox` altogether and
we can bring it back once we have figured out the naming thing.
Since `--sandbox` is gone, users now have to specify `--full-auto` to
get a sandbox that allows writes in `cwd`. Admittedly, there is no clean
way to specify the equivalent of `--full-auto` in your `config.toml`
right now, so we will have to revisit that, as well.
Because `Config` presents a `SandboxPolicy` field and `SandboxPolicy`
changed considerably, I had to overhaul how config loading works, as
well. There are now two distinct concepts, `ConfigToml` and `Config`:
* `ConfigToml` is the deserialization of `~/.codex/config.toml`. As one
might expect, every field is `Optional` and it is `#[derive(Deserialize,
Default)]`. Consistent use of `Optional` makes it clear what the user
has specified explicitly.
* `Config` is the "normalized config" and is produced by merging
`ConfigToml` with `ConfigOverrides`. Where `ConfigToml` contains a raw
`Option<Vec<SandboxPermission>>`, `Config` presents only the final
`SandboxPolicy`.
The changes to `core/src/exec.rs` and `core/src/linux.rs` merit extra
special attention to ensure we are faithfully mapping the
`SandboxPolicy` to the Seatbelt and Landlock configs, respectively.
Also, take note that `core/src/seatbelt_readonly_policy.sbpl` has been
renamed to `codex-rs/core/src/seatbelt_base_policy.sbpl` and that
`(allow file-read*)` has been removed from the `.sbpl` file as now this
is added to the policy in `core/src/exec.rs` when
`sandbox_policy.has_full_disk_read_access()` is `true`.
2025-04-29 15:01:16 -07:00
|
|
|
|
if sandbox_policy.is_unrestricted() {
|
|
|
|
|
|
approve_without_sandbox()
|
|
|
|
|
|
} else {
|
|
|
|
|
|
match get_platform_sandbox() {
|
feat: initial import of Rust implementation of Codex CLI in codex-rs/ (#629)
As stated in `codex-rs/README.md`:
Today, Codex CLI is written in TypeScript and requires Node.js 22+ to
run it. For a number of users, this runtime requirement inhibits
adoption: they would be better served by a standalone executable. As
maintainers, we want Codex to run efficiently in a wide range of
environments with minimal overhead. We also want to take advantage of
operating system-specific APIs to provide better sandboxing, where
possible.
To that end, we are moving forward with a Rust implementation of Codex
CLI contained in this folder, which has the following benefits:
- The CLI compiles to small, standalone, platform-specific binaries.
- Can make direct, native calls to
[seccomp](https://man7.org/linux/man-pages/man2/seccomp.2.html) and
[landlock](https://man7.org/linux/man-pages/man7/landlock.7.html) in
order to support sandboxing on Linux.
- No runtime garbage collection, resulting in lower memory consumption
and better, more predictable performance.
Currently, the Rust implementation is materially behind the TypeScript
implementation in functionality, so continue to use the TypeScript
implmentation for the time being. We will publish native executables via
GitHub Releases as soon as we feel the Rust version is usable.
2025-04-24 13:31:40 -07:00
|
|
|
|
// We have a sandbox, so we can approve the command in all modes
|
|
|
|
|
|
Some(sandbox_type) => SafetyCheck::AutoApprove { sandbox_type },
|
|
|
|
|
|
None => {
|
|
|
|
|
|
// We do not have a sandbox, so we need to consider the approval policy
|
|
|
|
|
|
match approval_policy {
|
|
|
|
|
|
// Never is our "non-interactive" mode; it must automatically reject
|
|
|
|
|
|
AskForApproval::Never => SafetyCheck::Reject {
|
|
|
|
|
|
reason: "auto-rejected by user approval settings".to_string(),
|
|
|
|
|
|
},
|
|
|
|
|
|
// Otherwise, we ask the user for approval
|
|
|
|
|
|
_ => SafetyCheck::AskUser,
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
fix: overhaul SandboxPolicy and config loading in Rust (#732)
Previous to this PR, `SandboxPolicy` was a bit difficult to work with:
https://github.com/openai/codex/blob/237f8a11e11fdcc793a09e787e48215676d9b95b/codex-rs/core/src/protocol.rs#L98-L108
Specifically:
* It was an `enum` and therefore options were mutually exclusive as
opposed to additive.
* It defined things in terms of what the agent _could not_ do as opposed
to what they _could_ do. This made things hard to support because we
would prefer to build up a sandbox config by starting with something
extremely restrictive and only granting permissions for things the user
as explicitly allowed.
This PR changes things substantially by redefining the policy in terms
of two concepts:
* A `SandboxPermission` enum that defines permissions that can be
granted to the agent/sandbox.
* A `SandboxPolicy` that internally stores a `Vec<SandboxPermission>`,
but externally exposes a simpler API that can be used to configure
Seatbelt/Landlock.
Previous to this PR, we supported a `--sandbox` flag that effectively
mapped to an enum value in `SandboxPolicy`. Though now that
`SandboxPolicy` is a wrapper around `Vec<SandboxPermission>`, the single
`--sandbox` flag no longer makes sense. While I could have turned it
into a flag that the user can specify multiple times, I think the
current values to use with such a flag are long and potentially messy,
so for the moment, I have dropped support for `--sandbox` altogether and
we can bring it back once we have figured out the naming thing.
Since `--sandbox` is gone, users now have to specify `--full-auto` to
get a sandbox that allows writes in `cwd`. Admittedly, there is no clean
way to specify the equivalent of `--full-auto` in your `config.toml`
right now, so we will have to revisit that, as well.
Because `Config` presents a `SandboxPolicy` field and `SandboxPolicy`
changed considerably, I had to overhaul how config loading works, as
well. There are now two distinct concepts, `ConfigToml` and `Config`:
* `ConfigToml` is the deserialization of `~/.codex/config.toml`. As one
might expect, every field is `Optional` and it is `#[derive(Deserialize,
Default)]`. Consistent use of `Optional` makes it clear what the user
has specified explicitly.
* `Config` is the "normalized config" and is produced by merging
`ConfigToml` with `ConfigOverrides`. Where `ConfigToml` contains a raw
`Option<Vec<SandboxPermission>>`, `Config` presents only the final
`SandboxPolicy`.
The changes to `core/src/exec.rs` and `core/src/linux.rs` merit extra
special attention to ensure we are faithfully mapping the
`SandboxPolicy` to the Seatbelt and Landlock configs, respectively.
Also, take note that `core/src/seatbelt_readonly_policy.sbpl` has been
renamed to `codex-rs/core/src/seatbelt_base_policy.sbpl` and that
`(allow file-read*)` has been removed from the `.sbpl` file as now this
is added to the policy in `core/src/exec.rs` when
`sandbox_policy.has_full_disk_read_access()` is `true`.
2025-04-29 15:01:16 -07:00
|
|
|
|
}
|
feat: initial import of Rust implementation of Codex CLI in codex-rs/ (#629)
As stated in `codex-rs/README.md`:
Today, Codex CLI is written in TypeScript and requires Node.js 22+ to
run it. For a number of users, this runtime requirement inhibits
adoption: they would be better served by a standalone executable. As
maintainers, we want Codex to run efficiently in a wide range of
environments with minimal overhead. We also want to take advantage of
operating system-specific APIs to provide better sandboxing, where
possible.
To that end, we are moving forward with a Rust implementation of Codex
CLI contained in this folder, which has the following benefits:
- The CLI compiles to small, standalone, platform-specific binaries.
- Can make direct, native calls to
[seccomp](https://man7.org/linux/man-pages/man2/seccomp.2.html) and
[landlock](https://man7.org/linux/man-pages/man7/landlock.7.html) in
order to support sandboxing on Linux.
- No runtime garbage collection, resulting in lower memory consumption
and better, more predictable performance.
Currently, the Rust implementation is materially behind the TypeScript
implementation in functionality, so continue to use the TypeScript
implmentation for the time being. We will publish native executables via
GitHub Releases as soon as we feel the Rust version is usable.
2025-04-24 13:31:40 -07:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
pub fn get_platform_sandbox() -> Option<SandboxType> {
|
|
|
|
|
|
if cfg!(target_os = "macos") {
|
|
|
|
|
|
Some(SandboxType::MacosSeatbelt)
|
|
|
|
|
|
} else if cfg!(target_os = "linux") {
|
|
|
|
|
|
Some(SandboxType::LinuxSeccomp)
|
|
|
|
|
|
} else {
|
|
|
|
|
|
None
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
fn is_write_patch_constrained_to_writable_paths(
|
|
|
|
|
|
changes: &HashMap<PathBuf, ApplyPatchFileChange>,
|
|
|
|
|
|
writable_roots: &[PathBuf],
|
2025-05-04 10:57:12 -07:00
|
|
|
|
cwd: &Path,
|
feat: initial import of Rust implementation of Codex CLI in codex-rs/ (#629)
As stated in `codex-rs/README.md`:
Today, Codex CLI is written in TypeScript and requires Node.js 22+ to
run it. For a number of users, this runtime requirement inhibits
adoption: they would be better served by a standalone executable. As
maintainers, we want Codex to run efficiently in a wide range of
environments with minimal overhead. We also want to take advantage of
operating system-specific APIs to provide better sandboxing, where
possible.
To that end, we are moving forward with a Rust implementation of Codex
CLI contained in this folder, which has the following benefits:
- The CLI compiles to small, standalone, platform-specific binaries.
- Can make direct, native calls to
[seccomp](https://man7.org/linux/man-pages/man2/seccomp.2.html) and
[landlock](https://man7.org/linux/man-pages/man7/landlock.7.html) in
order to support sandboxing on Linux.
- No runtime garbage collection, resulting in lower memory consumption
and better, more predictable performance.
Currently, the Rust implementation is materially behind the TypeScript
implementation in functionality, so continue to use the TypeScript
implmentation for the time being. We will publish native executables via
GitHub Releases as soon as we feel the Rust version is usable.
2025-04-24 13:31:40 -07:00
|
|
|
|
) -> bool {
|
|
|
|
|
|
// Early‑exit if there are no declared writable roots.
|
|
|
|
|
|
if writable_roots.is_empty() {
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Normalize a path by removing `.` and resolving `..` without touching the
|
|
|
|
|
|
// filesystem (works even if the file does not exist).
|
|
|
|
|
|
fn normalize(path: &Path) -> Option<PathBuf> {
|
|
|
|
|
|
let mut out = PathBuf::new();
|
|
|
|
|
|
for comp in path.components() {
|
|
|
|
|
|
match comp {
|
|
|
|
|
|
Component::ParentDir => {
|
|
|
|
|
|
out.pop();
|
|
|
|
|
|
}
|
|
|
|
|
|
Component::CurDir => { /* skip */ }
|
|
|
|
|
|
other => out.push(other.as_os_str()),
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
Some(out)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Determine whether `path` is inside **any** writable root. Both `path`
|
|
|
|
|
|
// and roots are converted to absolute, normalized forms before the
|
|
|
|
|
|
// prefix check.
|
|
|
|
|
|
let is_path_writable = |p: &PathBuf| {
|
|
|
|
|
|
let abs = if p.is_absolute() {
|
|
|
|
|
|
p.clone()
|
|
|
|
|
|
} else {
|
|
|
|
|
|
cwd.join(p)
|
|
|
|
|
|
};
|
|
|
|
|
|
let abs = match normalize(&abs) {
|
|
|
|
|
|
Some(v) => v,
|
|
|
|
|
|
None => return false,
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
writable_roots.iter().any(|root| {
|
|
|
|
|
|
let root_abs = if root.is_absolute() {
|
|
|
|
|
|
root.clone()
|
|
|
|
|
|
} else {
|
|
|
|
|
|
normalize(&cwd.join(root)).unwrap_or_else(|| cwd.join(root))
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
abs.starts_with(&root_abs)
|
|
|
|
|
|
})
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
for (path, change) in changes {
|
|
|
|
|
|
match change {
|
|
|
|
|
|
ApplyPatchFileChange::Add { .. } | ApplyPatchFileChange::Delete => {
|
|
|
|
|
|
if !is_path_writable(path) {
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
ApplyPatchFileChange::Update { move_path, .. } => {
|
|
|
|
|
|
if !is_path_writable(path) {
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
if let Some(dest) = move_path {
|
|
|
|
|
|
if !is_path_writable(dest) {
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
true
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
|
|
mod tests {
|
|
|
|
|
|
use super::*;
|
|
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
|
fn test_writable_roots_constraint() {
|
|
|
|
|
|
let cwd = std::env::current_dir().unwrap();
|
|
|
|
|
|
let parent = cwd.parent().unwrap().to_path_buf();
|
|
|
|
|
|
|
|
|
|
|
|
// Helper to build a single‑entry map representing a patch that adds a
|
|
|
|
|
|
// file at `p`.
|
|
|
|
|
|
let make_add_change = |p: PathBuf| {
|
|
|
|
|
|
let mut m = HashMap::new();
|
|
|
|
|
|
m.insert(
|
|
|
|
|
|
p.clone(),
|
|
|
|
|
|
ApplyPatchFileChange::Add {
|
|
|
|
|
|
content: String::new(),
|
|
|
|
|
|
},
|
|
|
|
|
|
);
|
|
|
|
|
|
m
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
let add_inside = make_add_change(PathBuf::from("inner.txt"));
|
|
|
|
|
|
let add_outside = make_add_change(parent.join("outside.txt"));
|
|
|
|
|
|
|
|
|
|
|
|
assert!(is_write_patch_constrained_to_writable_paths(
|
|
|
|
|
|
&add_inside,
|
2025-05-04 10:57:12 -07:00
|
|
|
|
&[PathBuf::from(".")],
|
|
|
|
|
|
&cwd,
|
feat: initial import of Rust implementation of Codex CLI in codex-rs/ (#629)
As stated in `codex-rs/README.md`:
Today, Codex CLI is written in TypeScript and requires Node.js 22+ to
run it. For a number of users, this runtime requirement inhibits
adoption: they would be better served by a standalone executable. As
maintainers, we want Codex to run efficiently in a wide range of
environments with minimal overhead. We also want to take advantage of
operating system-specific APIs to provide better sandboxing, where
possible.
To that end, we are moving forward with a Rust implementation of Codex
CLI contained in this folder, which has the following benefits:
- The CLI compiles to small, standalone, platform-specific binaries.
- Can make direct, native calls to
[seccomp](https://man7.org/linux/man-pages/man2/seccomp.2.html) and
[landlock](https://man7.org/linux/man-pages/man7/landlock.7.html) in
order to support sandboxing on Linux.
- No runtime garbage collection, resulting in lower memory consumption
and better, more predictable performance.
Currently, the Rust implementation is materially behind the TypeScript
implementation in functionality, so continue to use the TypeScript
implmentation for the time being. We will publish native executables via
GitHub Releases as soon as we feel the Rust version is usable.
2025-04-24 13:31:40 -07:00
|
|
|
|
));
|
|
|
|
|
|
|
|
|
|
|
|
let add_outside_2 = make_add_change(parent.join("outside.txt"));
|
|
|
|
|
|
assert!(!is_write_patch_constrained_to_writable_paths(
|
|
|
|
|
|
&add_outside_2,
|
2025-05-04 10:57:12 -07:00
|
|
|
|
&[PathBuf::from(".")],
|
|
|
|
|
|
&cwd,
|
feat: initial import of Rust implementation of Codex CLI in codex-rs/ (#629)
As stated in `codex-rs/README.md`:
Today, Codex CLI is written in TypeScript and requires Node.js 22+ to
run it. For a number of users, this runtime requirement inhibits
adoption: they would be better served by a standalone executable. As
maintainers, we want Codex to run efficiently in a wide range of
environments with minimal overhead. We also want to take advantage of
operating system-specific APIs to provide better sandboxing, where
possible.
To that end, we are moving forward with a Rust implementation of Codex
CLI contained in this folder, which has the following benefits:
- The CLI compiles to small, standalone, platform-specific binaries.
- Can make direct, native calls to
[seccomp](https://man7.org/linux/man-pages/man2/seccomp.2.html) and
[landlock](https://man7.org/linux/man-pages/man7/landlock.7.html) in
order to support sandboxing on Linux.
- No runtime garbage collection, resulting in lower memory consumption
and better, more predictable performance.
Currently, the Rust implementation is materially behind the TypeScript
implementation in functionality, so continue to use the TypeScript
implmentation for the time being. We will publish native executables via
GitHub Releases as soon as we feel the Rust version is usable.
2025-04-24 13:31:40 -07:00
|
|
|
|
));
|
|
|
|
|
|
|
|
|
|
|
|
// With parent dir added as writable root, it should pass.
|
|
|
|
|
|
assert!(is_write_patch_constrained_to_writable_paths(
|
|
|
|
|
|
&add_outside,
|
2025-05-04 10:57:12 -07:00
|
|
|
|
&[PathBuf::from("..")],
|
|
|
|
|
|
&cwd,
|
feat: initial import of Rust implementation of Codex CLI in codex-rs/ (#629)
As stated in `codex-rs/README.md`:
Today, Codex CLI is written in TypeScript and requires Node.js 22+ to
run it. For a number of users, this runtime requirement inhibits
adoption: they would be better served by a standalone executable. As
maintainers, we want Codex to run efficiently in a wide range of
environments with minimal overhead. We also want to take advantage of
operating system-specific APIs to provide better sandboxing, where
possible.
To that end, we are moving forward with a Rust implementation of Codex
CLI contained in this folder, which has the following benefits:
- The CLI compiles to small, standalone, platform-specific binaries.
- Can make direct, native calls to
[seccomp](https://man7.org/linux/man-pages/man2/seccomp.2.html) and
[landlock](https://man7.org/linux/man-pages/man7/landlock.7.html) in
order to support sandboxing on Linux.
- No runtime garbage collection, resulting in lower memory consumption
and better, more predictable performance.
Currently, the Rust implementation is materially behind the TypeScript
implementation in functionality, so continue to use the TypeScript
implmentation for the time being. We will publish native executables via
GitHub Releases as soon as we feel the Rust version is usable.
2025-04-24 13:31:40 -07:00
|
|
|
|
))
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|