T09 · Insecure Skill Coding Practices
- Location
scripts/run.py:26- Finding
Authentication Credentials Can Be Sent to an Arbitrary API Endpoint
- Content
View full analysis
Vulnerability Details
File Location:
scripts/run.py:26-39andscripts/run.py:75-81
Vulnerability Type: Unvalidated destination for authenticated outbound requests
Risk Level: MediumVulnerable Code
python def build_base_url(): return os.getenv("AISKILLS_BASE_URL", DEFAULT_BASE_URL).rstrip("/") def build_headers(): api_key = os.getenv("AISKILLS_API_KEY", "").strip() tenant_id = os.getenv("AISKILLS_TENANT_ID", "default").strip() or "default" if not api_key: fail("AISKILLS_API_KEY is required") return { "Content-Type": "application/json", # Cloudflare blocks urllib's default Python user agent for this endpoint. "User-Agent": "ai-skills-runner/1.0 (+https://ai-skills.ai)", "Accept": "application/json", "X-API-Key": api_key, "X-Tenant-Id": tenant_id, }python def request_json(method, path, payload): body = json.dumps(payload).encode("utf-8") req = urllib.request.Request( f"{build_base_url()}{path}", data=body, method=method, headers=build_headers(), )Technical Analysis
The request destination is derived directly from the
AISKILLS_BASE_URLenvironment variable without validating its scheme, hostname, port, or trust relationship. The same request is automatically populated with theX-API-KeyandX-Tenant-Idauthentication headers.Consequently, a deployment mistake or an attacker capable of influencing the process environment can redirect authenticated requests to an arbitrary server. The implementation also accepts an
http://URL, allowing the credentials and request data to be transmitted without transport encryption.TLS certificate verification is enabled for HTTPS requests, but it does not address this issue because an attacker-controlled HTTPS server can possess a valid certificate for its own hostname.
Attac
...[truncated 1654 chars]
- Remediation
View remediation
Remediation Suggestions
- Require the base URL to use HTTPS and reject all other schemes.
- Parse the URL with
urllib.parse.urlsplit()and reject embedded credentials, fragments, unexpected ports, malformed hostnames, and ambiguous URL forms. - Maintain an explicit allowlist of trusted API hostnames, preferably allowing only
ai-skills.aiin production. - Validate the final request destination before adding
X-API-KeyorX-Tenant-Id. - Do not forward authentication headers across redirects to a different origin. Consider disabling redirects or implementing a redirect handler that enforces same-origin redirects.
- If custom endpoints are a legitimate requirement, require an explicit opt-in setting and use separately scoped credentials that cannot authenticate to the production service.
- Document that
AISKILLS_BASE_URLis security-sensitive and must not be populated from untrusted user input. - Add tests confirming rejection of plaintext HTTP, unapproved hosts, embedded credentials, unexpected ports, and cross-origin redirects.
