T09 · Insecure Skill Coding Practices
- Location
scripts/html2md.js:77- Finding
Unrestricted URL Fetching Enables Server-Side Request Forgery
- Content
View full analysis
controller.abort(), 15000); let response; try { response = await fetch(url, { signal: controller.signal, redirect: 'follow', headers: { 'User-Agent': 'html2md/1.0 (agent-friendly HTML converter; +https://github.com/openclaw/html2md)', 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', 'Accept-Language': 'en-US,en;q=0.5', }, }); } catch (err) { if (err.name === 'AbortError') die(`Timeout: request exceeded 15s for ${url}`); const cause = err.cause?.message || err.message; die(`Network error fetching ${url}: ${cause}`); } finally { clearTimeout(timer); } if (!response.ok) die(`HTTP ${response.status} ${response.statusText} — ${url}`); const ct = response.headers.get('content-type') || ''; if (!ct.includes('html') && !ct.includes('xml') && !ct.includes('text')) { die(`Non-HTML content type: ${ct} — use a different tool for binary content`); } return { html: await response.text(), finalUrl: response.url }; } ``` The untrusted URL reaches this function directly: ```js } else if (url) { const result = await fetchHtml(url); html = result.html; pageUrl = result.finalUrl; } ``` ### Technical Analysis The CLI fetches a caller-provided URL without validating its scheme, hostname, resolved IP addresses, port, or network destination. It also enables automatic redirects through `redirect: 'follow'` without validating each redirect target. This behavior is necessary at a basic level because URL retrieval is part of the declared HTML conversion functionality. However, ...[truncated 1962 chars]- Remediation
View remediation
