Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 48 additions & 0 deletions crates/nono-cli/src/tool-sandbox/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,54 @@ pub(crate) fn agent_can_write(
&& (path.starts_with(policy_root) || caps_grant(outer_caps, path, nono::AccessMode::Write))
}

// A policy's fs_write_file entries are best-effort: not every candidate
// path exists on every machine (e.g. a log file some other tool creates
// lazily). Skip a missing one rather than denying the whole command —
// mirrors add_optional_dir/add_optional_read_file in each platform module.
#[cfg(any(target_os = "linux", target_os = "macos"))]
pub(crate) fn add_optional_write_file(
caps: &mut nono::CapabilitySet,
path: std::path::PathBuf,
) -> nono::Result<()> {
match nono::FsCapability::new_file(&path, nono::AccessMode::ReadWrite) {
Ok(capability) => {
caps.add_fs(capability);
Ok(())
}
Err(nono::NonoError::PathNotFound(_)) => Ok(()),
Err(err) => Err(err),
}
}

#[cfg(any(target_os = "linux", target_os = "macos"))]
#[cfg(test)]
mod add_optional_write_file_tests {
use super::add_optional_write_file;
use nono::CapabilitySet;
use std::path::PathBuf;

#[test]
fn missing_path_is_skipped_not_an_error() {
let mut caps = CapabilitySet::new();

let result = add_optional_write_file(&mut caps, PathBuf::from("/no/such/path.log"));

assert!(result.is_ok());
assert!(caps.fs_capabilities().is_empty());
}

#[test]
fn existing_path_is_granted() {
let mut caps = CapabilitySet::new();
let file = tempfile::NamedTempFile::new().expect("tempfile");

let result = add_optional_write_file(&mut caps, file.path().to_path_buf());

assert!(result.is_ok());
assert_eq!(caps.fs_capabilities().len(), 1);
}
}

#[cfg(any(target_os = "linux", target_os = "macos"))]
#[cfg(test)]
mod agent_can_write_tests {
Expand Down
2 changes: 1 addition & 1 deletion crates/nono-cli/src/tool-sandbox/platform/linux.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3592,7 +3592,7 @@ fn add_policy_fs(
if matches!(write_access(&path), AccessMode::Read) {
add_optional_read_file(caps, path)?;
} else {
caps.add_fs(FsCapability::new_file(path, AccessMode::ReadWrite)?);
super::add_optional_write_file(caps, path)?;
}
}
Ok(())
Expand Down
2 changes: 1 addition & 1 deletion crates/nono-cli/src/tool-sandbox/platform/macos.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3068,7 +3068,7 @@ fn add_policy_fs(
if matches!(write_access(&path), AccessMode::Read) {
add_optional_read_file(caps, path)?;
} else {
caps.add_fs(FsCapability::new_file(path, AccessMode::ReadWrite)?);
super::add_optional_write_file(caps, path)?;
}
}
Ok(())
Expand Down