T09 · Insecure Skill Coding Practices
- Location
scripts/check.sh:163- Finding
Remote GitHub release tags can reach unsafe Bash arithmetic evaluation
- Content
View full analysis
/dev/null) ``` ```bash # Get latest release info latest_tag=$(echo "$releases_json" | jq -r '.[0].tag_name // empty') release_url=$(echo "$releases_json" | jq -r '.[0].html_url // empty') if [[ -z "$latest_tag" ]]; then exit 0 fi latest_version="${latest_tag#v}" ``` ```bash # Compare versions (semver-style: major.minor.patch) version_gt() { # Returns 0 (true) if $1 > $2 local IFS='.' read -ra v1 <<< "$1" read -ra v2 <<< "$2" for i in 0 1 2; do local n1=${v1[i]:-0} local n2=${v2[i]:-0} if (( n1 > n2 )); then return 0; fi if (( n1 < n2 )); then return 1; fi done return 1 # Equal } ``` ```bash if version_gt "$current_version" "$latest_version"; then exit 0 fi ``` ### Technical Analysis The script downloads release metadata from the GitHub API and treats the first release's `tag_name` as a semantic version. The resulting value is split into components and assigned to `n2`, but the components are not validated as decimal integers before they are used in Bash arithmetic expressions. Bash arithmetic evaluation does not treat variable contents as inert strings. Values can be recursively interpreted as arithmetic expressions, including constructs such as array subscripts that may contain command substitutions. Consequently, specially crafted release metadata may cause shell commands embedded in an arithmetic expression to execute when the following statements are evaluated: ```bash (( n1 > n2 )) (( n1 < n2 )) ``` Although exploitation requires control over or compromise of release metadata returned for the configured repository, this is a meaningful trust-boundary violation because ...[truncated 1362 chars]- Remediation
View remediation
&2 exit 1 fi ``` 2. Apply equivalent validation to `current_version`, even though it originates locally. 3. Do not place untrusted strings directly or indirectly into Bash arithmetic expressions. 4. Convert validated components to canonical base-10 integers before comparison, accounting for leading-zero behavior. 5. Prefer a dedicated semantic-version comparison implementation that treats version input strictly as data. 6. Fail closed when the GitHub response has an unexpected schema or invalid tag instead of silently continuing. 7. Add tests using malformed tags, arithmetic operators, array syntax, command-substitution-like input, prerelease tags, and unusually long values. ]]>
