T09 · Insecure Skill Coding Practices
- Location
scripts/init-improvement-run.sh:151- Finding
Artifact-Controlled Git Pathspec Can Broaden Rollback Scope
- Content
View full analysis
Vulnerability Details
File Location:
scripts/init-improvement-run.sh, lines 151-175
Vulnerability Type: Unvalidated Git pathspec in destructive rollback operation
Risk Level: MediumVulnerable Code
bash if [[ -n "$SCOPE" ]]; then TARGETS+=("$SCOPE") elif [[ -f "$RUN_DIR/proposal.md" ]]; then while IFS= read -r line; do # accept "- path" or "* path" bullets file="${line#- }" file="${file#\* }" file="$(trim "$file")" [[ -n "$file" ]] && TARGETS+=("$file") done < <(awk ' /^## Files To Edit/ { in_section=1; next } /^## / && in_section { exit } in_section && /^[-*] / { print } ' "$RUN_DIR/proposal.md") fi if [[ ${#TARGETS[@]} -eq 0 ]]; then echo "Refusing rollback: no scope provided and proposal.md has no '## Files To Edit' bullets." >&2 echo "Pass --scope <path> or fill proposal.md before rolling back." >&2 exit 1 fi echo "Rollback targets:" for t in "${TARGETS[@]}"; do echo " - $t"; done if [[ "$IS_GIT_REPO" == "true" ]]; then (cd "$REPO_ABS" && git checkout -- "${TARGETS[@]}")Technical Analysis
Rollback targets are read from the mutable
## Files To Editsection ofproposal.mdand passed directly togit checkout. Shell quoting and the--separator prevent shell injection and Git option injection, but they do not make the arguments literal paths.Git continues to interpret each argument as a pathspec. Consequently, broad targets such as
.or Git pathspec magic can match substantially more tracked content than a normal file entry. The implementation does not:- Reject Git pathspec magic.
- Require targets to identify regular files.
- Reject broad directory targets such as
.. - Normalize and verify repository-relative paths.
- Compare rollback targets against a previously approved immutable manifest.
- Force Git to use literal pathspec semantics.
This violates the documented strict-roll ...[truncated 1556 chars]
- Remediation
View remediation
Remediation Suggestions
-
Force literal Git path handling. Invoke Git with literal pathspec behavior:
bash GIT_LITERAL_PATHSPECS=1 git checkout -- "${TARGETS[@]}" -
Normalize each target. Require a clean repository-relative path and reject:
- Absolute paths.
- Empty paths.
.and...- Paths containing traversal components.
- Git pathspec magic, including values beginning with
:(. - Directory-only or wildcard targets.
-
Resolve and enforce repository containment. Canonicalize the parent path and verify that it remains beneath
REPO_ABS. -
Require file-level targets. Check each target against tracked files before rollback, for example with literal-path Git queries. Reject entries that expand to zero or multiple files.
-
Use an immutable approved manifest. At approval time, store the exact normalized file list in a dedicated machine-readable artifact and bind it to the approved proposal with a digest. Rollback should consume that manifest rather than reparsing mutable Markdown.
-
Add a destructive-operation confirmation. Display the fully resolved file list and require explicit confirmation before checkout, with a separate noninteractive flag for controlled CI use.
-
Preserve recoverability. Before rollback, create a patch or stash of affected worktree changes so unintended data loss can be recovered.
-
Add security tests. Verify that
.,.., absolute paths, directories, wildcard expressions, and Git pathspec magic are rejected while valid repository-relative literal filenames are accepted.
-
