T09 · Insecure Skill Coding Practices
- Location
scripts/media-localizer.ts:212- Finding
Blind SSRF Through Unrestricted Media Localization
- Content
View full analysis
(); const fmMatch = markdown.match(/^---\n([\s\S]*?)\n---/); if (fmMatch) { const coverMatch = fmMatch[1]?.match(FRONTMATTER_COVER_RE); if (coverMatch?.[2] && !seen.has(coverMatch[2])) { seen.add(coverMatch[2]); candidates.push({ url: coverMatch[2], hint: "image" }); } } MARKDOWN_LINK_RE.lastIndex = 0; let match: RegExpExecArray | null; while ((match = MARKDOWN_LINK_RE.exec(markdown))) { const label = match[1] ?? ""; const rawUrl = match[3] ?? ""; if (!rawUrl || seen.has(rawUrl)) continue; const isImage = label.startsWith("!["); if (!isImage && !isPlausibleMediaUrl(rawUrl)) continue; seen.add(rawUrl); candidates.push({ url: rawUrl, hint: isImage ? "image" : "unknown", }); } return candidates; } ``` ```ts for (const candidate of candidates) { try { const downloadUrl = toHighResUrl(candidate.url); const response = await fetch(downloadUrl, { method: "GET", redirect: "follow", headers: { "user-agent": DOWNLOAD_USER_AGENT, }, }); ``` ### Technical Analysis Media URLs are extracted from generated or previously saved Markdown and passed to `fetch` without validating their destination. Image syntax is sufficient to make any HTTP or HTTPS URL a download candidate. The implementation does not: - Restrict requests to expected X media hosts. - Reject loopback, private, link-local, multicast, or reserved IP ranges. - Resolve and validate DNS results. - Validate the destination of each redirect. - Disable cross-origin redirects. - Require HT ...[truncated 1629 chars]- Remediation
View remediation
