T09 · Insecure Skill Coding Practices
- Location
scripts/run.py:200- Finding
Unrestricted LLM Endpoint Can Receive Medical Records and Bearer Credentials
- Content
View full analysis
str: url = f"{base.rstrip('/')}/chat/completions" headers = {"Authorization": f"Bearer {appkey}"} if appkey else {} payload = { "model": model, "messages": [{"role": "user", "content": prompt}], "temperature": 0, } response = _http_post(url, payload, headers, timeout=timeout) ``` The destination is supplied through an unrestricted command-line option: ```python parser.add_argument("--base", default=DEFAULT_LLM_BASE, help=f"Internal LLM base URL (default: {DEFAULT_LLM_BASE}).") ``` ### Technical Analysis The `--base` argument controls the destination of the LLM request without any scheme or host validation. `call_llm()` then sends both the complete medical-record prompt and the operator-provided API key to that destination. The implementation does not: - Require HTTPS. - Restrict the hostname to the intended medical-model service. - Prevent credentials from being sent to a custom endpoint. - Reject loopback, link-local, or private-network destinations. - Verify the final host following HTTP redirects. Consequently, a malicious or mistakenly configured endpoint can collect the bearer credential and all clinical information included in the prompt. Allowing local or private-network URLs also gives the script an SSRF-like network access capability, although response handling and the fixed POST path limit how that capability can be used. ### Attack Path 1. An attacker convinces an operator, automation wrapper, or deployment configuration to invoke the skill with a malicious base URL, for example: ```bash python scripts/run.py \ --input patient-record.json \ ...[truncated 1301 chars]- Remediation
View remediation
