T09 · Insecure Skill Coding Practices
- Location
handler.py:22- Finding
LLM API Credential Can Be Sent to an Untrusted or Plaintext Endpoint
- Content
View full analysis
Vulnerability Details
File Location:
handler.py:22-52
Vulnerability Type: Unvalidated outbound endpoint and insecure transmission of credentials
Risk Level: Highpython def build_llm_client(): api_key = os.getenv("LLM_API_KEY") base_url = os.getenv("LLM_BASE_URL", "").rstrip("/") model = os.getenv("LLM_MODEL") if not api_key: raise RuntimeError("Please set LLM_API_KEY") if not base_url: raise RuntimeError("Please set LLM_BASE_URL") if not model: raise RuntimeError("Please set LLM_MODEL") return {"api_key": api_key, "base_url": base_url, "model": model}, model def llm_chat(client, model: str, prompt: str, max_tokens: int = 800) -> str: import requests as _req url = client["base_url"].rstrip("/") + "/chat/completions" payload = { "model": model, "messages": [{"role": "user", "content": prompt}], "temperature": 0.3, "max_tokens": max_tokens, } headers = { "Authorization": f"Bearer {client['api_key']}", "Content-Type": "application/json", } resp = _req.post(url, json=payload, headers=headers, timeout=60) resp.raise_for_status() return resp.json()["choices"][0]["message"]["content"].strip()Technical Analysis
The application accepts
LLM_BASE_URLdirectly from the runtime environment and uses it as the destination of an outbound HTTP request without validating its scheme or hostname. The request includesLLM_API_KEYin a bearer authorization header.If the configured URL uses plain HTTP, the credential and request body are transmitted without TLS protection. If an attacker or compromised deployment configuration can alter
LLM_BASE_URL, the request can be redirected to an attacker-controlled server. The request body also includes stock codes, prices, indicators, and prompts derived from the user's requested analysis.S ...[truncated 1751 chars]
- Remediation
View remediation
Remediation Suggestions
- Parse
LLM_BASE_URLwith a standard URL parser and require thehttpsscheme. - Maintain an administrator-controlled allowlist of approved LLM hostnames rather than accepting arbitrary destinations.
- Reject URLs containing embedded credentials, fragments, unexpected ports, or unsupported components.
- Unless explicitly required, reject loopback, link-local, private-network, and metadata-service addresses after DNS resolution.
- Revalidate the destination after redirects, or disable redirects entirely for this request.
- Use a dedicated, narrowly scoped API key with restrictive quotas and rotation support.
- Avoid logging authorization headers and redact credentials from all exception and diagnostic output.
- Document precisely which stock-derived data is transmitted to the LLM provider.
- Consider constructing the client from a trusted platform configuration rather than an environment variable that less-trusted launchers may modify.
- Parse
