Skip to content

Commit 4e2ae8f

Browse files
bokelleyclaude
andauthored
fix(adagents): strip surrounding whitespace in normalize_url (#1629)
normalize_url(" https://interchange.io ") returned "interchange.io " because urlparse drops leading whitespace but keeps trailing whitespace in the path, so an adagents.json entry with a padded url did not match its agent. Strip before parsing; _normalize_domain already does the same. Signing paths keep byte-exact canonicalization: canonicalize_target_uri is a signature-base canonicalizer, and the brand.json / adagents entry matches in signing select keys or the signer identity and fail closed. Fixes #1624 Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
1 parent 6f61234 commit 4e2ae8f

2 files changed

Lines changed: 12 additions & 2 deletions

File tree

‎src/adcp/adagents.py‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -475,9 +475,10 @@ def normalize_url(url: str) -> str:
475475
Paths remain case-sensitive. Query strings and fragments are ignored, and
476476
trailing path slashes are removed, preserving the existing matching rules.
477477
Only the default port for the supplied scheme is removed (80 for HTTP,
478-
443 for HTTPS); non-default ports remain significant.
478+
443 for HTTPS); non-default ports remain significant. Surrounding
479+
whitespace is stripped, so a padded adagents.json ``url`` still matches.
479480
"""
480-
parsed = urlparse(url)
481+
parsed = urlparse(url.strip())
481482
authority = parsed.netloc
482483
if parsed.hostname is not None:
483484
host = parsed.hostname.lower()

‎tests/test_adagents_matching.py‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,9 @@ def document(url: Any = AGENT, tags: list[str] | None = None) -> dict[str, Any]:
4545
"https://SALES.Example.com:443/mcp/",
4646
"http://sales.example.com:80/mcp",
4747
"https://sales.example.com/mcp/?q=x#fragment",
48+
# #1624: stray whitespace around a listed url must not hide the agent.
49+
" https://sales.example.com/mcp ",
50+
"\thttps://sales.example.com/mcp/\n",
4851
],
4952
)
5053
def test_normalization_retains_protocol_and_path_contract(url: str) -> None:
@@ -98,3 +101,9 @@ def test_listing_distinguishes_unbound_and_unlisted_and_retains_duplicates() ->
98101
matches = find_authorized_agent_entries(unbound, AGENT)
99102
assert matches == unbound["authorized_agents"]
100103
assert matches[0] is unbound["authorized_agents"][0]
104+
105+
106+
def test_normalization_strips_surrounding_whitespace_on_either_side() -> None:
107+
assert normalize_url(" https://interchange.io ") == "interchange.io"
108+
assert normalize_url(" https://interchange.io ") == normalize_url("https://interchange.io")
109+
assert find_authorized_agent_entries(document(), f" {AGENT} ")

0 commit comments

Comments
 (0)