T09 · Insecure Skill Coding Practices
- Location
scripts/run.py:12- Finding
Arbitrary Command Execution Through Shell Command Injection
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
This Git automation skill is broadly purpose-aligned, but its implementation can turn tool inputs into arbitrary shell commands and make repository changes without strong safeguards.
Do not install this version in an agent environment that may receive untrusted branch names, paths, tags, URLs, PR text, or other tool inputs. The skill should be revised to remove shell=True, pass subprocess arguments as arrays, validate refs and paths, constrain worktree destinations, and require explicit confirmation or dry-run previews for force-updates, subtree imports, and PR creation.
scripts/run.py:12Arbitrary Command Execution Through Shell Command Injection
scripts/run.py:73Workspace Boundary Bypass Through Unrestricted Worktree Path
The description is only partially accurate. The code does cover several declared Git workflow areas: worktree management, reflog recovery, subtree addition, and PR creation. However, there are material discrepancies. First, declared capabilities for submodule handling and cherry-pick across forks are absent. Second, the interactive rebase functionality does not actually execute an interactive rebase; it inspects commits and returns instructions plus an autosquash note, which is weaker than the declared 'advanced Git operations as tools' wording. Third, the code includes an additional capability—changelog generation—that is not mentioned in the description. These differences are substantive enough to count as a description-behavior mismatch.
This is a classic tool-parameter-abuse issue: attacker-controlled tool inputs are embedded into shell commands executed with shell=True. Because nearly every high-level function forwards JSON fields into these commands, a crafted parameter can break out of the intended Git/GitHub CLI invocation and execute arbitrary shell commands on the host.
def run(cmd, cwd=None):
"""Run a command and return (returncode, stdout, stderr)"""
result = subprocess.run(cmd, shell=True, capture_output=True, text=True, cwd=cwd)
return result.returncode, result.stdout, result.stderr
def git_rebase_interactive(base, autosquash=False):
Without declared permissions the skill's intent is opaque and cannot be validated.
The skill exposes high-risk Git operations such as reflog restore and subtree modification under danger_full_access while explicitly noting that extra confirmation for truly dangerous actions is 'not yet implemented.' In an agent setting, this can lead to unintended history rewrites, branch corruption, or repository state changes without a strong human confirmation boundary.
The helper uses subprocess.run(..., shell=True) and many callers interpolate untrusted JSON-derived parameters directly into shell command strings. This enables command injection across multiple tools such as branch names, paths, tags, repo URLs, PR title/body, and commit hashes, allowing arbitrary OS command execution in the agent environment.
def run(cmd, cwd=None):
"""Run a command and return (returncode, stdout, stderr)"""
result = subprocess.run(cmd, shell=True, capture_output=True, text=True, cwd=cwd)
return result.returncode, result.stdout, result.stderr
def git_rebase_interactive(base, autosquash=False):
git branch -f force-moves the target branch to a supplied commit without any confirmation or safety check. In an agentic context, this can silently rewrite branch state, discard expected history references, and facilitate destructive repository tampering or recovery-point manipulation.
This function performs network fetches and working-tree modifications by adding a remote, fetching, and adding a subtree, yet provides no warning or confirmation. In agent use, this can import untrusted code or unexpectedly alter repository contents, which is more dangerous because the skill is designed to make repository-changing operations easy to trigger.
Most of the manifest describes advanced Git repository operations such as rebase, worktree management, reflog recovery, and subtree/submodule handling. Creating a PR through gh invokes a hosted GitHub workflow and performs remote side effects beyond core git operations, which is a distinct capability unless explicitly and clearly in scope.
PR creation sends branch metadata and user-provided content to GitHub and creates a remote artifact without any explicit consent gate. In an automation setting, this can leak repository context externally or trigger unintended publication/actions, especially when combined with command injection elsewhere in the file.
The manifest describes advanced Git workflows centered on rebase, worktrees, reflog recovery, subtree/submodule handling, cherry-pick across forks, and PR automation. This file adds a git_changelog_generate capability that is not mentioned, while there is no implementation of submodule handling or cherry-pick across forks, indicating the delivered behavior does not match the stated skill scope.
Adding an external repository as a subtree causes both network access and local repository modification, but the documentation does not provide concrete warnings, trust guidance, or approval requirements. In practice, this can import untrusted code or unexpectedly alter the repository state, which is more sensitive in an autonomous agent workflow.
The manifest specifically frames PR automation as being based on human-written intent, suggesting constrained assistance around user-authored PR content. The implementation simply accepts title and body strings and issues gh pr create, with no logic enforcing or reflecting that claimed intent-oriented behavior.