Skip to content

fix: validate resolved URL scheme/authority in _substitute_url_template (F-07-01)#12

Merged
kurtseifried merged 2 commits into
mainfrom
fix/resolver-url-validation
Jun 21, 2026
Merged

fix: validate resolved URL scheme/authority in _substitute_url_template (F-07-01)#12
kurtseifried merged 2 commits into
mainfrom
fix/resolver-url-validation

Conversation

@kurtseifried

Copy link
Copy Markdown
Contributor

Finding

F-07-01 — the Server-API (Python) half of the resolver-layer URL-validation, mirroring the Worker fix in SecID-Service#17. Closes Patch 06 across both resolvers.

_substitute_url_template substituted query-derived values into a registry URL template via raw str.replace with no validation. Latent today (registry templates keep placeholders in path position), but if a template placed a placeholder in the authority, a crafted identifier could steer the resolved host/scheme (open redirect).

Fix

_substitute_url_template now returns Optional[str]: it re-parses the assembled URL and returns None unless the scheme + netloc match the template's literal authority (read by neutralizing {placeholders}). The three callers (#subpath, @version, cross-source) drop to a description-only result on None.

Values are kept verbatim — no quote() encoding — so identifiers that contain reserved chars (e.g. RHSA-2024:1234) are preserved. (Same lesson as #17, where blanket encoding broke the colon case.)

Tests

2 new tests: authority-injection dropped (https://{id}.example.com/, https://{id}/path → None) and reserved-char preservation on the same host. The 6 existing _substitute_url_template tests still pass. Full suite: 30 passed.

Generated from PATCHES/06-resolver-url-validation.patch.md (Server-API half).

🤖 Generated with Claude Code

kurtseifried and others added 2 commits June 20, 2026 07:24
…te (F-07-01)

Mirror of the SecID-Service buildUrl fix (#17): the self-hosted resolver
substituted query-derived values into a registry URL template via raw
str.replace with no validation. _substitute_url_template now re-parses the
assembled URL and returns None (callers drop to a description-only result)
unless the scheme + netloc match the template's literal authority. Values are
kept verbatim — identifiers legitimately contain ':' etc. (RHSA-2024:1234), so
the authority check, not encoding, is what prevents an open redirect.

Latent today (registry templates keep placeholders in path position); this is
the resolver layer of the defense-in-depth URL-validation decision. Adds 2
regression tests; full suite 30 passed.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@kurtseifried kurtseifried merged commit 8393bdc into main Jun 21, 2026
2 checks passed
@kurtseifried kurtseifried deleted the fix/resolver-url-validation branch June 21, 2026 04:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant