T09 · Insecure Skill Coding Practices
Error
- Location
- lib/get-agent.js:13
- Finding
- Unrestricted Fetch of Attacker-Controlled On-Chain Agent URI Enables SSRF## Vulnerability Details **File Location**: `lib/get-agent.js:13-29` **Vulnerability Type**: Server-Side Request Forgery (SSRF) **Risk Level**: High ### Vulnerable Code ```js const [owner, agentURI, wallet] = await Promise.all([ registry.ownerOf(id), registry.tokenURI(id), registry.getAgentWallet(id), ]); const ZERO = "0x0000000000000000000000000000000000000000"; const result = { owner, agentURI, agentWallet: wallet === ZERO ? null : wallet, }; // Try to fetch and parse the agentURI if (agentURI && agentURI.startsWith("http")) { try { const res = await fetch(agentURI); if (res.ok) result.parsedJson = (await res.json()); } catch { // skip — optional } } ``` ### Technical Analysis The `agentURI` value is obtained from an on-chain `tokenURI` field that an agent registrant can control. `getAgent()` automatically performs a server-side request to this value whenever it starts with `http`. The prefix check is not an effective security boundary. It permits both HTTP and HTTPS and does not: - Reject loopback, private, link-local, multicast, or reserved IP ranges. - Resolve and validate hostnames against prohibited address ranges. - Restrict requests to trusted hosts. - Revalidate destinations after HTTP redirects. - Enforce connection or response timeouts. - Limit response size before JSON parsing. Although the request does not directly transmit the configured `PRIVATE_KEY`, it allows an attacker to make the Skill runtime access network resources that are not directly reachable by the attacker. Automatic metadata retrieval is not necessary to return the on-chain owner, wallet, and URI fields, so this behavior exceeds the minimum network privileges needed for the core read operation. ### Attack Path 1. An attacker registers or controls an agent record. 2. The attacker sets its on-chain `tokenURI` to an internal target, loopback endpoint, cloud metadata endpoint, or attacker-controlled ...[truncated 1113 chars]
- Remediation
- ## Remediation Suggestions 1. Make remote `agentURI` retrieval explicitly opt-in. By default, return the URI without fetching it. 2. Permit only the `https:` protocol unless HTTP support is strictly required. 3. Resolve the destination hostname and reject all loopback, private, link-local, multicast, unspecified, and reserved IPv4 and IPv6 addresses. 4. Disable automatic redirects or validate the protocol, hostname, resolved addresses, and port at every redirect hop. 5. Prefer an allowlist of trusted metadata hosts where compatible with the registry design. 6. Block sensitive ports and reject URLs containing credentials. 7. Apply strict connection and overall request timeouts using an abort signal. 8. Stream responses with a conservative maximum byte limit before parsing JSON. 9. Validate the response `Content-Type` and parsed document schema. 10. Consider retrieving metadata through an isolated proxy with restricted egress and no access to internal networks or cloud metadata services.
