fix(moshpit): never sell or answer for a real top-level domain - #462
Merged
Conversation
`.sh` was claimed through the ordinary registration flow, for $2, by someone
who is not us. It is Saint Helena's ccTLD. It is also where this project's own
registry lives: pit.moshcode.sh.
Every bridge that fetched the ending list therefore learned to treat the
registry as a Moshpit name. It stopped forwarding it to the clearnet and tried
to resolve it through the registry it had just made unreachable, which is a
resolver that cannot resolve the thing it needs in order to resolve anything.
The observed state on an affected desktop was a bridge that was running,
listening, correctly routed to, and answering NXDOMAIN to the entire internet:
pit.moshcode.sh → NXDOMAIN
alt.2600 → NXDOMAIN
mail-ads.google.com → NXDOMAIN
Moshpit names failed for the same reason clearnet ones did. Resolving a name
needs a live registry query, and the registry was the thing being swallowed.
It took the rest of the ccTLD with it. On a machine running the bridge as its
resolver, real `.sh` sites answered a Moshpit parking IP.
The static RESERVED_TLDS list was meant to cover this. It named com, net, org,
edu, mil, int and arpa. There are 1438 delegated TLDs.
So both halves are closed:
- the registry refuses to sell an ending IANA already delegates, on both the
single and bulk registration paths, and refuses it even for callers passing
`allowReserved` — reserving `.bank` is policy and policy has exceptions,
answering for `.sh` is a machine that has lost part of the internet
- the bridge refuses to answer for one whatever the registry says it sold
Neither is sufficient alone, and the second is the one that helps anyone today:
622 colliding endings are already registered across 14 owners, and a person
running a bridge should not have to wait for that to be cleaned up before their
resolver works. `isOurs` is now the last word rather than the ending list.
The list is vendored, not fetched at run time. A registry that phoned IANA on
every claim would sell `.sh` the moment IANA had a bad minute, and a resolver
that did it per query would depend on the very thing it exists to avoid needing.
`scripts/generate-iana-tlds.mjs` regenerates it; the two copies exist because
`src/` ships to npm and `apps/pwa/` deploys as the Pit and is not a workspace,
and a test fails if they drift.
Verified against a live bridge holding all 18224 endings including `sh`:
pit.moshcode.sh now answers 69.46.46.24 where it used to NXDOMAIN, moshcode.sh
answers its real 69.46.46.31, blue.eggs and alt.2600 are unchanged, and
moshcoding.sh correctly returns nothing because it genuinely does not exist —
rather than a parking IP claiming it does.
One existing test asserted `tldRejection("ai")` was null. `.ai` is Anguilla's
ccTLD; the expectation encoded the bug. Rewritten to test the length rule with
an ending that is only about length.
Not included: deleting the 622 endings already sold. The guards above make them
harmless without it, and removing paid claims across 14 owners is a decision to
take deliberately rather than as a side effect of a bug fix.
Suite: 2726 tests, 0 failures.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ThnQwoieWt8VR6N7gtgnhp
ThreatCrush Security Scan40 finding(s) in the 8 file(s) this pull request changes. HIGH/CRITICAL: 1 | MEDIUM: 39
48 pre-existing finding(s) elsewhere in the repository — **HIGH/CRITICAL**: 4 | **MEDIUM**: 34 | **LOW**: 10Not introduced by this pull request. The full set is in the Security tab.
…and 28 more. Full results in the Security tab. Snippets are redacted; ThreatCrush never prints matched credential material. |
Merged
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
.shwas sold for $2 and took the registry off the air.shwas claimed through the ordinary registration flow by someone who isn't us. It's Saint Helena's ccTLD. It's also where this project's registry lives:pit.moshcode.sh.Every bridge that fetched the ending list learned to treat the registry as a Moshpit name — stopped forwarding it, and tried to resolve it through the registry it had just made unreachable. A resolver that can't resolve the thing it needs in order to resolve anything.
Observed on an affected desktop: bridge running, listening, correctly routed to, answering NXDOMAIN to the entire internet.
Moshpit names failed for the same reason clearnet ones did — resolving a name needs a live registry query, and the registry was what was being swallowed. It took the rest of the ccTLD with it: real
.shsites answered a Moshpit parking IP.RESERVED_TLDSwas meant to cover this. It namedcom,net,org,edu,mil,int,arpa. There are 1438 delegated TLDs.Both halves
tldRejection), and even for callers passingallowReserved. Reserving.bankis policy and policy has exceptions; answering for.shis a machine that has lost part of the internet.isOursis now the last word rather than the ending list.Neither is sufficient alone, and the second is the one that helps anyone today — 622 colliding endings are already registered across 14 owners, and nobody should have to wait for that cleanup before their resolver works.
The list is vendored, not fetched at runtime: a registry that phoned IANA per claim would sell
.shthe moment IANA had a bad minute, and a resolver doing it per query would depend on the very thing it exists to avoid needing.scripts/generate-iana-tlds.mjsregenerates it. Two copies, becausesrc/ships to npm andapps/pwa/deploys as the Pit and isn't a workspace — a test fails if they drift.Verified live
Against a real bridge holding all 18224 endings including
sh:pit.moshcode.shmoshcode.shmoshcoding.sh69.46.46.103(fake parking IP)blue.eggsalt.2600example.comOne test premise was wrong, not the code
tldRejection("ai")was asserted to benull..aiis Anguilla's ccTLD — the expectation encoded the bug. Rewritten to test the length rule with an ending that's only about length.Suite: 2726 tests, 0 failures, 334 skipped (the usual
apps/pwaguards).Not included
Deleting the 622 endings already sold. The guards make them harmless without it, and removing paid claims across 14 owners — 334 of them the project owner's own — is a decision to take deliberately, not as a side effect of a bug fix.
🤖 Generated with Claude Code
https://claude.ai/code/session_01ThnQwoieWt8VR6N7gtgnhp