T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/run.py:87
- Finding
- Configurable API Endpoint Can Expose the Bearer Credential and Sensitive Medical Data<![CDATA[ ## Vulnerability Details **File Location**: `scripts/run.py:87-102`, `scripts/run.py:233`, and `scripts/run.py:278-286` **Vulnerability Type**: Unrestricted credential-bearing network destination **Risk Level**: High ### Vulnerable Code ```python def call_llm( *, api_url: str, model: str, appkey: str, system_prompt: str, user_prompt: str, temperature: float, timeout: int, ) -> str: payload = { "model": model, "temperature": temperature, "messages": [ {"role": "system", "content": system_prompt}, {"role": "user", "content": user_prompt}, ], } try: req = Request( api_url, data=json.dumps(payload, ensure_ascii=False).encode("utf-8"), headers={ "Content-Type": "application/json", "Authorization": f"Bearer {appkey}", }, ) resp = urlopen(req, timeout=timeout) ``` The destination is directly configurable through a command-line argument: ```python p.add_argument("--api-url", default=DEFAULT_API_URL, help="OpenAI 兼容接口地址") ``` The caller-supplied destination and credential are then passed to the request function: ```python out["answer"] = call_llm( api_url=args.api_url, model=args.model, appkey=args.appkey, system_prompt=args.system_prompt, user_prompt=user_prompt, temperature=float(args.temperature), timeout=int(args.timeout), ) ``` ### Technical Analysis The `--api-url` argument accepts an unrestricted URL. `call_llm()` sends both the bearer credential and the complete user prompt to that destination without validating the URL scheme or hostname. There is no enforcement that the destination: - Uses HTTPS. - Matches the documented internal medical-model hostname. - Belongs to an approved endpoint allowlist. - Remains on the approved origin after an HTTP redirect. Consequently, anyone able to influence the command-line ar ...[truncated 2204 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Remove `--api-url` from production-facing invocations if endpoint customization is unnecessary. 2. Enforce an allowlist containing the exact approved HTTPS origin, including the expected hostname and port. 3. Reject every non-HTTPS URL before constructing the request. 4. Normalize and parse URLs with `urllib.parse.urlsplit()` before validation; do not rely on string-prefix checks. 5. Reject URLs containing unexpected user-information, ports, schemes, or hostnames. 6. Disable redirects or validate every redirect target before forwarding the request. Never forward the `Authorization` header across origins. 7. Separate endpoint selection from untrusted command-line input by using an administrator-controlled configuration. 8. Use short-lived, narrowly scoped credentials and rotate any key suspected of having been transmitted to an unauthorized endpoint. 9. Add automated tests confirming rejection of HTTP URLs, unapproved domains, deceptive subdomains, embedded credentials, alternate ports, and cross-origin redirects. 10. Continue requiring upstream de-identification, and consider adding local validation or warnings for common personal identifiers before transmitting prompts. ]]>
