T09 · Insecure Skill Coding Practices
- Location
scripts/create_and_wait.py:63- Finding
Arbitrary SSE Endpoint Allows Disclosure of the skills.video API Key and Generation Payload
- 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", ) ``` ```python with request.urlopen(req, timeout=request_timeout) as resp: ``` ```python parser.add_argument("--sse-endpoint", required=True, help="SSE create endpoint path or full URL") parser.add_argument("--base-url", default="https://open.skills.video/api/v1") ``` ```python api_key = os.environ.get("SKILLS_VIDEO_API_KEY", "").strip() ``` ```python payload = load_payload(args) url = endpoint_url(args.base_url, args.sse_endpoint) emit({"event": "start", "url": url, "mode": "sse_then_poll_fallback"}) sse_rc, generation_id, terminal_payload = run_sse( url=url, api_key=api_key, payload=payload, request_timeout=args.sse_request_timeout, ) ``` ### Technical Analysis The helper expressly accepts either an endpoint path or a complete HTTP/HTTPS URL. When a complete URL is supplied, `endpoint_url()` returns it without validating the destination hostname or requiring encrypted transport. The resulting request automatically includes the `SKILLS_VIDEO_API_KEY` as a bearer credential and sends t ...[truncated 1920 chars]- Remediation
View remediation
str: if endpoint.startswith(("http://", "https://")): raise ValueError("Absolute endpoint URLs are not allowed") url = urljoin(base_url.rstrip("/") + "/", endpoint.lstrip("/")) parsed = urlsplit(url) if parsed.scheme != "https" or parsed.hostname not in TRUSTED_HOSTS: raise ValueError("Untrusted API destination") if parsed.username or parsed.password: raise ValueError("URL credentials are not allowed") return url ``` ]]>
