T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/utils/validator.js:3
- Finding
- Unrestricted URL Fetching Enables Server-Side Request Forgery and Internal Data Disclosure<![CDATA[ ## Vulnerability Details **File Location**: `scripts/utils/validator.js:3-8`; `scripts/utils/download.js:479-492, 911-922`; `scripts/video2text/index.js:96-124` **Vulnerability Type**: Server-Side Request Forgery (SSRF) with subsequent data upload **Risk Level**: High ### Vulnerable Code ```js // scripts/utils/validator.js:3-8 function isUrl(url) { try { const parsedUrl = new URL(url); return parsedUrl.protocol === "http:" || parsedUrl.protocol === "https:"; } catch (_) { return false; } } ``` ```js // scripts/utils/download.js:479-492 if (this.__isRequireRedirect(response)) { this.__redirectCount++; if (this.__redirectCount > this.__opts.maxRedirects) { const err = new Error("Too many redirects"); this.__setState(this.__states.FAILED); this.emit("error", err); return reject(err); } const redirectedURL = /^https?:\/\//.test(response.headers.location) ? response.headers.location : new URL(response.headers.location, this.url).href; this.__isRedirected = true; this.__initProtocol(redirectedURL); this.emit("redirected", redirectedURL, this.url); return this.__start(); } ``` ```js // scripts/utils/download.js:911-922 __getReqOptions(method, url, headers = {}) { const urlParse = new URL(url); const options = { protocol: urlParse.protocol, host: urlParse.hostname, port: urlParse.port, path: urlParse.pathname + urlParse.search, method, }; if (urlParse.username || urlParse.password) { options.auth = `${urlParse.username}:${urlParse.password}`; } ``` ```js // scripts/video2text/index.js:96-106 if (validator.isUrl(file)) { const filepath = utils.downloadPath(); try { await fs.promises.mkdir(filepath, { recursive: true }); } catch (error) { utils.printError("临时下载目录创建失败: " + (error.message || String(error))); process.exit(1); } try { const downloadResult = await helper.download(file, filepath); ``` ### Technical Analysis URL validation c ...[truncated 2074 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Resolve the destination hostname before connecting and reject all non-public IPv4 and IPv6 ranges, including: - Loopback ranges. - RFC1918 private networks. - Link-local and cloud metadata ranges. - Unique-local IPv6 addresses. - Multicast, unspecified, and reserved ranges. 2. Repeat DNS resolution and address validation for every redirect. 3. Prevent DNS rebinding by connecting only to the validated address while preserving the expected TLS server name. 4. Apply an allowlist of supported video-hosting domains where operationally possible. 5. Reduce the maximum redirect count and reject protocol downgrades from HTTPS to HTTP. 6. Disable URL user information unless explicitly required. 7. Separate downloading from uploading and require confirmation before an HTTP response from an unusual destination is sent to the cloud service. 8. Add automated tests for direct and redirected requests to loopback, private IPv4, IPv6 local, and metadata addresses. ]]>
