mirror of
https://github.com/openai/codex.git
synced 2026-09-09 15:58:47 +00:00
Fix Windows sandbox apply_patch and proxy setup
This commit is contained in:
@@ -38,6 +38,7 @@ pub const APPLY_PATCH_TOOL_INSTRUCTIONS: &str = include_str!("../apply_patch_too
|
||||
/// process-invocation contract between the apply-patch runtime and the arg0
|
||||
/// dispatcher.
|
||||
pub const CODEX_CORE_APPLY_PATCH_ARG1: &str = "--codex-run-as-apply-patch";
|
||||
pub const CODEX_CORE_APPLY_PATCH_FILE_ARG1: &str = "--codex-run-as-apply-patch-file";
|
||||
|
||||
#[derive(Debug, Error, PartialEq)]
|
||||
pub enum ApplyPatchError {
|
||||
|
||||
@@ -4,6 +4,7 @@ use std::path::Path;
|
||||
use std::path::PathBuf;
|
||||
|
||||
use codex_apply_patch::CODEX_CORE_APPLY_PATCH_ARG1;
|
||||
use codex_apply_patch::CODEX_CORE_APPLY_PATCH_FILE_ARG1;
|
||||
use codex_sandboxing::landlock::CODEX_LINUX_SANDBOX_ARG0;
|
||||
use codex_utils_home_dir::find_codex_home;
|
||||
#[cfg(unix)]
|
||||
@@ -93,10 +94,23 @@ pub fn arg0_dispatch() -> Option<Arg0PathEntryGuard> {
|
||||
}
|
||||
|
||||
let argv1 = args.next().unwrap_or_default();
|
||||
if argv1 == CODEX_CORE_APPLY_PATCH_ARG1 {
|
||||
if argv1 == CODEX_CORE_APPLY_PATCH_ARG1 || argv1 == CODEX_CORE_APPLY_PATCH_FILE_ARG1 {
|
||||
let patch_arg = args.next().and_then(|s| s.to_str().map(str::to_owned));
|
||||
let exit_code = match patch_arg {
|
||||
Some(patch_arg) => {
|
||||
let patch_arg = if argv1 == CODEX_CORE_APPLY_PATCH_FILE_ARG1 {
|
||||
match std::fs::read_to_string(&patch_arg) {
|
||||
Ok(patch_arg) => patch_arg,
|
||||
Err(err) => {
|
||||
eprintln!(
|
||||
"Error: failed to read PATCH file for {CODEX_CORE_APPLY_PATCH_FILE_ARG1}: {err}"
|
||||
);
|
||||
std::process::exit(1);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
patch_arg
|
||||
};
|
||||
let mut stdout = std::io::stdout();
|
||||
let mut stderr = std::io::stderr();
|
||||
let cwd = match codex_utils_absolute_path::AbsolutePathBuf::current_dir() {
|
||||
@@ -122,7 +136,7 @@ pub fn arg0_dispatch() -> Option<Arg0PathEntryGuard> {
|
||||
}
|
||||
}
|
||||
None => {
|
||||
eprintln!("Error: {CODEX_CORE_APPLY_PATCH_ARG1} requires a UTF-8 PATCH argument.");
|
||||
eprintln!("Error: {argv1:?} requires a UTF-8 PATCH argument.");
|
||||
1
|
||||
}
|
||||
};
|
||||
|
||||
@@ -22,6 +22,8 @@ use crate::tools::sandboxing::ToolRuntime;
|
||||
use crate::tools::sandboxing::with_cached_approval;
|
||||
use codex_apply_patch::ApplyPatchAction;
|
||||
use codex_apply_patch::CODEX_CORE_APPLY_PATCH_ARG1;
|
||||
#[cfg(target_os = "windows")]
|
||||
use codex_apply_patch::CODEX_CORE_APPLY_PATCH_FILE_ARG1;
|
||||
use codex_protocol::exec_output::ExecToolCallOutput;
|
||||
use codex_protocol::exec_output::StreamOutput;
|
||||
use codex_protocol::models::PermissionProfile;
|
||||
@@ -33,6 +35,8 @@ use codex_sandboxing::SandboxablePreference;
|
||||
use codex_utils_absolute_path::AbsolutePathBuf;
|
||||
use futures::future::BoxFuture;
|
||||
use std::collections::HashMap;
|
||||
#[cfg(target_os = "windows")]
|
||||
use std::io::Write;
|
||||
use std::path::PathBuf;
|
||||
use std::time::Instant;
|
||||
|
||||
@@ -71,10 +75,13 @@ impl ApplyPatchRuntime {
|
||||
fn build_sandbox_command(
|
||||
req: &ApplyPatchRequest,
|
||||
codex_home: &std::path::Path,
|
||||
patch_file: &std::path::Path,
|
||||
) -> Result<SandboxCommand, ToolError> {
|
||||
Ok(Self::build_sandbox_command_with_program(
|
||||
req,
|
||||
codex_windows_sandbox::resolve_current_exe_for_launch(codex_home, "codex.exe"),
|
||||
CODEX_CORE_APPLY_PATCH_FILE_ARG1.to_string(),
|
||||
patch_file.display().to_string(),
|
||||
))
|
||||
}
|
||||
|
||||
@@ -84,7 +91,12 @@ impl ApplyPatchRuntime {
|
||||
codex_self_exe: Option<&PathBuf>,
|
||||
) -> Result<SandboxCommand, ToolError> {
|
||||
let exe = Self::resolve_apply_patch_program(codex_self_exe)?;
|
||||
Ok(Self::build_sandbox_command_with_program(req, exe))
|
||||
Ok(Self::build_sandbox_command_with_program(
|
||||
req,
|
||||
exe,
|
||||
CODEX_CORE_APPLY_PATCH_ARG1.to_string(),
|
||||
req.action.patch.clone(),
|
||||
))
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
@@ -97,13 +109,15 @@ impl ApplyPatchRuntime {
|
||||
.map_err(|e| ToolError::Rejected(format!("failed to determine codex exe: {e}")))
|
||||
}
|
||||
|
||||
fn build_sandbox_command_with_program(req: &ApplyPatchRequest, exe: PathBuf) -> SandboxCommand {
|
||||
fn build_sandbox_command_with_program(
|
||||
req: &ApplyPatchRequest,
|
||||
exe: PathBuf,
|
||||
mode_arg: String,
|
||||
patch_arg: String,
|
||||
) -> SandboxCommand {
|
||||
SandboxCommand {
|
||||
program: exe.into_os_string(),
|
||||
args: vec![
|
||||
CODEX_CORE_APPLY_PATCH_ARG1.to_string(),
|
||||
req.action.patch.clone(),
|
||||
],
|
||||
args: vec![mode_arg, patch_arg],
|
||||
cwd: req.action.cwd.to_path_buf(),
|
||||
// Run apply_patch with a minimal environment for determinism and to avoid leaks.
|
||||
env: HashMap::new(),
|
||||
@@ -111,6 +125,22 @@ impl ApplyPatchRuntime {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
fn write_patch_temp_file(
|
||||
req: &ApplyPatchRequest,
|
||||
) -> Result<tempfile::NamedTempFile, ToolError> {
|
||||
let mut patch_file = tempfile::Builder::new()
|
||||
.prefix(".codex-apply-patch-")
|
||||
.suffix(".patch")
|
||||
.tempfile_in(req.action.cwd.as_path())
|
||||
.map_err(|err| ToolError::Rejected(format!("failed to create patch file: {err}")))?;
|
||||
patch_file
|
||||
.write_all(req.action.patch.as_bytes())
|
||||
.and_then(|_| patch_file.flush())
|
||||
.map_err(|err| ToolError::Rejected(format!("failed to write patch file: {err}")))?;
|
||||
Ok(patch_file)
|
||||
}
|
||||
|
||||
fn stdout_stream(ctx: &ToolCtx) -> Option<crate::exec::StdoutStream> {
|
||||
Some(crate::exec::StdoutStream {
|
||||
sub_id: ctx.turn.sub_id.clone(),
|
||||
@@ -241,7 +271,10 @@ impl ToolRuntime<ApplyPatchRequest, ExecToolCallOutput> for ApplyPatchRuntime {
|
||||
}
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
let command = Self::build_sandbox_command(req, &ctx.turn.config.codex_home)?;
|
||||
let patch_file = Self::write_patch_temp_file(req)?;
|
||||
#[cfg(target_os = "windows")]
|
||||
let command =
|
||||
Self::build_sandbox_command(req, &ctx.turn.config.codex_home, patch_file.path())?;
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
let command = Self::build_sandbox_command(req, ctx.turn.codex_self_exe.as_ref())?;
|
||||
let options = ExecOptions {
|
||||
|
||||
@@ -39,7 +39,7 @@ const OFFLINE_BLOCK_LOOPBACK_TCP_RULE_FRIENDLY: &str =
|
||||
"Codex Sandbox Offline - Block Loopback TCP (Except Proxy)";
|
||||
const OFFLINE_BLOCK_LOOPBACK_UDP_RULE_FRIENDLY: &str = "Codex Sandbox Offline - Block Loopback UDP";
|
||||
const OFFLINE_PROXY_ALLOW_RULE_NAME: &str = "codex_sandbox_offline_allow_loopback_proxy";
|
||||
const LOOPBACK_REMOTE_ADDRESSES: &str = "127.0.0.0/8,::/127";
|
||||
const LOOPBACK_REMOTE_ADDRESSES: &str = "127.0.0.1-127.255.255.255,::1";
|
||||
const NON_LOOPBACK_REMOTE_ADDRESSES: &str = "0.0.0.0-126.255.255.255,128.0.0.0-255.255.255.255,::,::2-ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff";
|
||||
|
||||
struct BlockRuleSpec<'a> {
|
||||
|
||||
Reference in New Issue
Block a user