mirror of
https://github.com/openai/codex.git
synced 2026-10-20 17:38:45 +00:00
## Why Local `apply_patch` permission checks can treat a macOS system alias and its canonical spelling as different locations, sending writes covered by temporary-directory grants for unnecessary approval. ## What changed - Normalize trusted top-level aliases in local policy roots and patch targets, reusing a prepared matcher for permission requests and patch safety checks. - Share alias normalization with Seatbelt and the macOS executor sandbox while preserving mutable symlinks and missing descendants. - Preserve read-only and deny precedence, protected metadata restrictions, and remote URI matching. Propagate normalization failures from fallible permission checks. ## Testing Add macOS regressions for multi-file patches with missing parent directories through both direct `apply_patch` calls and shell interception, asserting automatic approval and file contents. Add unit coverage for alias restriction precedence, mutable symlink preservation, missing descendants, and remote permission isolation. GitOrigin-RevId: 0822ff951eaab728cb1ad91281745fa1b8809f15
36 lines
1.4 KiB
Rust
36 lines
1.4 KiB
Rust
//! Normalize aliases rooted directly in the trusted filesystem root.
|
|
//! Never resolve mutable components below that root, including missing descendants.
|
|
|
|
use crate::AbsolutePathBuf;
|
|
use std::io;
|
|
use std::path::Path;
|
|
|
|
impl AbsolutePathBuf {
|
|
/// Resolve a top-level system alias, such as macOS `/tmp -> /private/tmp`.
|
|
/// All remaining components keep their logical spelling, even if they are
|
|
/// symlinks or do not exist. Only call this on the host that owns the path.
|
|
pub fn normalize_system_aliases(&self) -> io::Result<Self> {
|
|
let Some(top_level) = self.as_path().ancestors().find(|ancestor| {
|
|
ancestor.parent().is_some() && ancestor.parent().and_then(Path::parent).is_none()
|
|
}) else {
|
|
return Ok(self.clone());
|
|
};
|
|
match std::fs::symlink_metadata(top_level) {
|
|
Ok(metadata) if metadata.file_type().is_symlink() => {}
|
|
Ok(_) => return Ok(self.clone()),
|
|
Err(error) if error.kind() == io::ErrorKind::NotFound => return Ok(self.clone()),
|
|
Err(error) => return Err(error),
|
|
}
|
|
let canonical_top_level = dunce::canonicalize(top_level)?;
|
|
let suffix = self
|
|
.as_path()
|
|
.strip_prefix(top_level)
|
|
.map_err(io::Error::other)?;
|
|
Self::from_absolute_path(canonical_top_level.join(suffix))
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
#[path = "system_aliases_tests.rs"]
|
|
mod tests;
|