zeroclaw-labs/zeroclaw · error
Blocked potentially dangerous git argument: {arg}
Error message
Blocked potentially dangerous git argument: {arg} What it means
sanitize_git_args rejected one of the whitespace-split arguments to a git tool call (git_diff, git_add, git_checkout, git_worktree) because it matched a blocklist of command-injection vectors: options that execute external programs (--exec=, --upload-pack=, --receive-pack=), TTY-coupled options (--pager=, --editor=, --no-verify), shell substitution tokens '$(' and backtick, or the metacharacters '|', ';', '>' (git_operations.rs:30-42). The whole request fails before any git subprocess spawns.
Source
Thrown at crates/zeroclaw-tools/src/git_operations.rs:42
/// Sanitize git arguments to prevent injection attacks
fn sanitize_git_args(&self, args: &str) -> anyhow::Result<Vec<String>> {
let mut result = Vec::new();
for arg in args.split_whitespace() {
// Block dangerous git options that could lead to command injection
let arg_lower = arg.to_lowercase();
if arg_lower.starts_with("--exec=")
|| arg_lower.starts_with("--upload-pack=")
|| arg_lower.starts_with("--receive-pack=")
|| arg_lower.starts_with("--pager=")
|| arg_lower.starts_with("--editor=")
|| arg_lower == "--no-verify"
|| arg_lower.contains("$(")
|| arg_lower.contains('`')
|| arg.contains('|')
|| arg.contains(';')
|| arg.contains('>')
{
anyhow::bail!("Blocked potentially dangerous git argument: {arg}");
}
// Block `-c` config injection (exact match or `-c=...` prefix).
// This must not false-positive on `--cached` or `-cached`.
if arg_lower == "-c" || arg_lower.starts_with("-c=") {
anyhow::bail!("Blocked potentially dangerous git argument: {arg}");
}
result.push(arg.to_string());
}
Ok(result)
}
/// Check if an operation requires write access
fn requires_write_access(&self, operation: &str) -> bool {
matches!(
operation,
"commit" | "add" | "checkout" | "stash" | "reset" | "revert" | "worktree"
)
}View on GitHub (pinned to 88bb9c8533)
Solutions
- Remove the offending option or metacharacter from the args string and re-issue the call.
- If you need to bypass hooks (--no-verify) or set a pager, run that git command via a shell exec tool under its own policy instead of this one.
- Rename branches/paths that legitimately contain ';', '|', '>', '$(' before passing them to the tool.
- Mirror the same blocklist in the caller's pre-validation so rejection happens client-side with better context.
Example fix
// before git_checkout(args: "checkout feature;rm -rf .cache") // -> Blocked potentially dangerous git argument: feature;rm -rf .cache // after git_checkout(args: "checkout feature")
Defensive patterns
Strategy: validation
Validate before calling
// Mirror the tool's blocklist before sending args.
fn is_safe_git_arg(arg: &str) -> bool {
let l = arg.to_lowercase();
!(l.starts_with("--exec=") || l.starts_with("--upload-pack=")
|| l.starts_with("--receive-pack=") || l.starts_with("--pager=")
|| l.starts_with("--editor=") || l == "--no-verify"
|| l.contains("$(") || l.contains('`')
|| arg.contains('|') || arg.contains(';') || arg.contains('>'))
}
fn validate_git_args(args: &str) -> Result<(), String> {
match args.split_whitespace().find(|a| !is_safe_git_arg(a)) {
Some(bad) => Err(format!("blocked by policy: {bad}")),
None => Ok(()),
}
} Type guard
fn is_safe_git_arg(arg: &str) -> bool {
let l = arg.to_lowercase();
!(l.starts_with("--exec=") || l.starts_with("--upload-pack=")
|| l.starts_with("--receive-pack=") || l.starts_with("--pager=")
|| l.starts_with("--editor=") || l == "--no-verify"
|| l.contains("$(") || l.contains('`')
|| arg.contains('|') || arg.contains(';') || arg.contains('>'))
} Try / catch
match git_tool.execute(params).await {
Err(e) if e.to_string().contains("Blocked potentially dangerous git argument") => {
// extract the blocked token, surface it to the caller/LLM, and
// re-issue the command without it; never retry the same string
}
r => r,
} Prevention
- Never concatenate untrusted input into the args string
- Build args as a Vec<&str> of known-good tokens and join for the tool
- Reject branch/path names containing ; | > $ ( ` at input boundaries
- Do not attempt --no-verify or pager/editor overrides through this tool
When it happens
Trigger: Passing args strings like "show HEAD --pager=cat", "commit --no-verify", "log --exec=/bin/sh", or any token containing ';', '|', '>' or '$(' — including a file path or ref name that happens to embed one of those characters (e.g. a branch named 'feat;x'). The for-loop at git_operations.rs:27 checks every token from args.split_whitespace().
Common situations: LLM-driven agents forwarding shell-style habits into the structured git tool; users trying to skip hooks with --no-verify; scripts concatenating untrusted input into the args string; branch or path names containing semicolons or pipes; copy-pasted one-liners where a pipe was part of the original command.
Related errors
- Path '{}' resolves outside the workspace directory
- Path not allowed: parent-directory traversal is not allowed
- Worktree path '{}' resolves outside the workspace or allowed
- Branch name contains invalid characters
- purge_session not supported by this memory backend
AI-assisted analysis of zeroclaw-labs/zeroclaw@88bb9c8533 (2026-08-23).
Data as JSON: /api/errors/1449336bf13a3bb5.
Report an issue: GitHub.