Skip to content

fix(discovery): handle data: URIs inline in fetchAgentCard#238

Open
uibeka wants to merge 3 commits intoConway-Research:mainfrom
uibeka:fix/discovery-data-uri-inline-handling
Open

fix(discovery): handle data: URIs inline in fetchAgentCard#238
uibeka wants to merge 3 commits intoConway-Research:mainfrom
uibeka:fix/discovery-data-uri-inline-handling

Conversation

@uibeka
Copy link
Contributor

@uibeka uibeka commented Feb 27, 2026

Problem

Agents storing ERC-8004 metadata as inline data:application/json;base64,... URIs are invisible to discover_agents. The SSRF filter in isAllowedUri() blocks them because data: is not in the https:/ipfs: protocol allowlist. However, data: URIs are inline encoded payloads that make no network request — there is zero SSRF risk.

This affects approximately 90% of registered agents on Base, which use inline data: URIs for their on-chain agent cards (standard ERC-8004 practice). The framework successfully scans 20+ on-chain mint events, then fails to read 18+ of their metadata URIs, causing discover_agents to report only 2-4 agents instead of the full ecosystem.

Root Cause

fetchAgentCard() passes all URIs through isAllowedUri() before fetching. The allowlist only includes https: and ipfs:. data: URIs fail this check and are logged as "Blocked URI (SSRF protection)" — a misclassification since no network request is involved.

Fix

Add a handler in fetchAgentCard() that intercepts data:application/json URIs before the SSRF check. The handler:

  1. Detects data:application/json URIs (rejects other MIME types)
  2. Decodes the payload (base64 via Buffer.from() or percent-encoded via decodeURIComponent())
  3. Enforces the existing maxCardSizeBytes size limit (matching the network fetch path's protection against oversized responses)
  4. Parses as JSON
  5. Routes through the existing validateAgentCard() for schema validation

No changes to isAllowedUri() or the SSRF filter. The network fetch path for HTTPS/IPFS URIs is completely untouched. The only change is a new code block inside fetchAgentCard() that handles data: URIs as a separate path.

Security Considerations

  • SSRF filter untouched — all network-fetched URIs still go through isAllowedUri()
  • MIME type restricted — only data:application/json accepted; data:text/html, data:image/png, etc. are rejected
  • Size limited — decoded payload checked against maxCardSizeBytes (same limit as network-fetched cards)
  • Schema validatedvalidateAgentCard() applied identically to data: URI cards and network-fetched cards
  • No network requestdata: URIs are decoded in-process from the URI string itself

Impact

  • ~18-20 agents (~90% of ecosystem) become visible to discover_agents
  • Zero changes to SSRF protection for network URIs
  • Zero changes to agent card validation
  • All failure modes return null (identical to current behavior when data: URIs are blocked)
  • Backward compatible — agents with HTTPS/IPFS metadata URIs see zero behavioral change

Testing

  • pnpm build — zero errors
  • pnpm test — all existing + 12 new tests pass
  • New unit tests: base64 decode, percent-encode decode, charset parameter handling, oversized rejection, invalid JSON rejection, invalid base64 rejection, empty payload, non-JSON MIME rejection, schema validation passthrough

Open with Devin

Agents storing ERC-8004 metadata as inline data:application/json URIs
(base64 or percent-encoded) are invisible to discover_agents. The SSRF
filter in isAllowedUri() correctly blocks network requests to non-https/
ipfs URLs, but data: URIs are inline payloads that make no network
request and pose no SSRF risk.

Add a handler in fetchAgentCard() that intercepts data:application/json
URIs before the SSRF check, decodes the payload inline, enforces the
existing maxCardSizeBytes size limit, and routes through validateAgentCard
for schema validation. No changes to the SSRF filter itself.

This makes ~18-20 agents (~90% of the current ecosystem) visible to
discovery that were previously blocked.
devin-ai-integration[bot]

This comment was marked as resolved.

Co-authored-by: devin-ai-integration[bot] <158243242+devin-ai-integration[bot]@users.noreply.github.com>
devin-ai-integration[bot]

This comment was marked as resolved.

Co-authored-by: devin-ai-integration[bot] <158243242+devin-ai-integration[bot]@users.noreply.github.com>
@uibeka
Copy link
Contributor Author

uibeka commented Feb 27, 2026

@unifiedh Addressed Devin's review comment - tightened the MIME type check. Ready for merge.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants