File zeroclaw-git-ops-security-policy.patch of Package zeroclaw
commit 162050dafa9dac5cd0b607cf8766b2f39f32362c
Author: Oleksandr Ostrenko <openbuildservice@ostrenko.dev>
Date: Sat Mar 28 16:13:05 2026 +0100
Use security policy when evaluating git paths
diff --git a/src/tools/git_operations.rs b/src/tools/git_operations.rs
index 75d3d2b3b..20f74952f 100644
--- a/src/tools/git_operations.rs
+++ b/src/tools/git_operations.rs
@@ -67,7 +67,7 @@ impl GitOperationsTool {
/// Resolve a user-provided path to an absolute path within the workspace.
/// Returns the workspace_dir if no path is provided.
- /// Rejects paths that escape the workspace via traversal.
+ /// Rejects paths that based on the security policy (`is_resolved_path_allowed`).
fn resolve_working_dir(&self, path: Option<&str>) -> anyhow::Result<std::path::PathBuf> {
let base = match path {
Some(p) if !p.is_empty() => {
@@ -76,16 +76,26 @@ impl GitOperationsTool {
} else {
self.workspace_dir.join(p)
};
+
let resolved = candidate
.canonicalize()
.map_err(|e| anyhow::anyhow!("Cannot resolve path '{}': {}", p, e))?;
- let workspace_canonical = self
- .workspace_dir
- .canonicalize()
- .unwrap_or_else(|_| self.workspace_dir.clone());
- if !resolved.starts_with(&workspace_canonical) {
- anyhow::bail!("Path '{}' resolves outside the workspace directory", p);
+
+ if !resolved.is_dir() {
+ anyhow::bail!("project_path must be a directory: {}", resolved.display());
}
+
+ // Security policy check using the string representation.
+ if !self
+ .security
+ .is_resolved_path_allowed(resolved.as_ref())
+ {
+ anyhow::bail!(
+ "project_path is outside the allowed roots: {}",
+ resolved.display()
+ );
+ }
+
resolved
}
_ => self.workspace_dir.clone(),