T09 · Insecure Skill Coding Practices
- Location
index.js:7- Finding
Unrestricted Server-Side Request Forgery Through Caller-Controlled URLs
- Content
View full analysis
{ return new Promise((resolve, reject) => { const isHttps = url.startsWith('https://'); const protocol = isHttps ? https : http; const options = { headers: { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36', 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', 'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8', } }; protocol.get(url, options, (res) => { ``` ### Technical Analysis The `fetch` tool passes a caller-controlled URL directly to Node.js `http.get` or `https.get`. It does not parse and validate the URL before establishing the connection, resolve and inspect the destination address, or restrict requests to approved hosts. The implementation does not block: - Loopback addresses such as `127.0.0.1` and `::1` - RFC 1918 private IPv4 networks - IPv6 unique-local and link-local networks - Link-local addresses such as `169.254.0.0/16` - Cloud metadata services - Internal hostnames and DNS names that resolve to private addresses - DNS rebinding scenarios - Alternative textual representations of restricted IP addresses In addition, every value that does not start with the exact string `https://` is assigned to the HTTP client rather than being rejected through an explicit `http:`/`https:` protocol allowlist. Although redirects are only reported rather than followed, this does not mitigate direct requests to restricted destinations. ### Attack Path 1. An attacker invokes the skill's `fetch` tool with an internal destination, such as `http://127.0.0.1:8080/admin`, a private-network service, or a cloud metadata URL. 2. The skill selects Node.js's HTTP client and sends the request from the Agent runti ...[truncated 1139 chars]- Remediation
View remediation
