T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/00_probe_env.sh:16
- Finding
- Arbitrary Python Code Injection Through Untrusted HTTP Geolocation Data<![CDATA[ ## Vulnerability Details **File Location**: `scripts/00_probe_env.sh`, lines 16-20 and 34-51 **Vulnerability Type**: Untrusted data interpolation into executable Python source **Risk Level**: High ### Vulnerable Code ```bash # Local public IP MY_IP=$(curl -s --max-time 5 https://api.ipify.org 2>/dev/null || \ curl -s --max-time 5 http://ip-api.com/json 2>/dev/null | python3 -c "import json,sys; d=json.load(sys.stdin); print(d.get('query',''))" 2>/dev/null) # Public IP attribution IP_INFO=$(curl -s --max-time 5 "http://ip-api.com/json/${MY_IP}" 2>/dev/null) ``` ```bash COUNTRY=$(echo "$IP_INFO" | python3 -c "import json,sys; d=json.load(sys.stdin); print(d.get('country','unknown'))" 2>/dev/null) CITY=$(echo "$IP_INFO" | python3 -c "import json,sys; d=json.load(sys.stdin); print(d.get('city','unknown'))" 2>/dev/null) ISP=$(echo "$IP_INFO" | python3 -c "import json,sys; d=json.load(sys.stdin); print(d.get('isp','unknown'))" 2>/dev/null) AS=$(echo "$IP_INFO" | python3 -c "import json,sys; d=json.load(sys.stdin); print(d.get('as','unknown'))" 2>/dev/null) python3 -c " import json data = { 'my_ip': '$MY_IP', 'country': '$COUNTRY', 'city': '$CITY', 'isp': '$ISP', 'as': '$AS', 'default_dns': '$DEFAULT_DNS'.strip(','), 'tools': { 'dig': '$DIG_OK' == 'true', 'traceroute': '$TRACEROUTE_OK' == 'true', 'ping': '$PING_OK' == 'true', 'whois': '$WHOIS_OK' == 'true' } } print(json.dumps(data, ensure_ascii=False, indent=2)) " | tee "$ENV_FILE" ``` ### Technical Analysis The script retrieves IP attribution data from `ip-api.com` over unencrypted HTTP. Values such as country, city, ISP, and autonomous-system information are then inserted directly into a string passed to `python3 -c`. Shell quoting does not make these values safe inside the generated Python program. An attacker able to alter the HTTP response can include quotes, commas, and Python expressions in a JSON string. After extraction, that string becomes executable ...[truncated 1746 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Use HTTPS for every external API request and fail closed if transport security cannot be established. 2. Do not interpolate network-derived or command-derived values into Python source code. 3. Pass the complete JSON response to a fixed Python program through standard input and construct the output object entirely within that program. 4. If shell-to-Python transfer is unavoidable, use environment variables or command-line arguments and treat them strictly as data. 5. Enable strict shell behavior such as `set -euo pipefail`, validate API response status, and reject malformed or unexpectedly large responses. 6. A safe design would resemble: ```bash curl --fail --silent --show-error --max-time 5 \ "https://ip-api.com/json/${MY_IP}" | python3 -c ' import json import sys source = json.load(sys.stdin) data = { "country": source.get("country", "unknown"), "city": source.get("city", "unknown"), "isp": source.get("isp", "unknown"), "as": source.get("as", "unknown"), } json.dump(data, sys.stdout, ensure_ascii=False, indent=2) ' ``` 7. Ensure the selected API actually supports authenticated HTTPS on the intended plan; otherwise replace it with a provider that does. ]]>
