adagents.json discovery: follow same-registrable-domain redirects on .well-known, refuse on authoritative_location (adcp#5450)
Maintainers usually reply within 1 day
Nobody has claimed this yet.
Assessment
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Newbie friendliness
- 45/100
- Issue type
- Bug
- Clarity
- Clearly specified
- Activity status
- Active
- Tech stack
- go
- Domain
- backend-api-design, security
Research direction
Locate the adagents.json/.well-known discovery fetch and the authoritative_location dereference in the Go SDK, then read the shared adagents-discovery-redirects.json vectors linked in the issue. Implement the distinct redirect rules, origin-anchored same-registrable-domain checks with private PSL domains, and per-hop SSRF validation. Run every shared vector and confirm each resolves or refuses as specified.
Written by the indexing model from the issue text.
Description
Context
AdCP issue adcontextprotocol/adcp#5450 and merged spec PR adcontextprotocol/adcp#5472 define the redirect policy for adagents.json discovery. The reference validator in adcontextprotocol/adcp is now aligned; this SDK needs the same behavior so all AdCP implementations resolve discovery identically.
The bug this fixes: a publisher whose apex domain 301-redirects to www (the default on most managed hosting / CDNs) is silently reported unauthorized by validators that refuse all redirects on the discovery fetch.
Policy — two hops, deliberately different
| Fetch | Redirect policy |
|---|---|
Initial https://{domain}/.well-known/adagents.json |
Follow same-registrable-domain redirects (apex↔www, HTTPS-preserving, ≤3 hops), re-validating SSRF (reject non-HTTPS, reject reserved/private IPs, pin connect) on every hop, with the same-domain comparison anchored on the originally-requested domain at every hop (not the previous hop). Refuse cross-registrable-domain redirects — that is an unscoped delegation signal; the publisher should declare delegation via authoritative_location instead. |
authoritative_location dereference (2nd hop) |
Refuse all redirects. The named URL is the declared authoritative location; a redirect away from it changes that declaration and MUST be treated as an error. |
⚠️ Security-critical: use the PSL private section
Registrable-domain comparison MUST use the Public Suffix List including its PRIVATE section. Without it, shared-hosting tenants collapse to one registrable domain — victim.github.io and attacker.github.io both reduce to github.io — and a cross-tenant redirect would be wrongly followed and trusted as authoritative. The same applies to *.pages.dev, *.web.app, *.herokuapp.com, *.wordpress.com, etc. The reference impl uses tldts.getDomain(host, { allowPrivateDomains: true }).
Conformance
Gate on the shared cross-SDK vectors: static/test-vectors/adagents-discovery-redirects.json. They cover apex↔www, subdomain, co.uk (ICANN multi-label), *.github.io (PSL private section), same→cross two-hop (origin-anchored), HTTPS downgrade, hop cap, and the authoritative-location refuse-all rule. The normative assertion per vector is result (resolved vs refused).
This SDK (adcp-go)
Locate the adagents.json / .well-known discovery fetch and apply the policy above.
.well-knownfetch → follow same-registrable-domain redirects (≤3 hops, per-hop SSRF, anchored on origin), refuse cross-domain. The Gohttp.Clientfollows redirects by default — implement aCheckRedirectthat enforces the same-domain + HTTPS + hop-cap rules, or follow manually.authoritative_locationdereference → setCheckRedirectto refuse (returnhttp.ErrUseLastResponse/ an error).- PSL private section:
golang.org/x/net/publicsuffixdoes not include private-section control; usegithub.com/weppos/publicsuffix-gowithIncludePrivateDomains: true(or equivalent) so shared-hosting tenants are distinct registrants.
Acceptance: the discovery path passes every vector in adagents-discovery-redirects.json.
- Dominant language
- Go
- Stars
- 4
- Forks
- 2
- Avg merge
- 1d 16h
- Merged PRs (30d)
- 15
Getting set up
This project ships no dev container, Dockerfile or contributing guide, so setting up is up to you: start from its README, and see our first-contribution guide for the general steps.
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from adcontextprotocol/adcp-go
-
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
adcontextprotocol/adcp-go#567 ·
Maintainers usually reply within 1 day
-
Difficulty 4/5 3-5 days Newbie friendliness 25/100
adcontextprotocol/adcp-go#570 ·
Maintainers usually reply within 1 day
-
Difficulty 4/5 3-5 days Newbie friendliness 22/100
adcontextprotocol/adcp-go#564 ·
Maintainers usually reply within 1 day
-
Difficulty 5/5 Over a week Newbie friendliness 8/100
adcontextprotocol/adcp-go#556 ·
Maintainers usually reply within 1 day
-
claude-triaged cross-repo
Difficulty 5/5 Over a week Newbie friendliness 25/100
adcontextprotocol/adcp-go#548 · 2 comments ·
Maintainers usually reply within 1 day
All issues in adcontextprotocol/adcp-go
Similar issues
-
clawsweeper:fix-shape-clear clawsweeper:queueable-fix clawsweeper:source-repro impact:session-state issue-rating: 🦞 diamond lobster no-stale P2
Difficulty 2/5 1-3 hours Newbie friendliness 74/100
openclaw/wacli#503 · 1 comment · 1 reaction ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 81/100
apache/rocketmq-dashboard#6895 ·
Maintainers usually reply within 3 days
-
agent-butler-finding chore
Difficulty 1/5 Under an hour Newbie friendliness 88/100
jordansmall/spindrift#5466 ·
Maintainers usually reply within 1 day
-
Difficulty 1/5 Under an hour Newbie friendliness 92/100
open-telemetry/opentelemetry-go-compile-instrumentation#1507 ·
Maintainers usually reply within 3 days
-
Difficulty 1/5 Under an hour Newbie friendliness 87/100
777genius/agent-notifications#490 ·
Maintainers usually reply within 1 day