Skip to content

Commit 8105479

Browse files
log sandbox commands to $CODEX_HOME instead of cwd (openai#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.
1 parent 31786a9 commit 8105479

File tree

5 files changed

+47
-22
lines changed

5 files changed

+47
-22
lines changed

codex-rs/cli/src/debug_sandbox.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,7 @@ async fn run_command_under_sandbox(
124124
let cwd_clone = cwd.clone();
125125
let env_map = env.clone();
126126
let command_vec = command.clone();
127+
let base_dir = config.codex_home.clone();
127128
let res = tokio::task::spawn_blocking(move || {
128129
run_windows_sandbox_capture(
129130
policy_str,
@@ -132,6 +133,7 @@ async fn run_command_under_sandbox(
132133
&cwd_clone,
133134
env_map,
134135
None,
136+
Some(base_dir.as_path()),
135137
)
136138
})
137139
.await;

codex-rs/core/src/exec.rs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,7 @@ async fn exec_windows_sandbox(
171171
params: ExecParams,
172172
sandbox_policy: &SandboxPolicy,
173173
) -> Result<RawExecToolCallOutput> {
174+
use crate::config::find_codex_home;
174175
use codex_windows_sandbox::run_windows_sandbox_capture;
175176

176177
let ExecParams {
@@ -188,8 +189,17 @@ async fn exec_windows_sandbox(
188189
};
189190

190191
let sandbox_cwd = cwd.clone();
192+
let logs_base_dir = find_codex_home().ok();
191193
let spawn_res = tokio::task::spawn_blocking(move || {
192-
run_windows_sandbox_capture(policy_str, &sandbox_cwd, command, &cwd, env, timeout_ms)
194+
run_windows_sandbox_capture(
195+
policy_str,
196+
&sandbox_cwd,
197+
command,
198+
&cwd,
199+
env,
200+
timeout_ms,
201+
logs_base_dir.as_deref(),
202+
)
193203
})
194204
.await;
195205

codex-rs/windows-sandbox-rs/src/lib.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,7 @@ mod windows_impl {
182182
cwd: &Path,
183183
mut env_map: HashMap<String, String>,
184184
timeout_ms: Option<u64>,
185+
logs_base_dir: Option<&Path>,
185186
) -> Result<CaptureResult> {
186187
let policy = SandboxPolicy::parse(policy_json_or_preset)?;
187188
normalize_null_device_env(&mut env_map);
@@ -191,7 +192,7 @@ mod windows_impl {
191192
let current_dir = cwd.to_path_buf();
192193
// for now, don't fail if we detect world-writable directories
193194
// audit::audit_everyone_writable(&current_dir, &env_map)?;
194-
log_start(&command);
195+
log_start(&command, logs_base_dir);
195196
let (h_token, psid_to_use): (HANDLE, *mut c_void) = unsafe {
196197
match &policy.0 {
197198
SandboxMode::ReadOnly => {
@@ -295,7 +296,7 @@ mod windows_impl {
295296
env_block.len(),
296297
si.dwFlags,
297298
);
298-
debug_log(&dbg);
299+
debug_log(&dbg, logs_base_dir);
299300
unsafe {
300301
CloseHandle(in_r);
301302
CloseHandle(in_w);
@@ -395,9 +396,9 @@ mod windows_impl {
395396
};
396397

397398
if exit_code == 0 {
398-
log_success(&command);
399+
log_success(&command, logs_base_dir);
399400
} else {
400-
log_failure(&command, &format!("exit code {}", exit_code));
401+
log_failure(&command, &format!("exit code {}", exit_code), logs_base_dir);
401402
}
402403

403404
if !persist_aces {
@@ -446,6 +447,7 @@ mod stub {
446447
_cwd: &Path,
447448
_env_map: HashMap<String, String>,
448449
_timeout_ms: Option<u64>,
450+
_logs_base_dir: Option<&Path>,
449451
) -> Result<CaptureResult> {
450452
bail!("Windows sandbox is only available on Windows")
451453
}
Lines changed: 26 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
use std::fs::OpenOptions;
22
use std::io::Write;
3+
use std::path::Path;
4+
use std::path::PathBuf;
35

46
const LOG_COMMAND_PREVIEW_LIMIT: usize = 200;
57
pub const LOG_FILE_NAME: &str = "sandbox_commands.rust.log";
@@ -13,35 +15,43 @@ fn preview(command: &[String]) -> String {
1315
}
1416
}
1517

16-
fn append_line(line: &str) {
17-
if let Ok(mut f) = OpenOptions::new()
18-
.create(true)
19-
.append(true)
20-
.open(LOG_FILE_NAME)
21-
{
22-
let _ = writeln!(f, "{}", line);
18+
fn log_file_path(base_dir: &Path) -> Option<PathBuf> {
19+
if base_dir.is_dir() {
20+
Some(base_dir.join(LOG_FILE_NAME))
21+
} else {
22+
None
23+
}
24+
}
25+
26+
fn append_line(line: &str, base_dir: Option<&Path>) {
27+
if let Some(dir) = base_dir {
28+
if let Some(path) = log_file_path(dir) {
29+
if let Ok(mut f) = OpenOptions::new().create(true).append(true).open(path) {
30+
let _ = writeln!(f, "{}", line);
31+
}
32+
}
2333
}
2434
}
2535

26-
pub fn log_start(command: &[String]) {
36+
pub fn log_start(command: &[String], base_dir: Option<&Path>) {
2737
let p = preview(command);
28-
append_line(&format!("START: {}", p));
38+
append_line(&format!("START: {p}"), base_dir);
2939
}
3040

31-
pub fn log_success(command: &[String]) {
41+
pub fn log_success(command: &[String], base_dir: Option<&Path>) {
3242
let p = preview(command);
33-
append_line(&format!("SUCCESS: {}", p));
43+
append_line(&format!("SUCCESS: {p}"), base_dir);
3444
}
3545

36-
pub fn log_failure(command: &[String], detail: &str) {
46+
pub fn log_failure(command: &[String], detail: &str, base_dir: Option<&Path>) {
3747
let p = preview(command);
38-
append_line(&format!("FAILURE: {} ({})", p, detail));
48+
append_line(&format!("FAILURE: {p} ({detail})"), base_dir);
3949
}
4050

4151
// Debug logging helper. Emits only when SBX_DEBUG=1 to avoid noisy logs.
42-
pub fn debug_log(msg: &str) {
52+
pub fn debug_log(msg: &str, base_dir: Option<&Path>) {
4353
if std::env::var("SBX_DEBUG").ok().as_deref() == Some("1") {
44-
append_line(&format!("DEBUG: {}", msg));
45-
eprintln!("{}", msg);
54+
append_line(&format!("DEBUG: {msg}"), base_dir);
55+
eprintln!("{msg}");
4656
}
4757
}

codex-rs/windows-sandbox-rs/src/process.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@ pub unsafe fn create_process_as_user(
101101
argv: &[String],
102102
cwd: &Path,
103103
env_map: &HashMap<String, String>,
104+
logs_base_dir: Option<&Path>,
104105
) -> Result<(PROCESS_INFORMATION, STARTUPINFOW)> {
105106
let cmdline_str = argv
106107
.iter()
@@ -142,7 +143,7 @@ pub unsafe fn create_process_as_user(
142143
env_block.len(),
143144
si.dwFlags,
144145
);
145-
logging::debug_log(&msg);
146+
logging::debug_log(&msg, logs_base_dir);
146147
return Err(anyhow!("CreateProcessAsUserW failed: {}", err));
147148
}
148149
Ok((pi, si))

0 commit comments

Comments
 (0)