T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/diagnosis_sufficiency_review.py:481
- Finding
- Attacker-Controlled LLM Endpoint Can Receive Medical Records and Bearer Credentials<![CDATA[ ## Vulnerability Details **File Location**: `scripts/diagnosis_sufficiency_review.py:481-510, 720-727`; `scripts/run.py:160, 184` **Vulnerability Type**: Unrestricted outbound destination, credential disclosure, and server-side request forgery **Risk Level**: High ### Vulnerable Code ```python class HardcodedLlmClient: def __init__(self, llm_settings: LlmSettings) -> None: self._settings = llm_settings def complete(self, prompt: str, model_name: str | None = None) -> str: selected_model = model_name or self._settings.default_model model_config = self._settings.models.get(selected_model) if model_config is None: raise ValueError(f"未找到模型配置: {selected_model}") payload = { "model": model_config.model_id or selected_model, "messages": [{"role": "user", "content": prompt}], "temperature": model_config.temperature, } if model_config.type == "openai_compatible": return self._post_chat( url=f"{model_config.base_url.rstrip('/')}/chat/completions", payload=payload, headers={"Authorization": f"Bearer {model_config.api_key}"}, ) raise ValueError(f"不支持的模型类型: {model_config.type}") def _post_chat(self, url: str, payload: dict[str, Any], headers: dict[str, str]) -> str: body = json.dumps(payload, ensure_ascii=False).encode("utf-8") req = request.Request( url=url, data=body, headers={"Content-Type": "application/json", **{key: value for key, value in headers.items() if value}}, method="POST", ) opener = request.urlopen(req) if not self._settings.timeout else request.urlopen(req, timeout=self._settings.timeout) ``` The endpoint is populated directly from the request payload: ```python llm_client = _load_llm_client( use_llm, str(payload.get("appkey") or "").strip(), str(payload.get(" ...[truncated 2798 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Remove the caller-controlled `base` option in production and use a deployment-controlled endpoint. 2. If endpoint configurability is required, enforce an exact allowlist of approved HTTPS origins. 3. Parse and validate the URL before use: - Require the `https` scheme. - Reject embedded credentials and unexpected ports. - Reject loopback, private, link-local, multicast, and reserved addresses after DNS resolution. - Revalidate resolved addresses when connecting to mitigate DNS rebinding. 4. Disable redirects or validate every redirect destination against the same allowlist. 5. Bind credentials to a specific configured origin and never attach an LLM credential to an arbitrary URL. 6. Use narrowly scoped, short-lived credentials and rotate any credential that may have been sent to an untrusted destination. 7. Add tests proving that HTTP, localhost, private-network, metadata-service, and unapproved public endpoints are rejected. ]]>
