T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/_auth.py:20
- Finding
- Unvalidated API Base URL Can Exfiltrate Chanjing Credentials and Access Tokens<![CDATA[ ## Vulnerability Details **File Location**: `scripts/_auth.py:20-25, 93-101`; `scripts/_task_api.py:6, 21-45` **Vulnerability Type**: Unrestricted credential destination and insecure transport **Risk Level**: High ### Complete Code Snippet ```python # scripts/_auth.py:20-25 def openapi_base_url() -> str: return ( os.environ.get("CHANJING_OPENAPI_BASE_URL") or os.environ.get("CHANJING_API_BASE") or _DEFAULT_OPENAPI_BASE ).rstrip("/") ``` ```python # scripts/_auth.py:93-101 url = API_BASE + "/open/v1/access_token" req = urllib.request.Request( url, data=json.dumps({"app_id": app_id, "secret_key": secret_key}).encode("utf-8"), headers={"Content-Type": "application/json"}, method="POST", ) try: with urllib.request.urlopen(req, timeout=30) as resp: ``` ```python # scripts/_task_api.py:6 API_BASE = (__import__("os").environ.get("CHANJING_OPENAPI_BASE_URL") or __import__("os").environ.get("CHANJING_API_BASE") or "https://open-api.chanjing.cc").rstrip("/") ``` ```python # scripts/_task_api.py:21-45 def api_get(token, path, query=None): query = query or {} suffix = "" if query: suffix = "?" + urllib.parse.urlencode(query) req = urllib.request.Request( f"{API_BASE}{path}{suffix}", headers={"access_token": token}, method="GET", ) with urllib.request.urlopen(req, timeout=30) as resp: body = json.loads(resp.read().decode("utf-8")) if body.get("code") != 0: raise RuntimeError(body.get("msg", body)) return body.get("data") def api_post(token, path, payload): req = urllib.request.Request( f"{API_BASE}{path}", data=json.dumps(payload).encode("utf-8"), headers={"access_token": token, "Content-Type": "application/json"}, method="POST", ) with urllib.request.urlopen(req, timeout=30) as resp: ``` ### Technical Analysis The API base URL is taken directly from either `CHANJING_OPENAPI_BASE_URL ...[truncated 1936 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Parse the configured endpoint with `urllib.parse.urlparse`. 2. Require the `https` scheme and reject URLs containing user information, fragments, or unexpected ports. 3. Compare the normalized hostname against an explicit allowlist, preferably only `open-api.chanjing.cc` in production. 4. Apply identical validation to both current and legacy environment variables. 5. Disable endpoint overrides by default. If development overrides are necessary, require an explicit development mode and never load production credentials in that mode. 6. Validate the final destination after every redirect or disable redirects for credential-bearing requests. 7. Enforce the manifest network allowlist at runtime rather than treating it as documentation only. 8. Add tests proving that HTTP URLs, deceptive subdomains, user-information tricks, and redirects to unapproved hosts are rejected before any secret is transmitted. ]]>
