T09 · Insecure Skill Coding Practices
- Location
scripts/_classifier_client.py:20- Finding
Unrestricted remote endpoints can receive sensitive conversations and bearer credentials
- Content
View full analysis
str: normalized = (base_url or "").rstrip("/") if normalized.endswith("/chat/completions"): return normalized return f"{normalized}/chat/completions" ``` ```python if not api_key: raise ClassifierAPIError("missing classifier api key") total_attempts = max(1, int(max_retries) + 1) for attempt in range(total_attempts): try: response = requests.post( _chat_url(base_url), headers={ "Authorization": f"Bearer {api_key}", "Content-Type": "application/json", }, json={ "model": model, "messages": messages, "temperature": temperature, "response_format": {"type": "json_object"}, }, timeout=timeout_sec, ) ``` The related embedding path has the same endpoint-control issue: ```python if not self.api_key: raise RuntimeError("missing embedding api key") if not self.base_url: raise RuntimeError("missing embedding base url") url = f"{self.base_url}/embeddings" headers = { "Authorization": f"Bearer {self.api_key}", "Content-Type": "application/json", } payload = { "model": self.embedding_model, "input": text, } with httpx.Client(timeout=30.0) as client: response = client.post(url, headers=headers, json=payload) ``` ### Technical Analysis The classifier and embedding clients accept arbitrary base URLs from environment configuration. They do not enforce HTTPS, restrict destinations to approved hosts, reject loopback or link-local targets, or otherwise validate the destination before transmi ...[truncated 2169 chars]- Remediation
View remediation
