T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/surgery_review.py:255
- Finding
- Caller-Controlled LLM Endpoint Can Receive Medical Records and Bearer Credentials<![CDATA[ ## Vulnerability Details **File Location**: `scripts/surgery_review.py:255-276`, `scripts/surgery_review.py:451-465`, and `scripts/surgery_review.py:873-879`; endpoint exposed through `scripts/run.py:153,183` **Vulnerability Type**: Unrestricted transmission of sensitive information and credentials to a caller-controlled network endpoint **Risk Level**: High ### Vulnerable Code The LLM client sends the prompt and bearer credential to the configured model URL: ```python 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) ``` Selected medical-document contents are embedded directly in that prompt: ```python evidence_text = "\n\n".join( ( f"【文书#{doc['doc_index']} / {doc['doc_type']} / {doc['file_name']}】\n" f"{doc['content']}" ) ...[truncated 3157 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Remove caller-controlled model endpoint overrides in production and use a fixed, trusted service URL. 2. If endpoint configurability is operationally required, enforce: - HTTPS only. - An exact allowlist of approved hostnames and ports. - Proper URL parsing rather than prefix or substring checks. - Rejection of embedded credentials, fragments, nonstandard schemes, loopback addresses, link-local addresses, and unapproved private-network destinations. 3. Disable automatic cross-origin redirects or validate every redirect destination against the same allowlist before forwarding credentials or request content. 4. Bind each credential to its approved destination. Never attach the internal model credential to an arbitrary caller-supplied URL. 5. Minimize medical evidence before transmission. Send only the necessary excerpts and remove patient identifiers where possible. 6. Require an explicit data-transfer opt-in instead of enabling LLM transmission by default when handling medical records. 7. Reject an empty `appkey` when LLM use is enabled and avoid exposing credentials in logs or exception output. 8. Add tests proving that HTTP URLs, unapproved domains, alternate ports, redirect-based bypasses, and malformed URLs are rejected. ]]>
