T09 · Insecure Skill Coding Practices
- Location
- lib/torchsdk/tokens.js:280
- Finding
- Creator-Controlled Token Metadata URL Enables Server-Side Request Forgery<![CDATA[ ## Vulnerability Details **File Location**: `lib/torchsdk/tokens.js:280-294`; supporting request implementation in `lib/torchsdk/gateway.js:32-44` **Vulnerability Type**: Server-Side Request Forgery through an untrusted on-chain metadata URI **Risk Level**: Medium ### Vulnerable Code `lib/torchsdk/tokens.js:280-294`: ```js // Fetch metadata from URI let metadata; const uri = (0, program_1.decodeString)(bondingCurve.uri); if (uri) { try { const res = await (0, gateway_1.fetchWithFallback)(uri); const data = (await res.json()); metadata = { description: data.description, image: data.image && (0, gateway_1.isIrysUrl)(data.image) ? (0, gateway_1.irysToUploader)(data.image) : data.image, twitter: data.twitter, telegram: data.telegram, website: data.website, }; } catch (e) { warnings.push(`Metadata fetch failed: ${e instanceof Error ? e.message : String(e)}`); } } ``` `lib/torchsdk/gateway.js:32-44`: ```js const fetchWithFallback = async (url, options, timeoutMs = 10000) => { const controller = new AbortController(); const timer = setTimeout(() => controller.abort(), timeoutMs); const opts = { ...options, signal: controller.signal }; try { if ((0, exports.isIrysUrl)(url)) { return await fetch((0, exports.irysToArweave)(url), opts); } return await fetch(url, opts); } finally { clearTimeout(timer); } }; ``` ### Technical Analysis The `BondingCurve.uri` value is obtained from on-chain token data and can be selected by the token creator. Calling `getToken()` or the Kit's `getFaction()` wrapper causes the runtime to issue a network request to that URI. `fetchWithFallback()` applies a ten-second timeout and rewrites known Irys hostnames, but it does not: - Restrict requests to HTTPS. - Allowlist trusted metadata gateways. - Reject loopback, private, link-local, multicas ...[truncated 1918 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Accept only explicitly supported URI schemes, preferably `https:`. 2. Use an allowlist of trusted metadata gateways where operationally possible. 3. Resolve destination hostnames before connecting and reject: - IPv4 loopback and private ranges. - IPv4 link-local and multicast ranges. - IPv6 loopback, unique-local, link-local, and mapped private IPv4 ranges. - Cloud metadata addresses such as `169.254.169.254`. 4. Disable redirects or manually process them, applying the same scheme, hostname, DNS, and IP validation to every destination. 5. Guard against DNS rebinding by connecting only to the validated resolved address while preserving the expected TLS hostname. 6. Set strict limits for connection time, total request time, response body size, and redirect count. 7. Require an appropriate JSON content type and parse only within a bounded response size. 8. Return generic fetch failures rather than exposing detailed internal networking errors. 9. Consider requiring callers to opt in before resolving arbitrary creator-hosted metadata. ]]>
