T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/emr_qc_impl.py:58
- Finding
- Unrestricted LLM Endpoint Can Exfiltrate API Credentials and Medical Records<![CDATA[ ## Vulnerability Details **File Location**: `scripts/emr_qc_impl.py:58-65` **Additional Locations**: `scripts/emr_qc.py:27-30`, `scripts/run.py:54-57` **Vulnerability Type**: Unrestricted destination for sensitive outbound requests **Risk Level**: High ### Vulnerable Code ```python def make_llm_caller(appkey: str, base: str = DEFAULT_LLM_BASE, model: str = DEFAULT_LLM_MODEL, timeout: int = 0): """Return an llm(messages) → str calling function.""" url = f"{base.rstrip('/')}/chat/completions" headers = {"Authorization": f"Bearer {appkey}"} def llm(messages: List[Dict[str, str]]) -> str: payload = {"model": model, "messages": messages, "temperature": 0} resp = _http_post(url, payload, headers, timeout=timeout) ``` The endpoint is exposed through an unrestricted command-line argument: ```python parser.add_argument( "--base", default=DEFAULT_LLM_BASE, help=f"LLM base URL (default: {DEFAULT_LLM_BASE}).", ) ``` ### Technical Analysis The `--base` parameter accepts an arbitrary URL. The application appends `/chat/completions` and sends both of the following to that destination: - The application key in the `Authorization: Bearer` header. - EMR-derived content in the request payload. No destination hostname allowlist is applied. The implementation also does not explicitly reject plaintext HTTP URLs, embedded URL credentials, loopback destinations, private network addresses, or redirects to untrusted destinations. Although custom endpoint support may be intentional, using the same sensitive application credential for every caller-selected destination crosses a security boundary. Any party capable of influencing the command-line invocation or wrapper configuration can redirect credentials and medical data to infrastructure under its control. ### Attack Path 1. An attacker gains influence over the Skill invocation, a wrapper script, job configuration, or copied command. 2. The attacker supplies a destination ...[truncated 1214 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Allowlist the exact approved API hostname and scheme. 2. Reject non-HTTPS URLs, embedded credentials, fragments, and unexpected ports. 3. Resolve and reject loopback, link-local, and private network destinations unless explicitly required. 4. Disable automatic cross-origin redirects or validate the destination again after every redirect. 5. Do not transmit the production application key to a caller-selected endpoint. 6. If custom providers are required, use separately supplied credentials scoped to each provider. 7. Require an explicit high-visibility confirmation before transmitting medical data to a non-default service. 8. Log only the approved destination hostname; never log authorization headers or medical payloads. 9. Add tests confirming that malformed URLs, HTTP URLs, unapproved hosts, and redirect-based bypasses are rejected. ]]>
