Skip to content

DID: default getDidResolver() allows plain HTTP did:web fetches to loopback hosts (localhost, 127.0.0.1, 0.0.0.0) #223

Description

@byfor8

Summary

getDidResolver() defaults webOptions.allowedHttpHosts to ["localhost", "127.0.0.1", "0.0.0.0"], and the web DID resolver sends http:// (not https://) for any host in that list. A default-configured verifier therefore issues plain HTTP requests to its own loopback when resolving attacker-chosen did:web identifiers.

Attack path

JWT verification resolves the iss claim to obtain the verify key before the signature can succeed (did-jwt verifyJWT). isDidWebUri is only a did:web: prefix check, and buildDidPath percent-decodes the method-specific id, so did:web:127.0.0.1%3A6379 resolves to host 127.0.0.1:6379 over http://. There is no scheme allowlist beyond allowedHttpHosts and no private-IP denylist. The same default resolver is what every official example/demo passes into verifyPaymentRequestToken / parseJwtCredential.

Reproduction (source level)

  1. Attacker signs a JWT with iss: did:web:127.0.0.1%3A6379.
  2. Service calls any verify function that defaults to getDidResolver() (e.g. verifyA2AHandshakeMessage, verifyA2ASignedMessage, verifyPaymentRequestToken).
  3. The verifier issues http://127.0.0.1:6379/... on its own machine before any signature check can reject the token. The request repeats per verification attempt.

Note: 169.254.169.254 is not in the HTTP allowlist, so this is loopback/internal-service exposure rather than cloud-metadata SSRF.

Impact

Integrators running unauthenticated internal services on localhost expose them to crafted tokens from any external party: verification triggers attacker-directed internal HTTP requests.

Suggested fix

Default allowedHttpHosts to [] so the convenience wrapper is HTTPS-only, matching getResolver()'s own DEFAULT_ALLOWED_HTTP_HOSTS = []. Callers who truly need plain-HTTP local resolution can opt back in explicitly.

Environment: agentcommercekit/ack at commit b5b25ce (main as of 2026-09-12). Reviewed at source level; no live systems were tested.

Disclosure note: reported to security@agentcommercekit.com per SECURITY.md on 2026-09-14; a maintainer asked for these to be filed publicly, so they are here.

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions