mirror of
https://github.com/instructkr/claude-code.git
synced 2026-05-14 09:56:44 +00:00
omx(team): auto-checkpoint worker-2 [3]
This commit is contained in:
@@ -708,7 +708,7 @@ mod tests {
|
||||
use super::{
|
||||
component_contains_glob, derive_glob_walk_root, edit_file, expand_braces, glob_search,
|
||||
grep_search, is_symlink_escape, read_file, read_file_in_workspace, write_file,
|
||||
GrepSearchInput, MAX_WRITE_SIZE,
|
||||
write_file_in_workspace, GrepSearchInput, MAX_WRITE_SIZE,
|
||||
};
|
||||
|
||||
fn temp_path(name: &str) -> std::path::PathBuf {
|
||||
@@ -808,6 +808,68 @@ mod tests {
|
||||
assert!(!is_symlink_escape(&normal, &workspace).expect("check should succeed"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(unix)]
|
||||
fn workspace_read_rejects_symlink_escape_regression_3007_class() {
|
||||
let workspace = temp_path("workspace-read-symlink-escape");
|
||||
let outside = temp_path("workspace-read-symlink-target");
|
||||
std::fs::create_dir_all(&workspace).expect("workspace dir should be created");
|
||||
std::fs::create_dir_all(&outside).expect("outside dir should be created");
|
||||
let outside_file = outside.join("secret.txt");
|
||||
std::fs::write(&outside_file, "outside secret").expect("outside file should write");
|
||||
|
||||
let link_path = workspace.join("linked-secret.txt");
|
||||
std::os::unix::fs::symlink(&outside_file, &link_path).expect("symlink should create");
|
||||
|
||||
let result =
|
||||
read_file_in_workspace(link_path.to_string_lossy().as_ref(), None, None, &workspace);
|
||||
|
||||
assert!(result.is_err(), "symlink escape must be rejected");
|
||||
let error = result.unwrap_err();
|
||||
assert_eq!(error.kind(), std::io::ErrorKind::PermissionDenied);
|
||||
assert!(
|
||||
error.to_string().contains("escapes workspace"),
|
||||
"error should explain workspace escape: {error}"
|
||||
);
|
||||
|
||||
let _ = std::fs::remove_dir_all(&workspace);
|
||||
let _ = std::fs::remove_dir_all(&outside);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(unix)]
|
||||
fn workspace_write_rejects_parent_symlink_escape_regression_3007_class() {
|
||||
let workspace = temp_path("workspace-write-symlink-escape");
|
||||
let outside = temp_path("workspace-write-symlink-target");
|
||||
std::fs::create_dir_all(&workspace).expect("workspace dir should be created");
|
||||
std::fs::create_dir_all(&outside).expect("outside dir should be created");
|
||||
|
||||
let link_dir = workspace.join("linked-outside");
|
||||
std::os::unix::fs::symlink(&outside, &link_dir).expect("symlink dir should create");
|
||||
let escaped_child = link_dir.join("created.txt");
|
||||
|
||||
let result = write_file_in_workspace(
|
||||
escaped_child.to_string_lossy().as_ref(),
|
||||
"must not escape",
|
||||
&workspace,
|
||||
);
|
||||
|
||||
assert!(result.is_err(), "parent symlink escape must be rejected");
|
||||
let error = result.unwrap_err();
|
||||
assert_eq!(error.kind(), std::io::ErrorKind::PermissionDenied);
|
||||
assert!(
|
||||
error.to_string().contains("escapes workspace"),
|
||||
"error should explain workspace escape: {error}"
|
||||
);
|
||||
assert!(
|
||||
!outside.join("created.txt").exists(),
|
||||
"write should not create through an escaping symlink"
|
||||
);
|
||||
|
||||
let _ = std::fs::remove_dir_all(&workspace);
|
||||
let _ = std::fs::remove_dir_all(&outside);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn globs_and_greps_directory() {
|
||||
let dir = temp_path("search-dir");
|
||||
|
||||
@@ -91,6 +91,32 @@ fn status_and_sandbox_emit_json_when_requested() {
|
||||
assert!(sandbox["filesystem_mode"].as_str().is_some());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn status_json_surfaces_permission_mode_override_for_security_audit() {
|
||||
let root = unique_temp_dir("status-json-permission-mode");
|
||||
fs::create_dir_all(&root).expect("temp dir should exist");
|
||||
|
||||
let parsed = assert_json_command(
|
||||
&root,
|
||||
&[
|
||||
"--permission-mode",
|
||||
"read-only",
|
||||
"--output-format",
|
||||
"json",
|
||||
"status",
|
||||
],
|
||||
);
|
||||
|
||||
assert_eq!(parsed["kind"], "status");
|
||||
assert_eq!(parsed["permission_mode"], "read-only");
|
||||
assert!(
|
||||
parsed["workspace"]["cwd"].as_str().is_some(),
|
||||
"status JSON should retain workspace context with permission mode"
|
||||
);
|
||||
|
||||
fs::remove_dir_all(root).expect("cleanup temp dir");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn acp_guidance_emits_json_when_requested() {
|
||||
let root = unique_temp_dir("acp-json");
|
||||
|
||||
Reference in New Issue
Block a user