T09 · Insecure Skill Coding Practices
Error
- Location
- references/code-examples/bria_client.py:115
- Finding
- API Credential Forwarded to an Unvalidated Polling URL<![CDATA[ ## Vulnerability Details **File Location**: `references/code-examples/bria_client.py:115-129` **Additional Locations**: `SKILL.md:214-216`, `references/api-endpoints.md:544-547`, `references/workflows.md:22-25`, `references/workflows.md:115-119`, `references/code-examples/bria_client.ts:182-207`, `references/code-examples/bria_client.sh:124-144` **Vulnerability Type**: Credential disclosure through an untrusted network destination **Risk Level**: High ### Vulnerable Code ```python def _request(self, endpoint: str, data: Dict, wait: bool = True) -> Dict[str, Any]: """Make API request with optional polling.""" url = f"{self.BASE_URL}{endpoint}" response = requests.post(url, json=data, headers=self._headers()) response.raise_for_status() result = response.json() if wait and "status_url" in result: return self._poll(result["status_url"]) return result def _poll(self, status_url: str, timeout: int = 120) -> Dict[str, Any]: """Poll status URL until completion.""" for _ in range(timeout // 2): response = requests.get(status_url, headers=self._headers()) ``` The same pattern is present in the TypeScript workflow: ```typescript const { status_url } = (await res.json()) as BriaResponse; // Poll for result for (let i = 0; i < 60; i++) { const statusRes = await fetch(status_url, { headers: { "api_token": apiKey, "User-Agent": "BriaSkills/1.2.5" } }); ``` ### Technical Analysis The initial request is sent to the expected Bria API host, but the absolute `status_url` returned in the response is trusted without validation. The polling request attaches the Bria API key through the `api_token` header regardless of the polling URL's scheme, hostname, port, or path. Authentication on a legitimate Bria status endpoint is necessary for the declared image-generation functionality. Forwarding that credential to any URL supplied by a response exceeds the minimum privilege needed. Authentica ...[truncated 1272 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Parse `status_url` before sending any request. 2. Require the `https` scheme. 3. Require an exact approved hostname, such as `engine.prod.bria-api.com`. 4. Reject unexpected ports, embedded credentials, fragments, and non-status paths. 5. Prefer returning a request ID and constructing the status URL locally: ```python from urllib.parse import urlparse ALLOWED_HOST = "engine.prod.bria-api.com" def validate_status_url(status_url: str) -> str: parsed = urlparse(status_url) if parsed.scheme != "https": raise ValueError("Polling URL must use HTTPS") if parsed.hostname != ALLOWED_HOST: raise ValueError("Untrusted polling host") if parsed.port not in (None, 443): raise ValueError("Unexpected polling port") if not parsed.path.startswith("/v2/status/"): raise ValueError("Unexpected polling path") return status_url ``` 6. Disable automatic redirects for authenticated polling requests, or validate every redirect destination before resending credentials. 7. Never forward `api_token` across origins. 8. Apply equivalent validation in the Python, TypeScript, shell, and workflow examples so users do not reproduce the insecure pattern. ]]>
