T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/xiangongyun_api.py:41
- Finding
- Unvalidated API Endpoint Can Receive Bearer Tokens and Deployment Credentials<![CDATA[ ## Vulnerability Details **File Location**: `scripts/xiangongyun_api.py:41`, `scripts/xiangongyun_api.py:46-51`, `scripts/xiangongyun_api.py:64-77`, `scripts/xiangongyun_api.py:138-141`; `config/config.yaml:4-7` **Vulnerability Type**: Unvalidated credential transmission destination **Risk Level**: High ### Vulnerable Code ```python # scripts/xiangongyun_api.py:41 BASE_URL = config.get("api", {}).get( "base_url", "https://api.xiangongyun.com" ) ``` ```python # scripts/xiangongyun_api.py:46-51 def __init__(self): self.api_key = self._get_api_key() self.headers = { "Authorization": "Bearer " + self.api_key, "Content-Type": "application/json" } ``` ```python # scripts/xiangongyun_api.py:64-77 def _request( self, method: str, endpoint: str, params: Optional[Dict] = None, data: Optional[Dict] = None ) -> Dict[str, Any]: """发送 HTTP 请求""" url = f"{BASE_URL}{endpoint}" try: if method.upper() == "GET": response = requests.get( url, headers=self.headers, params=params, timeout=30 ) elif method.upper() == "POST": response = requests.post( url, headers=self.headers, json=data, timeout=30 ) ``` ```python # scripts/xiangongyun_api.py:138-141 if password: data["password"] = password return self._request("POST", "/open/instance/deploy", data=data) ``` ```yaml # config/config.yaml:4-7 api: base_url: "https://api.xiangongyun.com" # Replace the access_token below with the Xiangongyun API access token. access_token: "YOUR_ACCESS_TOKEN_HERE" ``` ### Technical Analysis The API destination is read directly from a mutable configuration file without validating its scheme, hostname, port, or origin. The same request logic attaches the bearer token to every request. Deployment requests can also carry a p ...[truncated 2239 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Pin production requests to `https://api.xiangongyun.com` rather than accepting an unrestricted configuration value. 2. If custom endpoints are required, parse the URL with `urllib.parse.urlparse` and enforce: - The `https` scheme. - An explicit hostname allowlist. - Approved ports only. - No embedded username or password. - No unexpected path prefix, query, or fragment. 3. Disable redirects for authenticated calls with `allow_redirects=False`, or validate every redirect destination before forwarding credentials. 4. Separate production and development configurations. Require an explicit development flag before permitting non-production endpoints, and never reuse production tokens in development. 5. Protect configuration ownership and permissions so that untrusted users cannot change the destination. 6. Use a narrowly scoped API token where the service supports scoped credentials, separating read-only, resource-management, destructive, and financial permissions. 7. Add automated tests confirming that HTTP URLs, lookalike domains, URL user-info components, and unapproved ports are rejected. ]]>
