codex / codex-rs /protocol /src /permissions /target_tests.rs
SaylorTwift's picture
SaylorTwift HF Staff
Add files using upload-large-folder tool
afa0cbf verified
Raw History Blame Contribute Delete
14.8 kB
//! Regression coverage for remote path matching and managed-denial enforcement.
use super::*;
use crate::permissions::FileSystemAccessMode;
use crate::permissions::FileSystemSandboxEntry;
use crate::permissions::PROTECTED_METADATA_PATH_NAMES;
use pretty_assertions::assert_eq;
fn uri(input: &str) -> PathUri {
PathUri::parse(input).unwrap()
}
fn deny(path: FileSystemPath) -> FileSystemSandboxEntry {
FileSystemSandboxEntry::new(path, FileSystemAccessMode::Deny)
}
#[test]
fn read_denials_use_target_paths_and_native_glob_semantics() {
for base in [
"file:///work/repo",
"file:///Users/agent/repo",
"file:///C:/work/repo",
"file://server/share/repo",
] {
let cwd = uri(base);
let context = FileSystemSandboxPolicyContext {
cwd: &cwd,
workspace_roots: std::slice::from_ref(&cwd),
user_home_dir: Some(&cwd),
temporary_directories: Some(&[]),
};
let policy = FileSystemSandboxPolicy::restricted(vec![
deny(FileSystemPath::Path {
path: cwd.join("private").unwrap(),
}),
deny(FileSystemPath::GlobPattern {
pattern: "~/secrets/*.key".into(),
}),
deny(FileSystemPath::GlobPattern {
pattern: "nested/**/*.env".into(),
}),
]);
let matcher = ReadDenyMatcher::try_new_with_context(&policy, &context)
.unwrap()
.unwrap();
for (path, expected) in [
("private", true),
("private/file", true),
("private-other/file", false),
("secrets/token.key", true),
("secrets/nested/token.key", false),
("nested/.env", true),
("nested/deep/token.env", true),
("public/file", false),
] {
assert_eq!(
matcher.is_read_denied_uri(&cwd.join(path).unwrap(), &context),
expected,
"{base}: {path}"
);
}
assert_eq!(
matcher.is_read_denied_uri(&cwd.join("PRIVATE/file").unwrap(), &context),
cwd.infer_path_convention() == Some(PathConvention::Windows),
);
assert!(matcher.is_read_denied_uri(&uri("file:///C:/foreign%2Fpath"), &context));
}
}
#[test]
fn managed_denials_reject_concrete_read_and_write_grants() {
for base in [
"file:///work/repo",
"file:///C:/work/repo",
"file://server/share/repo",
] {
let cwd = uri(base);
let private = cwd.join("private").unwrap();
let required = FileSystemSandboxPolicy::restricted(vec![deny(FileSystemPath::Path {
path: private.clone(),
})]);
let context = FileSystemSandboxPolicyContext {
cwd: &cwd,
workspace_roots: std::slice::from_ref(&cwd),
user_home_dir: None,
temporary_directories: Some(&[]),
};
let mut policy = FileSystemSandboxPolicy::workspace_write_with_path_uris(
&[],
/*exclude_tmpdir_env_var*/ true,
/*exclude_slash_tmp*/ true,
);
policy.entries.extend(required.entries.clone());
assert_eq!(
policy.validate_managed_deny_read(&required, &context),
Ok(())
);
for access in [FileSystemAccessMode::Read, FileSystemAccessMode::Write] {
let mut carveout = policy.clone();
carveout.entries.push(FileSystemSandboxEntry::new(
FileSystemPath::Path {
path: private.join("carveout").unwrap(),
},
access,
));
assert_eq!(
carveout.validate_managed_deny_read(&required, &context),
Err(SHADOWED.into())
);
}
}
}
#[test]
fn managed_denials_preserve_native_metadata_read_rejections() {
for base in [
"file:///executor/home",
"file:///C:/Users/executor",
"file://server/share/executor",
] {
let extra_root = uri(base);
let cwd = extra_root.join("workspace").unwrap();
let context = FileSystemSandboxPolicyContext {
cwd: &cwd,
workspace_roots: std::slice::from_ref(&cwd),
user_home_dir: Some(&extra_root),
temporary_directories: Some(&[]),
};
let legacy = FileSystemSandboxPolicy::workspace_write_with_path_uris(
std::slice::from_ref(&extra_root),
/*exclude_tmpdir_env_var*/ true,
/*exclude_slash_tmp*/ true,
);
for name in [".codex", ".git"] {
let denied_root = extra_root.join(name).unwrap();
let child = denied_root.join("reopened").unwrap();
for (path, expected_root_access) in [
(
FileSystemPath::Path {
path: denied_root.clone(),
},
FileSystemAccessMode::Deny,
),
(
FileSystemPath::GlobPattern {
pattern: denied_root.join("*").unwrap().inferred_native_path_string(),
},
FileSystemAccessMode::Read,
),
] {
let required = FileSystemSandboxPolicy::restricted(vec![deny(path)]);
let mut policy = legacy.clone();
policy.preserve_deny_read_restrictions_from(&required);
assert_eq!(
(
policy.resolve_access(&denied_root, &context),
policy.validate_managed_deny_read(&required, &context),
),
(
expected_root_access,
if expected_root_access == FileSystemAccessMode::Deny {
Err(SHADOWED.into())
} else {
Ok(())
},
),
"{base}: {name}",
);
let matcher = ReadDenyMatcher::try_new_with_context(&required, &context)
.unwrap()
.unwrap();
assert!(matcher.is_read_denied_uri(&child, &context));
for access in [FileSystemAccessMode::Read, FileSystemAccessMode::Write] {
let mut reopened = policy.clone();
reopened.entries.push(FileSystemSandboxEntry::new(
FileSystemPath::Path {
path: child.clone(),
},
access,
));
assert_eq!(
reopened.validate_managed_deny_read(&required, &context),
Err(SHADOWED.into()),
"{base}: {name}: {access}",
);
}
}
}
}
}
#[test]
fn malformed_or_unresolvable_denials_fail_closed() {
let cwd = uri("file:///work/repo");
let context = FileSystemSandboxPolicyContext {
cwd: &cwd,
workspace_roots: &[],
user_home_dir: None,
temporary_directories: Some(&[]),
};
for pattern in ["~/secrets/**", "secrets/[z-a]"] {
let policy = FileSystemSandboxPolicy::restricted(vec![deny(FileSystemPath::GlobPattern {
pattern: pattern.into(),
})]);
assert!(ReadDenyMatcher::try_new_with_context(&policy, &context).is_err());
}
let policy = FileSystemSandboxPolicy::restricted(vec![deny(FileSystemPath::Path {
path: uri("file:///C:/private"),
})]);
assert!(ReadDenyMatcher::try_new_with_context(&policy, &context).is_err());
}
#[test]
fn slash_tmp_denials_follow_the_executor_convention() {
let policy = FileSystemSandboxPolicy::restricted(vec![deny(FileSystemPath::Special {
value: FileSystemSpecialPath::SlashTmp,
})]);
for (base, active) in [("file:///work", true), ("file:///C:/work", false)] {
let cwd = uri(base);
let context = FileSystemSandboxPolicyContext {
cwd: &cwd,
workspace_roots: &[],
user_home_dir: None,
temporary_directories: None,
};
let matcher = ReadDenyMatcher::try_new_with_context(&policy, &context).unwrap();
assert_eq!(matcher.is_some(), active);
if let Some(matcher) = matcher {
assert!(matcher.is_read_denied_uri(&cwd.join("/tmp/file").unwrap(), &context));
}
}
}
#[test]
fn remote_workspace_write_keeps_metadata_protected() {
let cwd = uri("file:///C:/repo");
let extra = uri("file:///D:/extra");
let policy = FileSystemSandboxPolicy::workspace_write_with_path_uris(
std::slice::from_ref(&extra),
/*exclude_tmpdir_env_var*/ true,
/*exclude_slash_tmp*/ true,
);
let context = FileSystemSandboxPolicyContext {
cwd: &cwd,
workspace_roots: std::slice::from_ref(&cwd),
user_home_dir: None,
temporary_directories: Some(&[]),
};
for name in PROTECTED_METADATA_PATH_NAMES {
assert!(
policy
.entries
.contains(&FileSystemSandboxEntry::skip_missing_path(
FileSystemPath::Path {
path: extra.join(name).unwrap()
},
FileSystemAccessMode::Read,
))
);
}
for root in [cwd.clone(), extra] {
assert!(policy.can_write_path(&root.join("file").unwrap(), &context));
for name in PROTECTED_METADATA_PATH_NAMES {
let path = root.join(name).unwrap().join("file").unwrap();
assert!(policy.can_read_path(&path, &context));
assert!(!policy.can_write_path(&path, &context));
}
}
}
#[test]
fn read_globs_reject_metacharacters_in_home_and_cwd_facts() {
for prefix in ["file:///home", "file:///C:/Users"] {
let parent = uri(prefix);
let directory = parent.join("sam[1]").unwrap();
for (pattern, cwd, home) in [
("~/private/*.key", &parent, Some(&directory)),
("private/*.key", &directory, None),
] {
let policy =
FileSystemSandboxPolicy::restricted(vec![deny(FileSystemPath::GlobPattern {
pattern: pattern.into(),
})]);
let context = FileSystemSandboxPolicyContext {
cwd,
workspace_roots: std::slice::from_ref(&directory),
user_home_dir: home,
temporary_directories: None,
};
assert!(ReadDenyMatcher::try_new_with_context(&policy, &context).is_err());
let matcher = ReadDenyMatcher::from_context(&policy, &context).unwrap();
assert!(
matcher.is_read_denied_uri(&directory.join("private/a.key").unwrap(), &context)
);
}
}
}
#[test]
fn workspace_globs_fail_closed_on_literal_root_metacharacters_on_every_host() {
for prefix in ["file:///home", "file:///C:/Users"] {
let root = uri(prefix).join("sam[1]").unwrap();
let policy = FileSystemSandboxPolicy::restricted(vec![deny(FileSystemPath::GlobPattern {
pattern: crate::permissions::project_roots_glob_pattern(std::path::Path::new(
"private/*.key",
)),
})]);
let materialized = policy
.clone()
.materialize_project_roots_with_path_uris(std::slice::from_ref(&root));
assert_eq!(
materialized,
FileSystemSandboxPolicy::restricted(vec![deny(root.clone().into())]),
);
if let Ok(native_root) = root.to_abs_path() {
assert_eq!(
policy.materialize_project_roots_with_workspace_roots(&[native_root]),
materialized,
);
}
}
}
#[test]
fn materializing_legacy_home_relative_workspace_denials_removes_all_grants() {
for (root, home) in [
("file:///work/repo", "file:///home/sam"),
("file:///C:/work/repo", "file:///D:/Users/sam"),
] {
let root = uri(root);
let home = uri(home);
let convention = root.infer_path_convention().unwrap();
for subpath in ["~", "~/private/*.env", r"~\private", r"~\private\*.env"] {
if convention.home_relative_suffix(subpath).is_none() {
continue;
}
let denied_path = if subpath.contains('*') {
FileSystemPath::GlobPattern {
pattern: crate::permissions::project_roots_glob_pattern(std::path::Path::new(
subpath,
)),
}
} else {
FileSystemPath::Special {
value: FileSystemSpecialPath::ProjectRoots {
subpath: Some(subpath.into()),
},
}
};
let policy = FileSystemSandboxPolicy::restricted(vec![
FileSystemSandboxEntry::new(
FileSystemPath::Special {
value: FileSystemSpecialPath::Root,
},
FileSystemAccessMode::Read,
),
FileSystemSandboxEntry::new(
FileSystemPath::Special {
value: FileSystemSpecialPath::ProjectRoots { subpath: None },
},
FileSystemAccessMode::Write,
),
FileSystemSandboxEntry::new(home.clone().into(), FileSystemAccessMode::Write),
deny(denied_path),
]);
let mut materialized = vec![
policy
.clone()
.materialize_project_roots_with_path_uris(std::slice::from_ref(&root)),
policy
.clone()
.with_materialized_project_roots_for_path_uris(std::slice::from_ref(&root)),
];
if let Ok(native_root) = root.to_abs_path() {
materialized.push(
policy
.clone()
.materialize_project_roots_with_workspace_roots(std::slice::from_ref(
&native_root,
)),
);
materialized.push(policy.with_materialized_project_roots_for_workspace_roots(
std::slice::from_ref(&native_root),
));
}
for policy in materialized {
assert_eq!(policy, FileSystemSandboxPolicy::restricted(Vec::new()));
}
}
}
}