Files
codex/codex-rs/utils/absolute-path/src/system_aliases.rs
T
felixxia-oai 6f51c65958 Fix macOS system-alias matching in patch permission checks (#47879)
## 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
2026-09-24 16:36:57 +00:00

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;