Skip to content

Clarify pushNotificationConfig.url port semantics (declare unconstrained) #3555

@bokelley

Description

@bokelley

Background

schemas/cache/core/push-notification-config.json (line 7-11) defines url as format: \"uri\" with no port restriction. The spec is silent on whether publishers may restrict destination ports.

Why it matters

SDKs implementing the publisher side need to decide whether to enforce a port allowlist on buyer-supplied URLs as defense-in-depth against SSRF (a buyer URL like https://internal.example.com:6379/ can smuggle traffic to internal Redis on the same routable IP, even when the IP-range check passes).

If SDKs implement port allowlists by default, they reject legitimate buyers on non-standard TLS ports — Tomcat default :9443, Spring Boot default :4443, path-routed multi-tenant gateways. If they don't, the SSRF guard is weaker.

The Python SDK's foundation audit (adcp-client-python#297 review) initially defaulted to {443, 8443} — the protocol-expert review flagged this as over-restriction, since the spec doesn't constrain ports. The fix: default permissive, expose DEFAULT_ALLOWED_PORTS as opt-in operator hardening.

Proposed fix

Add a single sentence to push-notification-config.json url description:

Publishers SHOULD NOT constrain the URL's port to standard HTTPS values (443, 8443) by default — buyers may legitimately host webhook receivers on non-standard ports (:9443 Tomcat, :4443 Spring Boot, path-routed multi-tenant gateways). Operators who want a hardened destination-port allowlist as defense in depth opt in explicitly; the default URL contract is unconstrained beyond the format: uri requirement.

Optional: also note in docs/building/implementation/security.mdx#webhook-callbacks that AdCP recommends {443, 8443} for hardened deployments — see related issue.

Why now

Locks the spec position so SDKs stop diverging on this. The Python SDK exports DEFAULT_ALLOWED_PORTS = {443, 8443} as opt-in hardening (adcp.signing.DEFAULT_ALLOWED_PORTS), aligned with what the recommendation should be.

Surfaced by Python SDK foundation audit on adcp-client-python#297.

Metadata

Metadata

Assignees

No one assigned

    Labels

    claude-triagedIssue has been triaged by the Claude Code triage routine. Remove to re-triage.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions