T09 · Insecure Skill Coding Practices
- Location
tools/git-stats.sh:52- Finding
Git Statistics Tool Unexpectedly Modifies the Target Repository
- Content
View full analysis
Vulnerability Details
File Location:
tools/git-stats.sh, lines 52-57
Vulnerability Type: Repository state modification and unsafe argument handling
Risk Level: Mediumbash # 检查分支是否存在 if ! git show-ref --verify --quiet refs/heads/$BRANCH; then echo "错误: 分支不存在: $BRANCH" echo "可用分支:" git branch -a exit 1 fi # 切换到指定分支 git checkout $BRANCH > /dev/null 2>&1Technical Analysis
The tool is documented as a statistics utility, but it executes
git checkoutand therefore modifies the current branch, index, and potentially the working-tree state of the repository being analyzed. Reading Git history does not require a checkout, so this violates the principle of least modification.The attacker-controlled or caller-controlled
BRANCHvariable is also expanded without quotes and without an option terminator. Although this does not directly provide shell command execution, shell word splitting and pathname expansion can alter the arguments passed to Git. A specially constructed option-like ref can also be interpreted as a Git option rather than strictly as a branch name.The preceding
show-refoperation does not make the later checkout option-safe. It verifies a ref assembled underrefs/heads/, while the subsequent command passes the original branch string directly to Git's command-line parser.Attack Path
- An attacker or untrusted repository maintainer creates a specially named ref, including an option-like name where the Git implementation permits such a ref to exist.
- The user runs
git-stats.shagainst that repository and supplies the corresponding value as the third argument. - The script verifies the assembled ref but then passes the original value unquoted to
git checkout. - Git may interpret the value through option parsing rather than exclusively as a branch name.
- Even during ordinary use, the script switches the repository away from the developer's ...[truncated 773 chars]
- Remediation
View remediation
Remediation Suggestions
Remove the checkout operation entirely. All statistics commands should query a fully qualified, validated ref without modifying repository state.
- Validate the supplied branch name with
git check-ref-format --branch. - Reject branch values beginning with
-. - Resolve the branch to a full ref or commit identifier before using it.
- Quote every variable expansion.
- Use
--as an option terminator where the relevant Git command supports it. - Run commands with
git -C "$REPO_PATH"instead of changing the process working directory. - Add tests covering whitespace, wildcard characters, option-like values, missing branches, dirty working trees, and repositories whose active branch differs from the requested reporting branch.
A safer design is:
bash if ! git check-ref-format --branch "$BRANCH" > /dev/null 2>&1; then printf 'Invalid branch name: %s\n' "$BRANCH" >&2 exit 1 fi case "$BRANCH" in -*) printf 'Option-like branch names are not accepted\n' >&2; exit 1 ;; esac REF="refs/heads/$BRANCH" if ! git -C "$REPO_PATH" show-ref --verify --quiet "$REF"; then printf 'Branch does not exist: %s\n' "$BRANCH" >&2 exit 1 fi git -C "$REPO_PATH" rev-list --count --since="$SINCE_DATE 00:00:00" "$REF"Apply the same quoted
$REFvalue to all subsequentgit log,git diff, andgit rev-listoperations.- Validate the supplied branch name with
