T09 · Insecure Skill Coding Practices
- Location
douyin.js:163- Finding
Unrestricted User-Controlled URL Fetching Enables SSRF
- Content
View full analysis
{ const parsedUrl = new URL(url); const client = parsedUrl.protocol === 'https:' ? https : http; const opts = { method: options.method || 'GET', headers: { ...HEADERS, ...options.headers } }; const req = client.request(url, opts, (res) => { if (res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) { httpRequest(res.headers.location, options) .then(resolve) .catch(reject); return; } let data = ''; res.on('data', chunk => data += chunk); res.on('end', () => { resolve({ statusCode: res.statusCode, headers: res.headers, body: data, url: url }); }); }); ``` ```js async function parseShareUrl(shareText) { const modalIdMatch = shareText.match(/(?:modal_id[=:])?(\d{16,})/); if (modalIdMatch) { const modalId = modalIdMatch[1]; return await getVideoInfoByModalId(modalId); } const urlMatch = shareText.match(/https?:\/\/[^\s]+/); if (!urlMatch) { throw new Error('No valid sharing URL was found'); } const shareUrl = urlMatch[0]; const response1 = await httpRequest(shareUrl); const finalUrl = response1.url; ``` ### Technical Analysis The skill extracts an arbitrary HTTP or HTTPS URL from caller-controlled input and sends a request to it. There is no hostname allowlist, destination IP validation, DNS rebinding defense, or rejection of loopback, private, link-local, and cloud metadata addresses. The HTTP helper also follows redirects recursively without validating the new destination or imposing an explicit redirect limit. Therefore, even if the initial URL points to a public server, ...[truncated 1781 chars]- Remediation
View remediation
