T09 · Insecure Skill Coding Practices
- Location
scripts/lookup.sh:58- Finding
Arbitrary Python Code Execution Through an Unsafely Interpolated Address
- Content
View full analysis
Vulnerability Details
File Location:
scripts/lookup.sh:58-61
Vulnerability Type: Command injection through dynamically generated Python source code
Risk Level: Highbash if [[ -n "$ADDRESS" ]]; then ENCODED=$(python3 -c "import urllib.parse; print(urllib.parse.quote('$ADDRESS'))") curl -s "${BASE_URL}/request/${VERSION}?address=${ENCODED}" \ -H "X-API-KEY: ${ZIPTAX_API_KEY}" | python3 -m json.toolTechnical Analysis
The value of
ADDRESSis controlled by the--addresscommand-line argument and is interpolated directly into the source code passed topython3 -c. Shell quoting prevents ordinary shell word splitting, but it does not make the resulting Python program safe.An address containing a single quote and valid Python syntax can terminate the intended string literal and append arbitrary Python statements. The Python interpreter then executes those statements with the same operating-system identity, environment variables, filesystem permissions, and network access as the script.
This behavior is not necessary for URL encoding. User data should be passed to Python through an argument or standard input, never embedded into executable source code.
Attack Path
- An attacker influences the address supplied to the Skill or persuades a user or agent to perform a lookup using a crafted address.
- The attacker supplies Python syntax that closes the quoted address and adds a statement, for example:
text ')); __import__("os").system("id"); # - The shell expands the crafted value inside the
python3 -cargument. - Python parses the injected text as executable source code.
- The injected operating-system command runs before the ZipTax request is made.
The payload could replace
idwith commands that read accessible files, inspect environment variables, make outbound requests, or modify resources writable by the current account.Impact Assessment
...[truncated 568 chars]
- Remediation
View remediation
Remediation Suggestions
Pass the address as a data argument rather than inserting it into Python source:
bash ENCODED=$( python3 -c 'import sys, urllib.parse; print(urllib.parse.quote(sys.argv[1]))' \ "$ADDRESS" )Alternatively, use a URL-aware HTTP client that accepts query parameters separately. Apply strict argument-count checks before reading
$2, validate lookup inputs according to their expected formats, and add regression tests containing quotes, semicolons, newlines, command substitutions, and Python syntax. The tests should verify that such input is encoded as data and never executed.
