log sandbox commands to $CODEX_HOME instead of cwd (#6171)

Logging commands in the Windows Sandbox is temporary, but while we are
doing it, let's always write to CODEX_HOME instead of dirtying the cwd.
This commit is contained in:
iceweasel-oai
2025-11-03 13:12:33 -08:00
committed by GitHub
parent 6ee7fbcfff
commit 07b7d28937
5 changed files with 48 additions and 23 deletions

View File

@@ -124,6 +124,7 @@ async fn run_command_under_sandbox(
let cwd_clone = cwd.clone();
let env_map = env.clone();
let command_vec = command.clone();
let base_dir = config.codex_home.clone();
let res = tokio::task::spawn_blocking(move || {
run_windows_sandbox_capture(
policy_str,
@@ -132,6 +133,7 @@ async fn run_command_under_sandbox(
&cwd_clone,
env_map,
None,
Some(base_dir.as_path()),
)
})
.await;

View File

@@ -171,6 +171,7 @@ async fn exec_windows_sandbox(
params: ExecParams,
sandbox_policy: &SandboxPolicy,
) -> Result<RawExecToolCallOutput> {
use crate::config::find_codex_home;
use codex_windows_sandbox::run_windows_sandbox_capture;
let ExecParams {
@@ -188,8 +189,17 @@ async fn exec_windows_sandbox(
};
let sandbox_cwd = cwd.clone();
let logs_base_dir = find_codex_home().ok();
let spawn_res = tokio::task::spawn_blocking(move || {
run_windows_sandbox_capture(policy_str, &sandbox_cwd, command, &cwd, env, timeout_ms)
run_windows_sandbox_capture(
policy_str,
&sandbox_cwd,
command,
&cwd,
env,
timeout_ms,
logs_base_dir.as_deref(),
)
})
.await;

View File

@@ -182,6 +182,7 @@ mod windows_impl {
cwd: &Path,
mut env_map: HashMap<String, String>,
timeout_ms: Option<u64>,
logs_base_dir: Option<&Path>,
) -> Result<CaptureResult> {
let policy = SandboxPolicy::parse(policy_json_or_preset)?;
normalize_null_device_env(&mut env_map);
@@ -191,7 +192,7 @@ mod windows_impl {
let current_dir = cwd.to_path_buf();
// for now, don't fail if we detect world-writable directories
// audit::audit_everyone_writable(&current_dir, &env_map)?;
log_start(&command);
log_start(&command, logs_base_dir);
let (h_token, psid_to_use): (HANDLE, *mut c_void) = unsafe {
match &policy.0 {
SandboxMode::ReadOnly => {
@@ -295,7 +296,7 @@ mod windows_impl {
env_block.len(),
si.dwFlags,
);
debug_log(&dbg);
debug_log(&dbg, logs_base_dir);
unsafe {
CloseHandle(in_r);
CloseHandle(in_w);
@@ -395,9 +396,9 @@ mod windows_impl {
};
if exit_code == 0 {
log_success(&command);
log_success(&command, logs_base_dir);
} else {
log_failure(&command, &format!("exit code {}", exit_code));
log_failure(&command, &format!("exit code {}", exit_code), logs_base_dir);
}
if !persist_aces {
@@ -446,6 +447,7 @@ mod stub {
_cwd: &Path,
_env_map: HashMap<String, String>,
_timeout_ms: Option<u64>,
_logs_base_dir: Option<&Path>,
) -> Result<CaptureResult> {
bail!("Windows sandbox is only available on Windows")
}

View File

@@ -1,5 +1,7 @@
use std::fs::OpenOptions;
use std::io::Write;
use std::path::Path;
use std::path::PathBuf;
const LOG_COMMAND_PREVIEW_LIMIT: usize = 200;
pub const LOG_FILE_NAME: &str = "sandbox_commands.rust.log";
@@ -13,35 +15,43 @@ fn preview(command: &[String]) -> String {
}
}
fn append_line(line: &str) {
if let Ok(mut f) = OpenOptions::new()
.create(true)
.append(true)
.open(LOG_FILE_NAME)
{
let _ = writeln!(f, "{}", line);
fn log_file_path(base_dir: &Path) -> Option<PathBuf> {
if base_dir.is_dir() {
Some(base_dir.join(LOG_FILE_NAME))
} else {
None
}
}
pub fn log_start(command: &[String]) {
let p = preview(command);
append_line(&format!("START: {}", p));
fn append_line(line: &str, base_dir: Option<&Path>) {
if let Some(dir) = base_dir {
if let Some(path) = log_file_path(dir) {
if let Ok(mut f) = OpenOptions::new().create(true).append(true).open(path) {
let _ = writeln!(f, "{}", line);
}
}
}
}
pub fn log_success(command: &[String]) {
pub fn log_start(command: &[String], base_dir: Option<&Path>) {
let p = preview(command);
append_line(&format!("SUCCESS: {}", p));
append_line(&format!("START: {p}"), base_dir);
}
pub fn log_failure(command: &[String], detail: &str) {
pub fn log_success(command: &[String], base_dir: Option<&Path>) {
let p = preview(command);
append_line(&format!("FAILURE: {} ({})", p, detail));
append_line(&format!("SUCCESS: {p}"), base_dir);
}
pub fn log_failure(command: &[String], detail: &str, base_dir: Option<&Path>) {
let p = preview(command);
append_line(&format!("FAILURE: {p} ({detail})"), base_dir);
}
// Debug logging helper. Emits only when SBX_DEBUG=1 to avoid noisy logs.
pub fn debug_log(msg: &str) {
pub fn debug_log(msg: &str, base_dir: Option<&Path>) {
if std::env::var("SBX_DEBUG").ok().as_deref() == Some("1") {
append_line(&format!("DEBUG: {}", msg));
eprintln!("{}", msg);
append_line(&format!("DEBUG: {msg}"), base_dir);
eprintln!("{msg}");
}
}

View File

@@ -101,6 +101,7 @@ pub unsafe fn create_process_as_user(
argv: &[String],
cwd: &Path,
env_map: &HashMap<String, String>,
logs_base_dir: Option<&Path>,
) -> Result<(PROCESS_INFORMATION, STARTUPINFOW)> {
let cmdline_str = argv
.iter()
@@ -142,7 +143,7 @@ pub unsafe fn create_process_as_user(
env_block.len(),
si.dwFlags,
);
logging::debug_log(&msg);
logging::debug_log(&msg, logs_base_dir);
return Err(anyhow!("CreateProcessAsUserW failed: {}", err));
}
Ok((pi, si))