From 180ebb3b02a109a24142d406a1448cb1cb450d99 Mon Sep 17 00:00:00 2001 From: bellman Date: Thu, 14 May 2026 17:29:57 +0900 Subject: [PATCH] Reject Windows absolute PowerShell paths from workspace scope The G002 security gate caught that PowerShell path classification still treated Windows absolute paths as workspace-relative on POSIX, so workspace scope now rejects those tokens before permission downgrades. Constraint: G002-alpha-security requires workspace/path scope across Windows path cases as well as direct paths, symlinks, globbing, shell expansion, and worktrees. Rejected: Relying on PathBuf::is_absolute for Windows syntax on POSIX | it treats C:\ and UNC-like tokens as relative and weakens permission classification. Confidence: high Scope-risk: narrow Directive: Keep bash and PowerShell path classifiers aligned whenever new shell syntax is admitted. Tested: cargo test --manifest-path rust/Cargo.toml -p tools path_scope -- --nocapture; cargo test --manifest-path rust/Cargo.toml -p tools --test path_scope_enforcement -- --nocapture; cargo test --manifest-path rust/Cargo.toml -p runtime workspace_ -- --nocapture; python3 -m pytest tests/test_security_scope.py -q; cargo check --manifest-path rust/Cargo.toml --workspace. Not-tested: Full cargo test --workspace still has existing unrelated rusty-claude-cli session lifecycle failure reported by workers. Co-authored-by: OmX --- rust/crates/tools/src/lib.rs | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/rust/crates/tools/src/lib.rs b/rust/crates/tools/src/lib.rs index 868fe4e6..3024d1f5 100644 --- a/rust/crates/tools/src/lib.rs +++ b/rust/crates/tools/src/lib.rs @@ -2270,7 +2270,17 @@ fn extract_powershell_path(command: &str) -> Option { /// Check if a path is within the current workspace. fn is_within_workspace(path: &str) -> bool { - let path = PathBuf::from(path); + let trimmed = path.trim_matches(|ch: char| { + matches!( + ch, + '"' | '\'' | '`' | ',' | ';' | ')' | '(' | '[' | ']' | '{' | '}' + ) + }); + if looks_like_windows_absolute_path(trimmed) { + return false; + } + + let path = PathBuf::from(trimmed); // If path is absolute, check if it starts with CWD if path.is_absolute() {