readd tests, remove markdown files
This commit is contained in:
parent
e2634c72c2
commit
9a6fa76825
17 changed files with 1352 additions and 0 deletions
|
|
@ -1388,4 +1388,112 @@ mod tests {
|
|||
);
|
||||
}
|
||||
}
|
||||
|
||||
// ── §1.2 Path resolution / symlink bypass tests ──────────
|
||||
|
||||
#[test]
|
||||
fn resolved_path_blocks_outside_workspace() {
|
||||
let workspace = std::env::temp_dir().join("zeroclaw_test_resolved_path");
|
||||
let _ = std::fs::create_dir_all(&workspace);
|
||||
|
||||
// Use the canonicalized workspace so starts_with checks match
|
||||
let canonical_workspace = workspace
|
||||
.canonicalize()
|
||||
.unwrap_or_else(|_| workspace.clone());
|
||||
|
||||
let policy = SecurityPolicy {
|
||||
workspace_dir: canonical_workspace.clone(),
|
||||
..SecurityPolicy::default()
|
||||
};
|
||||
|
||||
// A resolved path inside the workspace should be allowed
|
||||
let inside = canonical_workspace.join("subdir").join("file.txt");
|
||||
assert!(
|
||||
policy.is_resolved_path_allowed(&inside),
|
||||
"path inside workspace should be allowed"
|
||||
);
|
||||
|
||||
// A resolved path outside the workspace should be blocked
|
||||
let canonical_temp = std::env::temp_dir()
|
||||
.canonicalize()
|
||||
.unwrap_or_else(|_| std::env::temp_dir());
|
||||
let outside = canonical_temp.join("outside_workspace_zeroclaw");
|
||||
assert!(
|
||||
!policy.is_resolved_path_allowed(&outside),
|
||||
"path outside workspace must be blocked"
|
||||
);
|
||||
|
||||
let _ = std::fs::remove_dir_all(&workspace);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn resolved_path_blocks_root_escape() {
|
||||
let policy = SecurityPolicy {
|
||||
workspace_dir: PathBuf::from("/home/zeroclaw_user/project"),
|
||||
..SecurityPolicy::default()
|
||||
};
|
||||
|
||||
assert!(
|
||||
!policy.is_resolved_path_allowed(Path::new("/etc/passwd")),
|
||||
"resolved path to /etc/passwd must be blocked"
|
||||
);
|
||||
assert!(
|
||||
!policy.is_resolved_path_allowed(Path::new("/root/.bashrc")),
|
||||
"resolved path to /root/.bashrc must be blocked"
|
||||
);
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
#[test]
|
||||
fn resolved_path_blocks_symlink_escape() {
|
||||
use std::os::unix::fs::symlink;
|
||||
|
||||
let root = std::env::temp_dir().join("zeroclaw_test_symlink_escape");
|
||||
let workspace = root.join("workspace");
|
||||
let outside = root.join("outside_target");
|
||||
|
||||
let _ = std::fs::remove_dir_all(&root);
|
||||
std::fs::create_dir_all(&workspace).unwrap();
|
||||
std::fs::create_dir_all(&outside).unwrap();
|
||||
|
||||
// Create a symlink inside workspace pointing outside
|
||||
let link_path = workspace.join("escape_link");
|
||||
symlink(&outside, &link_path).unwrap();
|
||||
|
||||
let policy = SecurityPolicy {
|
||||
workspace_dir: workspace.clone(),
|
||||
..SecurityPolicy::default()
|
||||
};
|
||||
|
||||
// The resolved symlink target should be outside workspace
|
||||
let resolved = link_path.canonicalize().unwrap();
|
||||
assert!(
|
||||
!policy.is_resolved_path_allowed(&resolved),
|
||||
"symlink-resolved path outside workspace must be blocked"
|
||||
);
|
||||
|
||||
let _ = std::fs::remove_dir_all(&root);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn is_path_allowed_blocks_null_bytes() {
|
||||
let policy = default_policy();
|
||||
assert!(
|
||||
!policy.is_path_allowed("file\0.txt"),
|
||||
"paths with null bytes must be blocked"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn is_path_allowed_blocks_url_encoded_traversal() {
|
||||
let policy = default_policy();
|
||||
assert!(
|
||||
!policy.is_path_allowed("..%2fetc%2fpasswd"),
|
||||
"URL-encoded path traversal must be blocked"
|
||||
);
|
||||
assert!(
|
||||
!policy.is_path_allowed("subdir%2f..%2f..%2fetc"),
|
||||
"URL-encoded parent dir traversal must be blocked"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue