Summary
did:jwks resolution currently validates/builds the initial DID-derived URLs, but the OIDC discovery fallback can return an arbitrary jwks_uri. That jwks_uri is then fetched without applying an equivalent URL policy.
This means a resolver can be made to fetch a URL that was not derived from the original did:jwks identifier and may not satisfy the same scheme/host expectations as the first-hop request.
Affected Code
packages/did/src/did-resolvers/get-did-resolver.ts
jwks-did-resolver / did-jwks resolution path
Relevant Dependency Behavior
did-jwks@1.1.0 performs this flow:
- fetch
https://<did-host>/.well-known/jwks.json
- if unavailable, fetch
https://<did-host>/.well-known/openid-configuration
- if the discovery document contains
jwks_uri, fetch that URL directly
The OpenID configuration schema validates jwks_uri as a URL, but does not appear to restrict scheme, host, localhost/private-network ranges, or same-origin/cross-origin policy before fetching it.
Why This Matters
ACK's DID resolver is used underneath verification paths such as JWT verification, VC verification, ACK-ID controller verification, and ACK-Pay receipt verification. These flows may need to resolve a DID before a signature can be verified.
If an application resolves attacker-controlled did:jwks identifiers, the OIDC discovery fallback can cause server-side fetches to URLs chosen by the DID host through jwks_uri.
Minimal Reproduction
Using ACK's public resolver API with a mocked fetch:
- The direct JWKS endpoint returns 404.
- The OpenID configuration endpoint returns a
jwks_uri pointing somewhere else.
- The resolver fetches the
jwks_uri target.
Observed fetch sequence:
[
"https://attacker.example/.well-known/jwks.json",
"https://attacker.example/.well-known/openid-configuration",
"http://169.254.169.254/latest/meta-data/iam/security-credentials/"
]
Expected Behavior
did:jwks resolution should apply a URL policy to OIDC discovery jwks_uri targets before fetching them.
Possible safe defaults:
- allow only
https:// by default
- reject localhost / loopback addresses
- reject
0.0.0.0
- reject RFC1918/private ranges
- reject link-local ranges such as
169.254.0.0/16
- reject IPv6 loopback/link-local/unique-local ranges
- optionally require same-origin
jwks_uri, or provide an explicit allowlist/callback for legitimate cross-origin JWKS providers
Relation to Existing Issues/PRs
I checked the existing issue/PR history and this does not appear to be the same as the did:web redirect issue.
Related but different:
This issue is not about following HTTP redirects. It is about the OIDC discovery document explicitly returning a jwks_uri that points to another URL. A redirect policy alone does not validate that jwks_uri target.
Suggested Fix
Wrap the fetch passed into jwks-did-resolver / did-jwks with URL validation that applies to every fetch target, including OIDC-discovered jwks_uri values.
Alternatively, expose a did:jwks-specific option such as:
allowedJwksUriHosts
allowJwksUri(url, did)
allowPrivateJwksUriTargets: false
and default to a conservative policy.
Summary
did:jwksresolution currently validates/builds the initial DID-derived URLs, but the OIDC discovery fallback can return an arbitraryjwks_uri. Thatjwks_uriis then fetched without applying an equivalent URL policy.This means a resolver can be made to fetch a URL that was not derived from the original
did:jwksidentifier and may not satisfy the same scheme/host expectations as the first-hop request.Affected Code
packages/did/src/did-resolvers/get-did-resolver.tsjwks-did-resolver/did-jwksresolution pathRelevant Dependency Behavior
did-jwks@1.1.0performs this flow:https://<did-host>/.well-known/jwks.jsonhttps://<did-host>/.well-known/openid-configurationjwks_uri, fetch that URL directlyThe OpenID configuration schema validates
jwks_urias a URL, but does not appear to restrict scheme, host, localhost/private-network ranges, or same-origin/cross-origin policy before fetching it.Why This Matters
ACK's DID resolver is used underneath verification paths such as JWT verification, VC verification, ACK-ID controller verification, and ACK-Pay receipt verification. These flows may need to resolve a DID before a signature can be verified.
If an application resolves attacker-controlled
did:jwksidentifiers, the OIDC discovery fallback can cause server-side fetches to URLs chosen by the DID host throughjwks_uri.Minimal Reproduction
Using ACK's public resolver API with a mocked fetch:
jwks_uripointing somewhere else.jwks_uritarget.Observed fetch sequence:
Expected Behavior
did:jwksresolution should apply a URL policy to OIDC discoveryjwks_uritargets before fetching them.Possible safe defaults:
https://by default0.0.0.0169.254.0.0/16jwks_uri, or provide an explicit allowlist/callback for legitimate cross-origin JWKS providersRelation to Existing Issues/PRs
I checked the existing issue/PR history and this does not appear to be the same as the
did:webredirect issue.Related but different:
did:web/did:jwksresolution.This issue is not about following HTTP redirects. It is about the OIDC discovery document explicitly returning a
jwks_urithat points to another URL. A redirect policy alone does not validate thatjwks_uritarget.Suggested Fix
Wrap the fetch passed into
jwks-did-resolver/did-jwkswith URL validation that applies to every fetch target, including OIDC-discoveredjwks_urivalues.Alternatively, expose a
did:jwks-specific option such as:allowedJwksUriHostsallowJwksUri(url, did)allowPrivateJwksUriTargets: falseand default to a conservative policy.