{"record":{"id":"1449336bf13a3bb5","repo":"zeroclaw-labs/zeroclaw","slug":"blocked-potentially-dangerous-git-argument-arg","errorCode":null,"errorMessage":"Blocked potentially dangerous git argument: {arg}","messagePattern":"Blocked potentially dangerous git argument: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/zeroclaw-tools/src/git_operations.rs","lineNumber":42,"sourceCode":"    /// Sanitize git arguments to prevent injection attacks\n    fn sanitize_git_args(&self, args: &str) -> anyhow::Result<Vec<String>> {\n        let mut result = Vec::new();\n        for arg in args.split_whitespace() {\n            // Block dangerous git options that could lead to command injection\n            let arg_lower = arg.to_lowercase();\n            if arg_lower.starts_with(\"--exec=\")\n                || arg_lower.starts_with(\"--upload-pack=\")\n                || arg_lower.starts_with(\"--receive-pack=\")\n                || arg_lower.starts_with(\"--pager=\")\n                || arg_lower.starts_with(\"--editor=\")\n                || arg_lower == \"--no-verify\"\n                || arg_lower.contains(\"$(\")\n                || arg_lower.contains('`')\n                || arg.contains('|')\n                || arg.contains(';')\n                || arg.contains('>')\n            {\n                anyhow::bail!(\"Blocked potentially dangerous git argument: {arg}\");\n            }\n            // Block `-c` config injection (exact match or `-c=...` prefix).\n            // This must not false-positive on `--cached` or `-cached`.\n            if arg_lower == \"-c\" || arg_lower.starts_with(\"-c=\") {\n                anyhow::bail!(\"Blocked potentially dangerous git argument: {arg}\");\n            }\n            result.push(arg.to_string());\n        }\n        Ok(result)\n    }\n\n    /// Check if an operation requires write access\n    fn requires_write_access(&self, operation: &str) -> bool {\n        matches!(\n            operation,\n            \"commit\" | \"add\" | \"checkout\" | \"stash\" | \"reset\" | \"revert\" | \"worktree\"\n        )\n    }","sourceCodeStart":24,"sourceCodeEnd":60,"githubUrl":"https://github.com/zeroclaw-labs/zeroclaw/blob/88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc/crates/zeroclaw-tools/src/git_operations.rs#L24-L60","documentation":"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.","triggerScenarios":"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().","commonSituations":"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.","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."],"exampleFix":"// before\ngit_checkout(args: \"checkout feature;rm -rf .cache\")\n// -> Blocked potentially dangerous git argument: feature;rm -rf .cache\n\n// after\ngit_checkout(args: \"checkout feature\")","handlingStrategy":"validation","validationCode":"// Mirror the tool's blocklist before sending args.\nfn is_safe_git_arg(arg: &str) -> bool {\n    let l = arg.to_lowercase();\n    !(l.starts_with(\"--exec=\") || l.starts_with(\"--upload-pack=\")\n        || l.starts_with(\"--receive-pack=\") || l.starts_with(\"--pager=\")\n        || l.starts_with(\"--editor=\") || l == \"--no-verify\"\n        || l.contains(\"$(\") || l.contains('`')\n        || arg.contains('|') || arg.contains(';') || arg.contains('>'))\n}\nfn validate_git_args(args: &str) -> Result<(), String> {\n    match args.split_whitespace().find(|a| !is_safe_git_arg(a)) {\n        Some(bad) => Err(format!(\"blocked by policy: {bad}\")),\n        None => Ok(()),\n    }\n}","typeGuard":"fn is_safe_git_arg(arg: &str) -> bool {\n    let l = arg.to_lowercase();\n    !(l.starts_with(\"--exec=\") || l.starts_with(\"--upload-pack=\")\n        || l.starts_with(\"--receive-pack=\") || l.starts_with(\"--pager=\")\n        || l.starts_with(\"--editor=\") || l == \"--no-verify\"\n        || l.contains(\"$(\") || l.contains('`')\n        || arg.contains('|') || arg.contains(';') || arg.contains('>'))\n}","tryCatchPattern":"match git_tool.execute(params).await {\n    Err(e) if e.to_string().contains(\"Blocked potentially dangerous git argument\") => {\n        // extract the blocked token, surface it to the caller/LLM, and\n        // re-issue the command without it; never retry the same string\n    }\n    r => r,\n}","preventionTips":["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"],"tags":["git","security","command-injection","arguments","sanitization"],"backgroundTag":"command-injection-guard","analyzedSha":"88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc","analyzedAt":"2026-08-23T01:07:41.857Z","schemaVersion":2},"datasetVersion":"2026-08-23T08:06:27.607Z"}