T09 · Insecure Skill Coding Practices
- Location
smalltalk.py:626- Finding
Unrestricted OpenAI-compatible endpoint can expose API credentials and source code
- Content
View full analysis
str: """Query OpenAI-compatible chat completions API.""" import urllib.request import urllib.error base_url = os.environ.get("OPENAI_API_BASE", "https://api.openai.com/v1") model = os.environ.get("OPENAI_MODEL", "gpt-4o") messages = [] if system: messages.append({"role": "system", "content": system}) messages.append({"role": "user", "content": prompt}) body = json.dumps({ "model": model, "messages": messages, "temperature": 0.3, "max_tokens": 2048, }).encode() req = urllib.request.Request( f"{base_url}/chat/completions", data=body, headers={ "Authorization": f"Bearer {api_key}", "Content-Type": "application/json", }, ) try: with urllib.request.urlopen(req, timeout=30) as resp: data = json.loads(resp.read()) return data["choices"][0]["message"]["content"] except urllib.error.HTTPError as e: return f"Error: LLM API returned {e.code}: {e.read().decode()[:200]}" except Exception as e: return f"Error: LLM query failed: {e}" ``` ### Technical Analysis The `OPENAI_API_BASE` environment variable is accepted without validating its scheme, hostname, port, or trust level. The resulting URL receives both: 1. The value of `OPENAI_API_KEY` in the `Authorization` header. 2. The complete LLM prompt, which can contain Smalltalk source code obtained from the live image, an arbitrary `--source-file`, standard input, or inline source. The Skill documentation describes OpenAI as an LLM provider but does not document `OPENAI_API_BASE` or clearly warn that a custom endpoint receives the API credential ...[truncated 1999 chars]- Remediation
View remediation
