mirror of
https://github.com/openai/codex.git
synced 2026-11-12 21:20:34 +00:00
## Why Filesystem denial paths need to use the owning environment's path syntax, base directory, and home directory. Host-native resolution cannot supply those facts for another platform, and invalid denials must not be silently skipped when building the sandbox policy. ## What changed - Add `ConfigPathContext` to requirements layers so `permissions.filesystem.deny_read` can resolve using explicit POSIX or Windows path facts, with native defaults when no context is supplied. - Share URI-based resolution and validation for literal paths and glob prefixes. Reject ambiguous or lossy paths, including NUL bytes, Windows stream syntax, and unsupported UNC spellings. - Move denial conversion into `FilesystemConstraints::apply_to_policy`, preserving glob patterns and deduplicating entries. Validate all denials before modifying the policy and propagate failures through configuration loading. ## Testing Add tests for per-layer base and home resolution, Windows drives and globs, nested context restoration, missing home directories, and policy conversion without partial mutation. Add a configuration-loading regression test for a required denial glob containing a NUL byte. GitOrigin-RevId: fa0da0d149407958e39897a39fe7b87edd6f1644
63 lines
2.4 KiB
Rust
63 lines
2.4 KiB
Rust
//! Convert resolved filesystem denials into portable policy entries.
|
|
|
|
use crate::FilesystemConstraints;
|
|
use codex_protocol::permissions::FileSystemAccessMode;
|
|
use codex_protocol::permissions::FileSystemPath;
|
|
use codex_protocol::permissions::FileSystemSandboxEntry;
|
|
use codex_protocol::permissions::FileSystemSandboxPolicy;
|
|
use codex_utils_path_uri::LegacyAppPathString;
|
|
use codex_utils_path_uri::LegacyAppPathStringError;
|
|
use codex_utils_path_uri::PathConvention;
|
|
use codex_utils_path_uri::PathUri;
|
|
use std::io;
|
|
|
|
impl FilesystemConstraints {
|
|
/// Adds denials without changing existing entries or other policy settings.
|
|
/// `convention` must match the executor facts used to resolve these requirements.
|
|
/// Literal paths become URIs; glob spellings and entry order are preserved.
|
|
/// Invalid denials return an error before the policy is changed.
|
|
pub fn apply_to_policy(
|
|
&self,
|
|
policy: &mut FileSystemSandboxPolicy,
|
|
convention: PathConvention,
|
|
) -> io::Result<()> {
|
|
let entries = self
|
|
.deny_read
|
|
.iter()
|
|
.map(|deny_read| {
|
|
PathUri::validate_config_path_text(deny_read.as_str(), convention)?;
|
|
let path = if deny_read.contains_glob() {
|
|
FileSystemPath::GlobPattern {
|
|
pattern: deny_read.as_str().to_string(),
|
|
}
|
|
} else {
|
|
let mut path = LegacyAppPathString::from_string(deny_read.as_str())
|
|
.to_path_uri(convention)?;
|
|
path.validate_config_path(convention)?;
|
|
// Match Core's existing URI spelling for UNC share roots.
|
|
if path.to_url().host_str().is_some() {
|
|
path = path.join(".")?;
|
|
}
|
|
path.into()
|
|
};
|
|
Ok(FileSystemSandboxEntry::new(
|
|
path,
|
|
FileSystemAccessMode::Deny,
|
|
))
|
|
})
|
|
.collect::<Result<Vec<_>, LegacyAppPathStringError>>()
|
|
.map_err(|error| {
|
|
io::Error::new(
|
|
io::ErrorKind::InvalidInput,
|
|
format!("invalid permissions.filesystem.deny_read path: {error}"),
|
|
)
|
|
})?;
|
|
for entry in entries {
|
|
if !policy.entries.contains(&entry) {
|
|
policy.entries.push(entry);
|
|
}
|
|
}
|
|
Ok(())
|
|
}
|
|
}
|