mirror of
https://github.com/instructkr/claude-code.git
synced 2026-05-14 18:06:45 +00:00
task: prefer tests before fixes
Add focused regression coverage for path-scope enforcement before implementation changes land, preserving worker-1 ownership of the fix path. Constraint: task 4 requested tests-first coverage for direct path, symlink, glob/shell expansion, worktree, and Windows-style path cases.\nRejected: implementation edits in enforcement code | worker-1 owns minimal implementation changes.\nConfidence: high\nScope-risk: narrow\nDirective: Keep these regressions red until path canonicalization/enforcement blocks outside-workspace reads before dispatch.\nTested: cargo fmt -p tools -- --check; cargo check -p tools; cargo clippy -p tools --test path_scope_enforcement (warnings only, pre-existing); cargo test -p tools --test path_scope_enforcement (expected red: 4 failing path-scope gaps, 2 passing baselines).\nNot-tested: Full workspace test suite because the new regression tests intentionally fail until implementation lands.
This commit is contained in:
@@ -30,6 +30,14 @@ fn run_bash(command: &str) -> Result<String, String> {
|
||||
workspace_write_registry().execute("bash", &json!({ "command": command }))
|
||||
}
|
||||
|
||||
fn run_powershell(command: &str) -> Result<String, String> {
|
||||
workspace_write_registry().execute("PowerShell", &json!({ "command": command }))
|
||||
}
|
||||
|
||||
fn run_read_file(path: &Path) -> Result<String, String> {
|
||||
workspace_write_registry().execute("read_file", &json!({ "path": path.display().to_string() }))
|
||||
}
|
||||
|
||||
fn assert_permission_denied(result: Result<String, String>, case_name: &str) {
|
||||
let err = result
|
||||
.unwrap_err_or_else(|ok| panic!("{case_name} should be denied before execution, got {ok}"));
|
||||
@@ -86,6 +94,24 @@ fn direct_paths_allow_workspace_file_and_deny_absolute_outside_file() {
|
||||
let _ = fs::remove_file(outside);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn file_tool_direct_outside_path_is_denied_before_reading() {
|
||||
let _guard = env_lock()
|
||||
.lock()
|
||||
.unwrap_or_else(std::sync::PoisonError::into_inner);
|
||||
let root = temp_path("file-tool-direct");
|
||||
fs::create_dir_all(&root).expect("create workspace");
|
||||
let outside = temp_path("file-tool-secret.txt");
|
||||
fs::write(&outside, "secret\n").expect("write outside file");
|
||||
|
||||
with_cwd(&root, || {
|
||||
assert_permission_denied(run_read_file(&outside), "read_file outside workspace");
|
||||
});
|
||||
|
||||
let _ = fs::remove_dir_all(root);
|
||||
let _ = fs::remove_file(outside);
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
#[test]
|
||||
fn symlink_resolving_outside_workspace_is_denied_before_execution() {
|
||||
@@ -162,4 +188,17 @@ fn windows_style_absolute_paths_are_denied_before_execution() {
|
||||
] {
|
||||
assert_permission_denied(run_bash(command), name);
|
||||
}
|
||||
|
||||
for (name, command) in [
|
||||
(
|
||||
"powershell windows drive backslash",
|
||||
r"Get-Content -Path C:\Users\attacker\secret.txt",
|
||||
),
|
||||
(
|
||||
"powershell windows drive slash",
|
||||
r"Get-Content -Path C:/Users/attacker/secret.txt",
|
||||
),
|
||||
] {
|
||||
assert_permission_denied(run_powershell(command), name);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user