T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/export_git_commits.sh:32
- Finding
- Arbitrary Command Execution Through Git Log Argument Injection<![CDATA[ ## Vulnerability Details **File Location**: `scripts/export_git_commits.sh`, lines 32–45, 68, 92, 119, and 154 **Vulnerability Type**: Shell command injection through `eval` **Risk Level**: High ### Vulnerable Code ```bash # Build git log command arguments GIT_LOG_ARGS="--pretty=format:'%H|%an|%ae|%ad|%s' --date=iso" if [ -n "$AUTHOR" ]; then GIT_LOG_ARGS="$GIT_LOG_ARGS --author=\"$AUTHOR\"" fi if [ -n "$START_DATE" ]; then GIT_LOG_ARGS="$GIT_LOG_ARGS --since=\"$START_DATE\"" fi if [ -n "$END_DATE" ]; then GIT_LOG_ARGS="$GIT_LOG_ARGS --until=\"$END_DATE\"" fi ``` The constructed command string is subsequently executed through `eval` in multiple locations: ```bash eval git log $GIT_LOG_ARGS ``` It is also used when calculating statistics: ```bash total_commits=$(eval git log $GIT_LOG_ARGS --oneline | wc -l) ``` ### Technical Analysis `AUTHOR`, `START_DATE`, and `END_DATE` are caller-controlled positional arguments. The script embeds them into a shell command string and then passes that string to `eval`. Quoting the values while constructing the string does not make this safe. `eval` causes the shell to parse the resulting text a second time. Embedded quotation marks, command substitutions, shell separators, or redirection operators can therefore terminate the intended Git argument and introduce additional commands. Every supported output branch invokes the affected command, so the vulnerability is reachable when exporting Markdown, CSV, or JSON. The final statistics command also invokes the same injection sink. ### Attack Path 1. An attacker supplies a crafted author or date argument, for example an author containing: ```text "; touch /tmp/git_skill_pwned; # ``` 2. The script concatenates the value into `GIT_LOG_ARGS`. 3. An affected branch executes: ```bash eval git log $GIT_LOG_ARGS ``` 4. `eval` reparses the injected quotation mark and semicolon as shell syntax. 5. The injected command executes independent ...[truncated 761 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions Remove every use of `eval` and construct arguments with a Bash array: ```bash git_log_args=( "--pretty=format:%H|%an|%ae|%ad|%s" "--date=iso" ) if [[ -n "$AUTHOR" ]]; then git_log_args+=(--author="$AUTHOR") fi if [[ -n "$START_DATE" ]]; then git_log_args+=(--since="$START_DATE") fi if [[ -n "$END_DATE" ]]; then git_log_args+=(--until="$END_DATE") fi git log "${git_log_args[@]}" total_commits=$(git log "${git_log_args[@]}" --oneline | wc -l) ``` Apply the same array-based invocation to the Markdown, CSV, JSON, and statistics branches. Each user value must remain one argument and must never be reparsed as shell source. Consider validating date inputs as an additional defense-in-depth measure. ]]>
