T09 · Insecure Skill Coding Practices
- Location
post-merge-rename.sh:88- Finding
Remote Branch Deletion Proceeds Despite Failed Preservation Operations
- Content
View full analysis
Vulnerability Details
File Location:
post-merge-rename.sh, lines 88-95
Vulnerability Type: Unchecked failures before destructive Git operation
Risk Level: Mediumbash else echo " Renaming: $trimmed -> $new_name" # Rename local git branch -m "$trimmed" "$new_name" 2>/dev/null || true # Push new name to remote git push origin "$new_name" 2>/dev/null || true # Remove old name from remote git push origin --delete "$trimmed" 2>/dev/null || true fiTechnical Analysis
The script suppresses errors from the local branch rename and the push of the replacement branch by appending
|| true. It then unconditionally attempts to delete the original branch fromorigin.Consequently, failure to rename the local branch or publish the replacement remote reference does not stop the destructive deletion step. Although
set -euo pipefailis enabled, the explicit|| trueexpressions negate its failure-handling protection. Redirecting standard error to/dev/nullalso prevents the user from seeing why preservation failed.This behavior contradicts the claim in
README.mdline 10 and the script comments that branches are never deleted.SKILL.mddoes disclose deletion of the old remote branch, but the inconsistent documentation may cause operators to underestimate the operation's destructive nature.Attack Path
- A merged local branch is selected for processing.
- The local rename or push of the dated replacement fails, for example because of a name collision, permissions, a remote policy, or an inconsistent repository state.
- The failure is suppressed with
2>/dev/null || true. - The script continues to
git push origin --delete "$trimmed". - If the caller has deletion permission, the original remote branch reference is removed without confirmation that an equivalent replacement was successfully published.
An attacker who can influence repository state or remote ...[truncated 564 chars]
- Remediation
View remediation
Remediation Suggestions
Remove
|| truefrom the local rename and replacement push, and do not discard their diagnostics. Permit deletion only after all preservation steps have succeeded.Before deleting the old remote branch:
- Record the original branch commit with
git rev-parse. - Rename the local branch and require success.
- Push the replacement branch using an explicit refspec.
- Query the new remote reference and verify that it resolves to the expected commit.
- Delete the old remote reference only after successful verification.
- Exit with a nonzero status and retain the old branch whenever any step fails.
- Consider requiring explicit confirmation or a separate flag for remote deletion.
- Update all documentation to clearly state that the old remote branch name is deleted after successful preservation.
Example control flow:
bash original_commit=$(git rev-parse "$trimmed") || exit 1 git branch -m "$trimmed" "$new_name" || exit 1 git push origin "refs/heads/$new_name:refs/heads/$new_name" || exit 1 remote_commit=$(git ls-remote --heads origin "refs/heads/$new_name" | awk '{print $1}') if [[ "$remote_commit" != "$original_commit" ]]; then echo "Error: replacement remote branch was not verified." >&2 exit 1 fi git push origin --delete "$trimmed" || exit 1- Record the original branch commit with
