T09 · Insecure Skill Coding Practices
- Location
scripts/create_and_wait.py:62- Finding
Bearer API Key Disclosure Through an Unrestricted SSE Endpoint
- Content
View full analysis
str: if endpoint.startswith("http://") or endpoint.startswith("https://"): return endpoint if not endpoint.startswith("/"): endpoint = "/" + endpoint return f"{base_url.rstrip('/')}{endpoint}" ``` ```python def run_sse( url: str, api_key: str, payload: dict[str, Any], request_timeout: float, ) -> tuple[int, str | None, Any]: req = request.Request( url, headers={ "Authorization": f"Bearer {api_key}", "Accept": "text/event-stream", "Content-Type": "application/json", }, data=json.dumps(payload).encode("utf-8"), method="POST", ) ``` The request is subsequently sent using: ```python with request.urlopen(req, timeout=request_timeout) as resp: ``` ### Technical Analysis The `--sse-endpoint` argument accepts either a relative endpoint or an unrestricted absolute URL. If an absolute `http://` or `https://` URL is supplied, `endpoint_url()` returns it without verifying the scheme, hostname, port, or relationship to the documented `open.skills.video` service. `run_sse()` then unconditionally attaches the value of `SKILLS_VIDEO_API_KEY` as a bearer token and sends the complete generation payload to that URL. This violates the least-privilege requirement because the declared functionality only requires disclosing the credential to the skills.video API. Acceptance of plain HTTP additionally permits the API key and potentially sensitive prompts or media references to be transmitted without transport encryption. ### Attack Path 1. An attacker influences the arguments used to invoke `create_and_wait.py`, such as through an untrusted generated command, copied instruc ...[truncated 1114 chars]- Remediation
View remediation
