Files
codex/codex-rs/exec-server/src/regular_file_tests.rs
jif b5ea64a203 Add a symlink-safe reader for sensitive files (#39200)
## What changed

- Export `read_sensitive_file_to_string` from `codex-exec-server`.
- Require the opened path to be a regular disk file and avoid following its
  final symlink component on Unix or reparse point on Windows.
- Read valid UTF-8 file contents asynchronously and return I/O errors for
  unsupported inputs.

## Testing

Add tests covering regular files, directories, and symlinks.

GitOrigin-RevId: 68809e94c0d3719e5685c064f9610a0455ffd8d7
2026-08-18 13:36:16 +00:00

48 lines
1.4 KiB
Rust

use super::read_sensitive_file_to_string;
use tempfile::TempDir;
#[tokio::test]
async fn read_sensitive_file_reads_regular_file() {
let directory = TempDir::new().expect("temporary directory");
let path = directory.path().join("role.toml");
tokio::fs::write(&path, "developer_instructions = 'stay focused'")
.await
.expect("write regular file");
assert_eq!(
read_sensitive_file_to_string(&path)
.await
.expect("read regular file"),
"developer_instructions = 'stay focused'",
);
}
#[tokio::test]
async fn read_sensitive_file_rejects_directory() {
let directory = TempDir::new().expect("temporary directory");
assert!(
read_sensitive_file_to_string(directory.path())
.await
.is_err()
);
}
#[cfg(any(unix, windows))]
#[tokio::test]
async fn read_sensitive_file_rejects_symlink() {
let directory = TempDir::new().expect("temporary directory");
let target = directory.path().join("target.toml");
let link = directory.path().join("role.toml");
tokio::fs::write(&target, "model_provider = 'attacker'")
.await
.expect("write symlink target");
#[cfg(unix)]
std::os::unix::fs::symlink(&target, &link).expect("create symlink");
#[cfg(windows)]
std::os::windows::fs::symlink_file(&target, &link).expect("create symlink");
assert!(read_sensitive_file_to_string(&link).await.is_err());
}