mirror of
https://github.com/openai/codex.git
synced 2026-09-07 15:40:00 +00:00
exec-server: migrate owned paths to PathUri
This commit is contained in:
@@ -878,11 +878,9 @@ mod tests {
|
||||
#[tokio::test]
|
||||
async fn test_environment_rejects_sandboxed_filesystem_without_runtime_paths() {
|
||||
let environment = Environment::default_for_tests();
|
||||
let path = codex_utils_absolute_path::AbsolutePathBuf::from_absolute_path(
|
||||
std::env::current_exe().expect("current exe").as_path(),
|
||||
)
|
||||
.expect("absolute current exe");
|
||||
let path = codex_utils_path_uri::PathUri::from_abs_path(&path).expect("path URI");
|
||||
let path =
|
||||
codex_utils_path_uri::PathUri::from_path(std::env::current_exe().expect("current exe"))
|
||||
.expect("path URI");
|
||||
let sandbox = crate::FileSystemSandboxContext::from_permission_profile(
|
||||
codex_protocol::models::PermissionProfile::from_runtime_permissions(
|
||||
&codex_protocol::permissions::FileSystemSandboxPolicy::restricted(Vec::new()),
|
||||
|
||||
@@ -15,6 +15,7 @@ use codex_sandboxing::SandboxTransformRequest;
|
||||
use codex_sandboxing::SandboxablePreference;
|
||||
use codex_utils_absolute_path::AbsolutePathBuf;
|
||||
use codex_utils_absolute_path::canonicalize_preserving_symlinks;
|
||||
use codex_utils_path_uri::PathUri;
|
||||
use tokio::io::AsyncWriteExt;
|
||||
use tokio::process::Command;
|
||||
|
||||
@@ -63,9 +64,10 @@ impl FileSystemSandboxRunner {
|
||||
let helper_read_roots = if sandbox.use_legacy_landlock {
|
||||
Vec::new()
|
||||
} else {
|
||||
helper_read_roots(&self.runtime_paths)
|
||||
helper_read_roots(&self.runtime_paths).map_err(io_error)?
|
||||
};
|
||||
add_helper_runtime_permissions(&mut file_system_policy, &helper_read_roots, cwd.as_path());
|
||||
add_helper_runtime_permissions(&mut file_system_policy, &helper_read_roots, cwd.as_path())
|
||||
.map_err(io_error)?;
|
||||
normalize_file_system_policy_root_aliases(&mut file_system_policy);
|
||||
let network_policy = NetworkSandboxPolicy::Restricted;
|
||||
let permission_profile = PermissionProfile::from_runtime_permissions_with_enforcement(
|
||||
@@ -84,7 +86,18 @@ impl FileSystemSandboxRunner {
|
||||
cwd: &AbsolutePathBuf,
|
||||
sandbox_context: &FileSystemSandboxContext,
|
||||
) -> Result<SandboxExecRequest, JSONRPCErrorError> {
|
||||
let helper = &self.runtime_paths.codex_self_exe;
|
||||
let helper = self
|
||||
.runtime_paths
|
||||
.codex_self_exe
|
||||
.to_abs_path()
|
||||
.map_err(io_error)?;
|
||||
let codex_linux_sandbox_exe = self
|
||||
.runtime_paths
|
||||
.codex_linux_sandbox_exe
|
||||
.as_ref()
|
||||
.map(PathUri::to_abs_path)
|
||||
.transpose()
|
||||
.map_err(io_error)?;
|
||||
let sandbox_manager = SandboxManager::new();
|
||||
let (file_system_policy, network_policy) = permission_profile.to_runtime_permissions();
|
||||
let sandbox = sandbox_manager.select_initial(
|
||||
@@ -109,7 +122,7 @@ impl FileSystemSandboxRunner {
|
||||
enforce_managed_network: false,
|
||||
network: None,
|
||||
sandbox_policy_cwd: cwd.as_path(),
|
||||
codex_linux_sandbox_exe: self.runtime_paths.codex_linux_sandbox_exe.as_deref(),
|
||||
codex_linux_sandbox_exe: codex_linux_sandbox_exe.as_deref(),
|
||||
use_legacy_landlock: sandbox_context.use_legacy_landlock,
|
||||
windows_sandbox_level: sandbox_context.windows_sandbox_level,
|
||||
windows_sandbox_private_desktop: sandbox_context.windows_sandbox_private_desktop,
|
||||
@@ -134,26 +147,28 @@ fn sandbox_cwd(sandbox: &FileSystemSandboxContext) -> Result<AbsolutePathBuf, JS
|
||||
.map_err(|err| invalid_request(format!("current directory is not absolute: {err}")))
|
||||
}
|
||||
|
||||
fn helper_read_roots(runtime_paths: &ExecServerRuntimePaths) -> Vec<AbsolutePathBuf> {
|
||||
fn helper_read_roots(runtime_paths: &ExecServerRuntimePaths) -> std::io::Result<Vec<PathUri>> {
|
||||
let mut roots = Vec::new();
|
||||
for path in std::iter::once(runtime_paths.codex_self_exe.as_path())
|
||||
.chain(runtime_paths.codex_linux_sandbox_exe.as_deref())
|
||||
for path in std::iter::once(&runtime_paths.codex_self_exe)
|
||||
.chain(runtime_paths.codex_linux_sandbox_exe.as_ref())
|
||||
{
|
||||
if let Some(parent) = path.parent()
|
||||
&& let Ok(root) = AbsolutePathBuf::from_absolute_path(parent)
|
||||
&& !roots.contains(&root)
|
||||
{
|
||||
let path = path.to_abs_path()?;
|
||||
let Some(parent) = path.parent() else {
|
||||
continue;
|
||||
};
|
||||
let root = PathUri::from_path(parent)?;
|
||||
if !roots.contains(&root) {
|
||||
roots.push(root);
|
||||
}
|
||||
}
|
||||
roots
|
||||
Ok(roots)
|
||||
}
|
||||
|
||||
fn add_helper_runtime_permissions(
|
||||
file_system_policy: &mut FileSystemSandboxPolicy,
|
||||
helper_read_roots: &[AbsolutePathBuf],
|
||||
helper_read_roots: &[PathUri],
|
||||
cwd: &std::path::Path,
|
||||
) {
|
||||
) -> std::io::Result<()> {
|
||||
if !file_system_policy.has_full_disk_read_access() {
|
||||
let minimal_read_entry = FileSystemSandboxEntry {
|
||||
path: FileSystemPath::Special {
|
||||
@@ -167,6 +182,7 @@ fn add_helper_runtime_permissions(
|
||||
}
|
||||
|
||||
for helper_read_root in helper_read_roots {
|
||||
let helper_read_root = helper_read_root.to_abs_path()?;
|
||||
if file_system_policy.can_read_path_with_cwd(helper_read_root.as_path(), cwd) {
|
||||
continue;
|
||||
}
|
||||
@@ -178,6 +194,7 @@ fn add_helper_runtime_permissions(
|
||||
access: FileSystemAccessMode::Read,
|
||||
});
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn normalize_file_system_policy_root_aliases(file_system_policy: &mut FileSystemSandboxPolicy) {
|
||||
@@ -345,7 +362,8 @@ mod tests {
|
||||
.expect("absolute cwd");
|
||||
let mut policy = restricted_policy(Vec::new());
|
||||
|
||||
add_helper_runtime_permissions(&mut policy, /*helper_read_roots*/ &[], cwd.as_path());
|
||||
add_helper_runtime_permissions(&mut policy, /*helper_read_roots*/ &[], cwd.as_path())
|
||||
.expect("helper permissions");
|
||||
|
||||
assert!(policy.include_platform_defaults());
|
||||
}
|
||||
@@ -359,7 +377,8 @@ mod tests {
|
||||
FileSystemAccessMode::Write,
|
||||
)]);
|
||||
|
||||
add_helper_runtime_permissions(&mut policy, /*helper_read_roots*/ &[], cwd.as_path());
|
||||
add_helper_runtime_permissions(&mut policy, /*helper_read_roots*/ &[], cwd.as_path())
|
||||
.expect("helper permissions");
|
||||
|
||||
assert!(policy.include_platform_defaults());
|
||||
}
|
||||
@@ -377,19 +396,19 @@ mod tests {
|
||||
writable.clone(),
|
||||
FileSystemAccessMode::Write,
|
||||
)]);
|
||||
let readable = AbsolutePathBuf::from_absolute_path(
|
||||
runtime_paths
|
||||
.codex_self_exe
|
||||
.parent()
|
||||
.expect("current exe parent"),
|
||||
)
|
||||
.expect("absolute readable path");
|
||||
let readable = runtime_paths
|
||||
.codex_self_exe
|
||||
.parent()
|
||||
.expect("current exe parent")
|
||||
.to_abs_path()
|
||||
.expect("absolute readable path");
|
||||
|
||||
add_helper_runtime_permissions(
|
||||
&mut policy,
|
||||
&helper_read_roots(&runtime_paths),
|
||||
&helper_read_roots(&runtime_paths).expect("helper read roots"),
|
||||
cwd.as_path(),
|
||||
);
|
||||
)
|
||||
.expect("helper permissions");
|
||||
|
||||
assert!(policy.can_read_path_with_cwd(readable.as_path(), cwd.as_path()));
|
||||
assert!(policy.can_write_path_with_cwd(writable.as_path(), cwd.as_path()));
|
||||
@@ -546,19 +565,19 @@ mod tests {
|
||||
let cwd = AbsolutePathBuf::from_absolute_path(std::env::temp_dir().as_path())
|
||||
.expect("absolute cwd");
|
||||
let mut policy = restricted_policy(Vec::new());
|
||||
let readable = AbsolutePathBuf::from_absolute_path(
|
||||
runtime_paths
|
||||
.codex_self_exe
|
||||
.parent()
|
||||
.expect("current exe parent"),
|
||||
)
|
||||
.expect("absolute readable path");
|
||||
let readable = runtime_paths
|
||||
.codex_self_exe
|
||||
.parent()
|
||||
.expect("current exe parent")
|
||||
.to_abs_path()
|
||||
.expect("absolute readable path");
|
||||
|
||||
add_helper_runtime_permissions(
|
||||
&mut policy,
|
||||
&helper_read_roots(&runtime_paths),
|
||||
&helper_read_roots(&runtime_paths).expect("helper read roots"),
|
||||
cwd.as_path(),
|
||||
);
|
||||
)
|
||||
.expect("helper permissions");
|
||||
|
||||
assert!(policy.can_read_path_with_cwd(readable.as_path(), cwd.as_path()));
|
||||
}
|
||||
@@ -581,14 +600,32 @@ mod tests {
|
||||
|
||||
add_helper_runtime_permissions(
|
||||
&mut policy,
|
||||
&helper_read_roots(&runtime_paths),
|
||||
&helper_read_roots(&runtime_paths).expect("helper read roots"),
|
||||
cwd.as_path(),
|
||||
);
|
||||
)
|
||||
.expect("helper permissions");
|
||||
|
||||
assert!(policy.can_read_path_with_cwd(codex_parent.as_path(), cwd.as_path()));
|
||||
assert!(policy.can_read_path_with_cwd(alias_parent.as_path(), cwd.as_path()));
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
#[test]
|
||||
fn helper_read_roots_preserve_windows_drive_roots() {
|
||||
use codex_utils_path_uri::PathUri;
|
||||
|
||||
let runtime_paths = ExecServerRuntimePaths::new(
|
||||
std::path::PathBuf::from(r"C:\codex.exe"),
|
||||
/*codex_linux_sandbox_exe*/ None,
|
||||
)
|
||||
.expect("runtime paths");
|
||||
|
||||
assert_eq!(
|
||||
helper_read_roots(&runtime_paths).expect("helper read roots"),
|
||||
vec![PathUri::from_path(r"C:\").expect("drive root URI")],
|
||||
);
|
||||
}
|
||||
|
||||
fn restricted_policy(entries: Vec<FileSystemSandboxEntry>) -> FileSystemSandboxPolicy {
|
||||
FileSystemSandboxPolicy::restricted(entries)
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
use async_trait::async_trait;
|
||||
use codex_utils_absolute_path::AbsolutePathBuf;
|
||||
use codex_utils_path_uri::PathUri;
|
||||
use std::path::Path;
|
||||
use std::path::PathBuf;
|
||||
@@ -264,9 +263,8 @@ impl ExecutorFileSystem for DirectFileSystem {
|
||||
) -> FileSystemResult<PathUri> {
|
||||
reject_sandbox_context(sandbox)?;
|
||||
let path = path.to_abs_path()?;
|
||||
let canonicalized =
|
||||
AbsolutePathBuf::from_absolute_path(tokio::fs::canonicalize(path.as_path()).await?)?;
|
||||
PathUri::from_abs_path(&canonicalized)
|
||||
let canonicalized = tokio::fs::canonicalize(path.as_path()).await?;
|
||||
PathUri::from_path(canonicalized)
|
||||
}
|
||||
|
||||
async fn read_file(
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
use std::path::PathBuf;
|
||||
|
||||
use codex_utils_absolute_path::AbsolutePathBuf;
|
||||
use codex_utils_path_uri::PathUri;
|
||||
|
||||
/// Runtime paths needed by exec-server child processes.
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
pub struct ExecServerRuntimePaths {
|
||||
/// Stable path to the Codex executable used to launch hidden helper modes.
|
||||
pub codex_self_exe: AbsolutePathBuf,
|
||||
pub codex_self_exe: PathUri,
|
||||
/// Path to the Linux sandbox helper alias used when the platform sandbox
|
||||
/// needs to re-enter Codex by argv0.
|
||||
pub codex_linux_sandbox_exe: Option<AbsolutePathBuf>,
|
||||
pub codex_linux_sandbox_exe: Option<PathUri>,
|
||||
}
|
||||
|
||||
impl ExecServerRuntimePaths {
|
||||
@@ -31,13 +31,10 @@ impl ExecServerRuntimePaths {
|
||||
codex_linux_sandbox_exe: Option<PathBuf>,
|
||||
) -> std::io::Result<Self> {
|
||||
Ok(Self {
|
||||
codex_self_exe: absolute_path(codex_self_exe)?,
|
||||
codex_linux_sandbox_exe: codex_linux_sandbox_exe.map(absolute_path).transpose()?,
|
||||
codex_self_exe: PathUri::from_path(codex_self_exe)?,
|
||||
codex_linux_sandbox_exe: codex_linux_sandbox_exe
|
||||
.map(PathUri::from_path)
|
||||
.transpose()?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
fn absolute_path(path: PathBuf) -> std::io::Result<AbsolutePathBuf> {
|
||||
AbsolutePathBuf::from_absolute_path(path.as_path())
|
||||
.map_err(|err| std::io::Error::new(std::io::ErrorKind::InvalidInput, err))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user