T09 · Insecure Skill Coding Practices
- Location
scripts/audit_repo.py:384- Finding
Shell Command Injection Through Attacker-Controlled Git Branch Names
- Content
View full analysis
Vulnerability Details
File Location:
scripts/audit_repo.py, lines 384–395
Vulnerability Type: Shell command injection in generated cleanup script
Risk Level: HighVulnerable Code
python if branch_findings.get("merged"): lines.append("# === Delete merged branches ===") for b in branch_findings["merged"]: lines.append(f'echo "Deleting merged branch: {b["name"]}"') lines.append(f'git branch {delete_flag} "{b["name"]}"') lines.append("") if branch_findings.get("stale"): lines.append("# === Delete stale branches (review carefully!) ===") for b in branch_findings["stale"]: lines.append(f'# Stale {b["days_old"]} days, last: {b["last_subject"][:50]}') if force_delete: lines.append(f'git branch -D "{b["name"]}"') else: lines.append(f'# git branch -D "{b["name"]}" # Uncomment after review')Technical Analysis
Branch names are read from the repository and interpolated directly into shell commands. The generated commands enclose branch names in double quotes, but double quotes do not disable shell command substitution through constructs such as
$()or backticks.Consequently, a branch name containing shell metacharacters accepted by Git can introduce executable shell expressions into the generated cleanup script. The expressions are evaluated when the user executes that script. The vulnerable values are used both in an
echocommand and in branch-deletion commands.Although
--fixprints rather than automatically executes the cleanup script, the documented workflow explicitly directs users to save, review, and execute it. This creates a direct path from untrusted repository metadata to local command execution.Attack Path
- An attacker creates or supplies a Git repository containing a maliciously named stale or merged branch.
- The victim runs the audit tool against that repository with ...[truncated 902 chars]
- Remediation
View remediation
Remediation Suggestions
- Apply robust shell escaping to every repository-derived value using
shlex.quote(). - Insert the Git end-of-options marker before branch names, for example:
git branch -d -- "$branch". - Validate branch names and reject values containing unsafe or unexpected shell syntax.
- Prefer generating a structured data file and using a trusted Python cleanup program that invokes Git through
subprocess.run()with an argument list andshell=False. - If shell output must be generated, assign safely quoted values to variables and never interpolate raw repository metadata into executable shell source.
- Add automated tests using branch names containing
$(), backticks, dollar signs, parentheses, and other shell-significant characters. - Clearly warn users that cleanup output generated from an untrusted repository must not be executed without validation.
- Apply robust shell escaping to every repository-derived value using
