T09 · Insecure Skill Coding Practices
- Location
scripts/scan.sh:7- Finding
API Key Disclosure Through an Unrestricted Service Host Override
- Content
View full analysis
Vulnerability Details
File Location:
scripts/cities.sh:6-11,scripts/forecast.sh:7-22, andscripts/scan.sh:7-13
Vulnerability Type: User-controlled request destination combined with credential forwarding
Risk Level: MediumVulnerable Code
scripts/cities.sh:6-11bash HOST="${POLYMARKET_SCANNER_HOST:-https://polymarket-scanner.fly.dev}" API_KEY="${POLYMARKET_SCANNER_API_KEY:-}" RESPONSE=$(curl -s -w "\n%{http_code}" \ ${API_KEY:+-H "X-API-Key: ${API_KEY}"} \ "${HOST}/cities")scripts/forecast.sh:7-22bash HOST="${POLYMARKET_SCANNER_HOST:-https://polymarket-scanner.fly.dev}" API_KEY="${POLYMARKET_SCANNER_API_KEY:-}" CITY="${1:?Usage: forecast.sh <city> [YYYY-MM-DD]}" # Sanitize city input: only allow alphanumeric, spaces, hyphens CITY=$(echo "$CITY" | tr '[:upper:]' '[:lower:]' | sed 's/[^a-z0-9 -]//g' | sed 's/ /%20/g') DATE="${2:-}" URL="${HOST}/forecast/${CITY}" if [ -n "$DATE" ]; then URL="${URL}?target_date=${DATE}" fi RESPONSE=$(curl -s -w "\n%{http_code}" \ ${API_KEY:+-H "X-API-Key: ${API_KEY}"} \ "$URL")scripts/scan.sh:7-13bash HOST="${POLYMARKET_SCANNER_HOST:-https://polymarket-scanner.fly.dev}" API_KEY="${POLYMARKET_SCANNER_API_KEY:-}" DAYS="${1:-1}" RESPONSE=$(curl -s -w "\n%{http_code}" \ ${API_KEY:+-H "X-API-Key: ${API_KEY}"} \ "${HOST}/scan/weather?days_ahead=${DAYS}")Technical Analysis
The three scripts allow the
POLYMARKET_SCANNER_HOSTenvironment variable to replace the trusted API origin without validating its scheme, hostname, or port. They then attach the value ofPOLYMARKET_SCANNER_API_KEYas anX-API-Keyheader to requests sent to that destination.This creates a credential-forwarding vulnerability across a mutable trust boundary. An attacker who can influence the environment in which the skill runs can redirect requests from the intended `https://polymarket- ...[truncated 1874 chars]
- Remediation
View remediation
Remediation Suggestions
-
Remove the production host override and use a fixed trusted origin:
bash readonly HOST="https://polymarket-scanner.fly.dev" -
If an override is required for development, enforce an explicit allowlist before attaching credentials:
bash HOST="${POLYMARKET_SCANNER_HOST:-https://polymarket-scanner.fly.dev}" case "$HOST" in "https://polymarket-scanner.fly.dev") ;; *) echo "Error: untrusted scanner host" >&2 exit 1 ;; esac -
Never forward production credentials to arbitrary development hosts. If non-production endpoints must be supported, require a separate development credential and suppress the production API-key header.
-
Build curl arguments with a Bash array so every option and value remains a single, well-defined argument:
bash curl_args=( --silent --show-error --fail-with-body --write-out $'\n%{http_code}' ) if [[ -n "$API_KEY" ]]; then curl_args+=(-H "X-API-Key: $API_KEY") fi RESPONSE=$(curl "${curl_args[@]}" "${HOST}/scan/weather?days_ahead=${DAYS}") -
Require HTTPS and validate the normalized hostname rather than relying on a prefix or substring check. Reject URLs containing embedded credentials, unexpected ports, redirects to untrusted hosts, or unsupported schemes.
-
Consider disabling redirects or restricting them because curl may otherwise reach an unintended destination. Use an explicit redirect policy and ensure sensitive headers are never forwarded across origins.
-
Rotate any API key that may previously have been used while
POLYMARKET_SCANNER_HOSTpointed to an untrusted endpoint.
-
