T09 · Insecure Skill Coding Practices
- Location
scripts/botsee.py:19- Finding
Unrestricted API Base URL Override Can Exfiltrate Stored Credentials
- Content
View full analysis
Vulnerability Details
File Location:
scripts/botsee.py, lines 19 and 99-121
Vulnerability Type: Attacker-controlled network destination for authenticated requests
Risk Level: MediumVulnerable Code
python # API Configuration BASE_URL = os.environ.get("BOTSEE_BASE_URL", "https://botsee.io")python def api_call(method, endpoint, data=None, api_key=None, timeout=30, params=None, extra_headers=None): """Make an API call to BotSee. Returns (response_dict, http_status).""" url = f"{BASE_URL}/api/v1{endpoint}" if params: query = urllib.parse.urlencode(params) url = f"{url}?{query}" headers = {"Content-Type": "application/json"} if api_key: headers["Authorization"] = f"Bearer {api_key}" if extra_headers: headers.update(extra_headers) body = json.dumps(data).encode() if data else None req = urllib.request.Request(url, data=body, headers=headers, method=method) # Create SSL context with certificate validation ssl_context = ssl.create_default_context() ssl_context.check_hostname = True ssl_context.verify_mode = ssl.CERT_REQUIRED try: with urllib.request.urlopen(req, timeout=timeout, context=ssl_context) as resp:Technical Analysis
The destination of every API request is controlled by the
BOTSEE_BASE_URLenvironment variable without validation of its scheme, hostname, port, or origin. Authenticated operations subsequently add the API key loaded from~/.botsee/config.jsonto the request as anAuthorization: Bearerheader.Consequently, a process environment controlled by an attacker can redirect authenticated requests to an arbitrary server. The override also accepts an
http://URL. Although the code creates a certificate-validating SSL context, that context does not provide transport security when the selected URL uses plaintext HTTP.The same generic request fu ...[truncated 2408 chars]
- Remediation
View remediation
Remediation Suggestions
-
Remove the production override where possible. Use a fixed, trusted API origin for released Skill packages:
python BASE_URL = "https://botsee.io" -
If development overrides are required, enforce an explicit allowlist. Parse and validate the URL before any request:
python from urllib.parse import urlparse ALLOWED_API_ORIGINS = { "https://botsee.io", "https://staging.botsee.io", } candidate = os.environ.get("BOTSEE_BASE_URL", "https://botsee.io").rstrip("/") parsed = urlparse(candidate) if parsed.scheme != "https" or candidate not in ALLOWED_API_ORIGINS: raise RuntimeError("BOTSEE_BASE_URL is not an approved HTTPS API origin") BASE_URL = candidate -
Never send secrets based solely on a configurable URL. Before attaching
Authorization, payment-signature, or other sensitive headers, verify that the final parsed request origin exactly matches an approved origin. -
Reject plaintext HTTP. Require HTTPS for every non-loopback endpoint. If local development must support HTTP, require an explicit development mode and prevent real API keys or payment proofs from being used in that mode.
-
Prevent cross-origin redirect leakage. Disable automatic redirects for authenticated requests or validate every redirect target before forwarding authorization and payment headers.
-
Separate authenticated and unauthenticated clients. Use dedicated request functions or policies for signup calls, authenticated API operations, and payment-proof submission so each sends only the minimum required headers.
-
Document the override as security-sensitive. Clearly warn users that changing the API origin can disclose credentials and should only be used with trusted local or staging services.
-
Add automated security tests. Confirm that HTTP URLs, unapproved domains, crafted ports, user-info URLs, and red ...[truncated 80 chars]
-
