T09 · Insecure Skill Coding Practices
- Location
scripts/question_bank.py:16- Finding
Environment-Controlled API Base URL Can Exfiltrate Credentials
- Content
View full analysis
Vulnerability Details
File Location:
scripts/question_bank.py:16-18,scripts/question_bank.py:55-77,scripts/question_bank.py:145-151,scripts/question_bank.py:171-181
Vulnerability Type: Unvalidated credential destination
Risk Level: HighVulnerable Code
python BASE_URL = os.getenv( "QUESTION_SERVICE_URL", "https://tizhuang.qcscience.cc/api" ).rstrip("/")python def _http_json( path: str, params: dict | None = None, *, headers: dict[str, str] | None = None, method: str = "GET", json_body: dict | None = None, ): query = urllib.parse.urlencode( {key: value for key, value in (params or {}).items() if value is not None}, doseq=True, ) url = f"{BASE_URL}{path}" + (f"?{query}" if query else "") request_headers = dict(headers or {}) body = None if json_body is not None: body = json.dumps(json_body, ensure_ascii=False).encode("utf-8") request_headers["Content-Type"] = "application/json" api_request = urllib.request.Request( url, data=body, headers=request_headers, method=method ) try: with urllib.request.urlopen(api_request, timeout=30) as response: return json.load(response)python license_key = os.getenv("QUESTION_SERVICE_LICENSE") if license_key: return _http_json( registered_path, params, headers={"X-API-Key": license_key}, method=method, json_body=json_body, )python token = os.getenv("QUESTION_SERVICE_ACCOUNT_TOKEN") if not token: raise SystemExit( "This command needs a signed-in website account. Open the account URL " "from the onboarding command, then configure QUESTION_SERVICE_ACCOUNT_TOKEN " "locally. Never paste the token into chat." ) return _http_json( path, headers={"Authorization ...[truncated 2401 chars]- Remediation
View remediation
Remediation Suggestions
- Allow credentials to be sent only to the declared production origin, such as
https://tizhuang.qcscience.cc/api. - Parse the configured URL and reject:
- Schemes other than HTTPS.
- User-information components.
- Unexpected hostnames or ports.
- Malformed or ambiguous hostnames.
- If custom service endpoints are required for development, place them behind an explicit development-only option and maintain an administrator-controlled hostname allowlist.
- Do not forward production API keys or account bearer tokens to development or custom origins.
- Bind each credential to its expected origin and fail closed if the request destination differs.
- Consider separating public, trial, licensed, and account clients so that account credentials cannot accidentally be attached to unrelated destinations.
- Add automated tests confirming that HTTP URLs, unapproved hosts, URL user information, and unexpected ports are rejected before any request is sent.
- Allow credentials to be sent only to the declared production origin, such as
