T09 · Insecure Skill Coding Practices
- Location
nft.js:53- Finding
Unrestricted NFT Metadata URL Fetch Enables Server-Side Request Forgery
- Content
View full analysis
null), contract.tokenURI(tokenId).catch(() => null) ]); if (!owner) { console.log(JSON.stringify({ error: 'Token does not exist or was burned' })); return; } let metadata = null; if (tokenURI && tokenURI.startsWith('http')) { try { const response = await fetch(tokenURI, { timeout: 5000 }); metadata = await response.json(); } catch (e) { // Could not fetch metadata } } ``` ### Technical Analysis The metadata URL originates from the untrusted `tokenURI()` response of a user-selected NFT contract. The implementation only checks whether the value begins with `http`, then requests it from the environment running the Skill. This allows both HTTP and HTTPS URLs without validating the destination hostname or resolved IP address. Consequently, a malicious contract can return URLs targeting: - Loopback services such as `127.0.0.1` or `[::1]` - Private network ranges - Link-local addresses - Cloud instance metadata services - Internal administrative or development services - Redirectors that ultimately resolve to a restricted destination The retrieved JSON is included in the command output. If an internal endpoint returns valid JSON, this behavior can expose its response through the Skill. The request also lacks effective resource controls. The standard Node.js `fetch` API does not enforce a `timeout` option in this form; an `AbortSignal` is required. No response-size limit is imposed before `response.json()` buffers and parses the response, creating an additional denial-of-service risk. Fetching remote NFT metadata is consistent with the declared functionality, but unrestricted access to arbitrary netw ...[truncated 1707 chars]- Remediation
View remediation
