T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/utils/validator.js:3
- Finding
- Unrestricted URL Fetching Enables SSRF and Internal Data Exfiltration<![CDATA[ ## Vulnerability Details **File Location**: `scripts/utils/validator.js:3-9`; related request and redirect handling in `scripts/video2text/index.js:101-109` and `scripts/utils/download.js:317-332, 464-494` **Vulnerability Type**: Server-Side Request Forgery through unrestricted URL downloading **Risk Level**: High ### Vulnerable Code ```js function isUrl(url) { try { const parsedUrl = new URL(url); return parsedUrl.protocol === "http:" || parsedUrl.protocol === "https:"; } catch (_) { return false; } } ``` The accepted URL is subsequently downloaded: ```js if (validator.isUrl(file)) { const filepath = utils.downloadPath(); // ... const downloadResult = await helper.download(file, filepath); } ``` The downloader also follows redirects, including cross-host redirects: ```js const redirectedURL = /^https?:\/\//.test(response.headers.location) ? response.headers.location : new URL(response.headers.location, url).href; this.emit("redirected", redirectedURL, url); return getRequest(redirectedURL, getReqOptions(redirectedURL)); ``` ### Technical Analysis URL validation checks only whether the scheme is HTTP or HTTPS. It does not reject: - Loopback addresses such as `127.0.0.1` and `::1` - Private network ranges - Link-local addresses - Cloud metadata services - Internal DNS names - Hostnames that resolve to prohibited addresses - Public URLs that redirect to internal resources Redirect targets are followed without repeating a network-boundary validation check. DNS resolution is also not pinned, leaving the implementation potentially exposed to DNS rebinding. After the response is downloaded, the entry point treats it as a video file and uploads it to remote object storage. This creates an exfiltration path rather than merely allowing blind SSRF. ### Attack Path 1. An attacker causes the Skill to receive an internal URL as the `--file` argument, or supplies a public URL that redirects to an internal endpoint. 2. `isUrl( ...[truncated 973 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Resolve the hostname before connecting and reject all loopback, private, link-local, multicast, unspecified, and reserved IP ranges for both IPv4 and IPv6. 2. Explicitly block cloud metadata destinations, including common link-local metadata addresses. 3. Repeat the full validation process after every redirect. 4. Restrict redirects to HTTPS and, where practical, to the same registrable domain. 5. Mitigate DNS rebinding by connecting only to the validated resolved address and verifying resolution throughout the request lifecycle. 6. Permit only expected media hosts or require explicit user approval for arbitrary hosts. 7. Validate response `Content-Type`, file signatures, and maximum size before upload. 8. Avoid automatically uploading downloaded content until it has passed media validation. ]]>
