T09 · Insecure Skill Coding Practices
- Location
lib/torchsdk/tokens.js:268- Finding
Creator-Controlled Metadata URI Enables Server-Side Request Forgery
- Content
View full analysis
Vulnerability Details
File Location:
lib/torchsdk/tokens.js:268-285
Vulnerability Type: Server-Side Request Forgery through an unvalidated metadata URI
Risk Level: MediumVulnerable Code
javascript // Fetch metadata from URI let metadata; const uri = (0, program_1.decodeString)(bondingCurve.uri); if (uri) { try { const controller = new AbortController(); const timer = setTimeout(() => controller.abort(), 10000); const res = await fetch(uri, { signal: controller.signal }).finally(() => clearTimeout(timer)); const data = (await res.json()); metadata = { description: data.description, 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)}`); } }Technical Analysis
The metadata URI is read from the on-chain
BondingCurve.urifield, which is controlled by the token creator. The SDK passes this value directly tofetch()without validating:- The permitted URI scheme
- The destination hostname or resolved IP address
- Loopback and private network ranges
- Link-local and cloud metadata addresses
- Nonstandard destination ports
- Redirect destinations
- Response content type or maximum response size
The ten-second
AbortControllertimeout reduces the risk of indefinitely hanging requests but does not prevent server-side request forgery. A creator can supply a URI targeting services reachable from the Agent's runtime, including localhost, private network services, or cloud instance metadata endpoints.Because redirects are followed by default, an apparently public URL could also redirect to a prohibited internal destination unless every redirect hop is independently validated.
The autonom ...[truncated 1865 chars]
- Remediation
View remediation
Remediation Suggestions
- Parse metadata locations with
new URL(uri)and permit only an explicitly supported scheme, preferablyhttps:. - Reject URLs containing embedded usernames or passwords.
- Restrict destination ports to an allowlist such as port 443.
- Resolve the destination hostname before connecting and reject:
- IPv4 and IPv6 loopback ranges
- RFC1918 private ranges
- Link-local addresses
- Multicast and unspecified addresses
- Cloud metadata destinations
- Disable automatic redirects or validate the scheme, hostname, resolved address, and port of every redirect hop.
- Apply a strict response-size limit while streaming the body rather than calling unrestricted
res.json(). - Require a successful HTTP status and an expected JSON content type before parsing.
- Prefer an allowlist of trusted metadata gateways, such as an approved Arweave gateway, instead of permitting arbitrary creator-selected hosts.
- Retain the existing timeout, but combine it with connection, body-size, and redirect limits.
- Add tests covering localhost, private IPv4, private IPv6, DNS rebinding, alternate numeric IP representations, and redirect-based SSRF attempts.
- Parse metadata locations with
