mirror of
https://github.com/instructkr/claude-code.git
synced 2026-05-14 18:06:45 +00:00
Prevent workspace escape through tool path resolution
File and shell tool dispatch now resolves path-sensitive operations through workspace-scoped wrappers so direct paths, globs, symlinks, shell expansion, and Windows absolute path probes fail before execution when they leave the workspace. Constraint: G002-alpha-security requires alpha-blocking workspace/path scope enforcement without mutating .omx/ultragoal Rejected: string-prefix only checks | they miss canonical symlink and glob expansion escapes Confidence: high Scope-risk: moderate Directive: keep new file/shell tool entrypoints wired through workspace-aware wrappers before dispatch Tested: python3 -m unittest discover -s tests -v; python3 -m compileall -q src tests; cargo test -p runtime workspace --manifest-path rust/Cargo.toml --quiet; cargo test -p tools workspace --manifest-path rust/Cargo.toml --quiet; cargo test -p tools given_workspace_write_enforcer_when_bash --manifest-path rust/Cargo.toml --quiet; cargo test -p tools file_tools_reject --manifest-path rust/Cargo.toml --quiet; cargo fmt --all --manifest-path rust/Cargo.toml -- --check; cargo check --manifest-path rust/Cargo.toml --workspace Not-tested: full unfiltered cargo test workspace due task-time constraints; targeted runtime/tools workspace security tests and full cargo check passed Co-authored-by: OmX <omx@oh-my-codex.dev>
This commit is contained in:
@@ -8693,8 +8693,12 @@ mod tests {
|
||||
let _guard = env_lock()
|
||||
.lock()
|
||||
.unwrap_or_else(std::sync::PoisonError::into_inner);
|
||||
let path = temp_path("subagent-input.txt");
|
||||
let root = temp_path("subagent-runtime");
|
||||
std::fs::create_dir_all(&root).expect("create root");
|
||||
let path = root.join("subagent-input.txt");
|
||||
std::fs::write(&path, "hello from child").expect("write input file");
|
||||
let original_dir = std::env::current_dir().expect("cwd");
|
||||
std::env::set_current_dir(&root).expect("set cwd");
|
||||
|
||||
let mut runtime = ConversationRuntime::new(
|
||||
Session::new(),
|
||||
@@ -8726,7 +8730,8 @@ mod tests {
|
||||
if output.contains("hello from child")
|
||||
)));
|
||||
|
||||
let _ = std::fs::remove_file(path);
|
||||
std::env::set_current_dir(&original_dir).expect("restore cwd");
|
||||
let _ = std::fs::remove_dir_all(root);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -9787,11 +9792,14 @@ printf 'pwsh:%s' "$1"
|
||||
fs::create_dir_all(&root).expect("create root");
|
||||
let file = root.join("readable.txt");
|
||||
fs::write(&file, "content\n").expect("write test file");
|
||||
let original_dir = std::env::current_dir().expect("cwd");
|
||||
std::env::set_current_dir(&root).expect("set cwd");
|
||||
|
||||
let registry = read_only_registry();
|
||||
let result = registry.execute("read_file", &json!({ "path": file.display().to_string() }));
|
||||
assert!(result.is_ok(), "read_file should be allowed: {result:?}");
|
||||
|
||||
std::env::set_current_dir(&original_dir).expect("restore cwd");
|
||||
let _ = fs::remove_dir_all(root);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user