T09 · Insecure Skill Coding Practices
- Location
scripts/audit.js:300- Finding
Server-Side Request Forgery Through Attacker-Controlled Agent URI
- Content
View full analysis
Vulnerability Details
File Location:
scripts/audit.js, lines 300–329; request helper at lines 155–171
Vulnerability Type: Unrestricted server-side request forgery (SSRF)
Risk Level: HighVulnerable Code
js async function fetchJson(url, timeout = 10000) { const controller = new AbortController(); const timeoutId = setTimeout(() => controller.abort(), timeout); try { const response = await fetch(url, { signal: controller.signal }); clearTimeout(timeoutId); if (!response.ok) { throw new Error(`HTTP ${response.status}: ${response.statusText}`); } return await response.json(); } catch (error) { clearTimeout(timeoutId); throw error; } }js let agentURI; try { agentURI = await identityRegistry.tokenURI(agentId); report.metadata.agentURI = agentURI; console.log(` Agent URI: ${agentURI}`); } catch (error) { findings.push({ severity: SEVERITY.CRITICAL, title: 'Missing Agent URI', description: 'Could not retrieve agent URI from registry', recommendation: 'Contact agent owner to set agentURI' }); report.summary.critical++; console.log(` ${colors.red}✗ Error: ${error.message}${colors.reset}`); return report; } let registration; try { if (agentURI.startsWith('data:')) { const base64Data = agentURI.replace('data:application/json;base64,', ''); const jsonStr = Buffer.from(base64Data, 'base64').toString('utf-8'); registration = JSON.parse(jsonStr); } else { registration = await fetchJson(agentURI); }Technical Analysis
The agent owner controls the
tokenURIreturned by the on-chain registry. Every URI not beginning withdata:is passed directly to the built-infetchAPI.No validation is performed on:
- The URI scheme.
- The destination hostname.
- The destination's resolved IPv4 or IPv6 addresses.
- Lo ...[truncated 2131 chars]
- Remediation
View remediation
Remediation Suggestions
- Allow only explicitly supported URI schemes, such as
https:and strictly validateddata:application/json;base64. - Implement IPFS access through a configured trusted gateway rather than passing
ipfs:URIs to genericfetch. - Resolve destination hostnames before connecting and reject all loopback, private, link-local, multicast, unspecified, and reserved IPv4 and IPv6 ranges.
- Explicitly reject cloud metadata destinations, including link-local metadata addresses.
- Disable automatic redirects or validate the scheme, hostname, and resolved address at every redirect.
- Reject URLs containing embedded usernames or passwords.
- Apply a strict response-size limit before parsing JSON.
- Retain the timeout and add limits for redirect count and decompressed response size.
- Consider routing metadata requests through an isolated egress proxy with no access to internal networks.
- Validate the response content type and registration schema before adding it to the report.
- Allow only explicitly supported URI schemes, such as
