T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/lib/api_client.py:121
- Finding
- API Credential Can Be Transmitted to an Arbitrary Configurable Origin<![CDATA[ ## Vulnerability Details **File Location**: `scripts/lib/api_client.py:121-164`; `setup.py:138-145`; `setup.py:179` **Vulnerability Type**: Unvalidated credential destination and possible cleartext credential transmission **Risk Level**: High ### Vulnerable Code `scripts/lib/api_client.py:121-164`: ```python self.base_url = base_url or os.getenv("CODEALIVE_BASE_URL", "https://app.codealive.ai") self.timeout = 60 def _make_request( self, method: str, endpoint: str, params: Optional[Dict[str, Any]] = None, body: Optional[Dict[str, Any]] = None ) -> Dict[str, Any]: """ Make an HTTP request to the CodeAlive API. Args: method: HTTP method (GET, POST, etc.) endpoint: API endpoint path params: URL query parameters body: Request body for POST requests Returns: Parsed JSON response """ url = f"{self.base_url}{endpoint}" # Add query parameters if params: query_string = urllib.parse.urlencode(params, doseq=True) url = f"{url}?{query_string}" # Prepare request headers = { "Authorization": f"Bearer {self.api_key}", "Content-Type": "application/json" } data = None if body: data = json.dumps(body).encode("utf-8") request = urllib.request.Request(url, data=data, headers=headers, method=method) # Make request try: with urllib.request.urlopen(request, timeout=self.timeout) as response: ``` `setup.py:138-145` and `setup.py:179`: ```python def verify_key(api_key: str, base_url: str = DEFAULT_BASE_URL) -> tuple[bool, str]: """Test the API key by fetching data sources. Returns (success, message).""" url = f"{base_url}/api/datasources/alive" headers = { "Authorization": f"Bearer {api_key}", "Content-Type": "application/json", } req = urllib.request.Request(url, headers=headers, method="GET") try: with urllib.request.urlopen(req, timeout=15) as re ...[truncated 2603 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Parse the base URL with `urllib.parse.urlparse` before using it. 2. Require the `https` scheme and reject cleartext HTTP. 3. Pin the default credential to `app.codealive.ai`. 4. If private instances must be supported, require an explicit trusted-host allowlist or an interactive confirmation that clearly identifies the destination. 5. Reject URLs containing user information, fragments, unexpected ports, malformed hosts, or unsupported schemes. 6. Associate stored credentials with a specific API origin rather than using one generic credential-store entry for every configured host. 7. Refuse to forward the `Authorization` header across redirects to a different origin. Prefer disabling automatic cross-origin redirects for authenticated requests. 8. Avoid revealing full custom URLs in errors if they may contain sensitive components. 9. Add tests covering HTTP URLs, attacker-controlled hosts, cross-origin redirects, malformed URLs, and default-host operation. A safe validation pattern should resemble: ```python from urllib.parse import urlparse parsed = urlparse(self.base_url) if parsed.scheme != "https": raise ValueError("CODEALIVE_BASE_URL must use HTTPS") trusted_hosts = {"app.codealive.ai"} if parsed.hostname not in trusted_hosts: raise ValueError("Untrusted CodeAlive API host") ``` For supported private instances, the trusted hostname should come from a separately protected configuration and the credential should be scoped to that hostname. ]]>
