Skip to content

Refuse redirects when fetching a creator's key - #7

Merged
jwrosewell merged 1 commit into
mainfrom
fix/refuse-redirects
Sep 6, 2026
Merged

jwrosewell merged 1 commit into
mainfrom
fix/refuse-redirects

Conversation

@jwrosewell

Copy link
Copy Markdown
Contributor

Found in the review that followed the Python and PHP fetches, which were
modelled on this one and inherited it.

The key fetch followed redirects. HttpURLConnection follows one to any
other host by default, refusing only a change of protocol, so a creator
whose domain answered 302 to some other https host would have that other
host's key trusted as its own, and a network attacker able to bend the
creator's DNS, or a creator that was simply misconfigured, could put a
key there and have forgeries verify. There is no legitimate reason for
the well known key end point to send a caller off its own host, and this
is the one request in the specification whose answer decides whether an
identifier is genuine.

setInstanceFollowRedirects(false) leaves the 3xx as the response code,
which read() already treats as the key being unavailable with the code
carried, which is what it is.

The stand in end point learned a REDIRECT answer naming where to send the
caller. The new test redirects to a second stand in serving the genuine
schedule, so following would read as valid, and asserts the answer is
unavailable, the creator was asked once, and the second stand in never
was. It fails when redirects are followed again.

DatedKeyFetchTest: 15 tests, up from 14.

Produced with AI assistance after an adversarial review of the fetch across every port, and needs human review before merging. Held for the batch merge with the other six. The test was proved by mutation.

Found in the review that followed the Python and PHP fetches, which were
modelled on this one and inherited it.

The key fetch followed redirects. HttpURLConnection follows one to any
other host by default, refusing only a change of protocol, so a creator
whose domain answered 302 to some other https host would have that other
host's key trusted as its own, and a network attacker able to bend the
creator's DNS, or a creator that was simply misconfigured, could put a
key there and have forgeries verify. There is no legitimate reason for
the well known key end point to send a caller off its own host, and this
is the one request in the specification whose answer decides whether an
identifier is genuine.

setInstanceFollowRedirects(false) leaves the 3xx as the response code,
which read() already treats as the key being unavailable with the code
carried, which is what it is.

The stand in end point learned a REDIRECT answer naming where to send the
caller. The new test redirects to a second stand in serving the genuine
schedule, so following would read as valid, and asserts the answer is
unavailable, the creator was asked once, and the second stand in never
was. It fails when redirects are followed again.

DatedKeyFetchTest: 15 tests, up from 14.
@jwrosewell
jwrosewell merged commit 9a9ac62 into main Sep 6, 2026
8 checks passed
@jwrosewell
jwrosewell deleted the fix/refuse-redirects branch September 6, 2026 15:44
jwrosewell added a commit to 51Degrees/pipeline-java that referenced this pull request Sep 6, 2026
…ing a key (#126)

The 51Degrees fork of owid-java now carries SWAN-community/owid-java#7,
which stops HttpURLConnection following a redirect from a creator domain,
so a creator whose domain answered 302 could no longer have some other
host's key trusted as its own. The pin moves from 764996e0 to 44d4e0bf,
the fork's main after the sync. PublicKeyFetch.java stays excluded from
this module's build, as before, because DidClient fetches the cloud's key
list through its own transport.

pipeline.did tests: 127 run, 0 failures.
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