T09 · Insecure Skill Coding Practices
- Location
run.sh:54- Finding
Unvalidated API Base URL Exposes Credentials and Enables Media Exfiltration
- Content
View full analysis
Vulnerability Details
File Location:
run.sh:54,run.sh:156-185,run.sh:247-256
Vulnerability Type: Unvalidated external endpoint configuration and sensitive-data exposure
Risk Level: HighVulnerable Code
sh : "${JOGG_BASE_URL:=https://api.jogg.ai}"sh if [ -n "$payload" ]; then if [ -n "${JOGG_API_PLATFORM:-}" ]; then RESPONSE_STATUS=$(curl -sS -o "$body_file" -w "%{http_code}" -X "$method" "$url" \ -H "X-Api-Key: ${JOGG_API_KEY}" \ -H "x-api-platform: ${JOGG_API_PLATFORM}" \ -H "Content-Type: application/json" \ -d "$payload") || { rm -f "$body_file" json_error "request failed" exit 1 } else RESPONSE_STATUS=$(curl -sS -o "$body_file" -w "%{http_code}" -X "$method" "$url" \ -H "X-Api-Key: ${JOGG_API_KEY}" \ -H "Content-Type: application/json" \ -d "$payload") || { rm -f "$body_file" json_error "request failed" exit 1 } fi else if [ -n "${JOGG_API_PLATFORM:-}" ]; then RESPONSE_STATUS=$(curl -sS -o "$body_file" -w "%{http_code}" -X "$method" "$url" \ -H "X-Api-Key: ${JOGG_API_KEY}" \ -H "x-api-platform: ${JOGG_API_PLATFORM}") || { rm -f "$body_file" json_error "request failed" exit 1 } else RESPONSE_STATUS=$(curl -sS -o "$body_file" -w "%{http_code}" -X "$method" "$url" \ -H "X-Api-Key: ${JOGG_API_KEY}") || { rm -f "$body_file" json_error "request failed" exit 1 } fi fish api_request "POST" "${JOGG_BASE_URL%/}/v2/upload/asset" "$payload" api_success_data sign_url=$(printf '%s' "$LAST_JSON" | jq -r '.sign_url') asset_url=$(printf '%s' "$LAST_JSON" | jq -r '.asset_url') upload_status_file=$(mktemp) run_with_heartbeat "uploading binary to storage" \ sh -c ' curl -sS -o /dev/null -w "%{http_code}" -X PUT "$1" -H "Content-Type: $2" --data-binary "@$3" > "$4" ' sh "$sign_url" "$content_type" "$media_input" "$upload_status_file" || {...[truncated 2247 chars]
- Remediation
View remediation
Remediation Suggestions
- Remove the production
JOGG_BASE_URLoverride and use a constant trusted endpoint where custom endpoints are not explicitly required. - If configurability is necessary, parse and validate the URL before any request:
- Require the
httpsscheme. - Require an exact allowlisted hostname such as
api.jogg.ai. - Reject embedded credentials, unexpected ports, malformed hosts, and non-HTTPS URLs.
- Require the
- Validate every returned
sign_urlbefore uploading:- Require HTTPS.
- Permit only documented Jogg storage domains or an authoritative allowlist.
- Reject loopback, link-local, private-network, and unapproved external destinations.
- Configure
curlto fail securely, such as with--fail-with-body, and use explicit connection and total timeouts. - Do not forward authentication headers across redirects. Either reject redirects or constrain them to approved HTTPS hosts.
- Treat the Skill-local
.envas sensitive configuration:- Require restrictive filesystem permissions.
- Ensure it is not writable by untrusted users.
- Document that environment overrides can affect credential destinations.
- Consider separating authenticated API communication from media upload logic so that the API key can only ever be sent to a fixed, trusted origin.
- Remove the production
