fix(trust): accept a root that excludes the internet instead of listing Moshpit - #474
Merged
Conversation
…ng Moshpit moshpit-proxy now constrains its root by exclusion — nothing permitted, all 1438 real top-level domains excluded — because permitting every Moshpit ending does not scale. There are 18224, a permitted subtree each is roughly 214 KB of name constraints on every handshake, and the list is stale the next time the registry sells one. That is why a machine could reach `.2600` over HTTPS and not `.hacker`: each ending worked only if someone had configured it. This gate refused that root. It required a permitted DNS subtree, and the new shape has none by design, so `dns enable`'s trust step would have refused every root the proxy minted from now on. The difficulty is real rather than cosmetic: "no permitted subtree" is also exactly what an unconstrained root looks like. RFC 5280 4.2.1.10 leaves a name type unrestricted when nothing permits it, which is what makes the new shape cover the whole namespace — and what would make a root with no constraints at all sail through a check that only asked whether a permitted list was absent. So the difference is established rather than assumed, against the same IANA list this tool already refuses to sell endings from (v0.80.0). A root that excludes the internet cannot forge your bank, which is the property the old shape bought by enumeration. Below 1000 excluded TLDs it is not that shape at all — it is an unconstrained root with a few names crossed out, and is refused. Verified against a real root minted by the new proxy: accepted, "excludes all 1438 real top-level domains". Verified against a root with no constraints and one excluding only .com and .net: both still refused. A root minted before a TLD was delegated does not exclude it. Reported as `uncovered` rather than made fatal — refusing there would mean refusing every root on the day IANA adds a name. Also stops writing MOSHPIT_PROXY_TLDS into the generated unit. It was set from the registry's ending list, which would have put a ~150 KB environment variable into a unit file; the proxy now reads unset as "every Moshpit ending", so there is nothing to pass. A test asserts the unit does not grow when handed 18224 endings. Suite: 2747 tests, 0 failures. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01ThnQwoieWt8VR6N7gtgnhp
ThreatCrush Security Scan1 finding(s) in the 4 file(s) this pull request changes. MEDIUM: 1
90 pre-existing finding(s) elsewhere in the repository — **HIGH/CRITICAL**: 8 | **MEDIUM**: 72 | **LOW**: 10Not introduced by this pull request. The full set is in the Security tab.
…and 70 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.
moshpit-proxy now constrains its root by exclusion — nothing permitted, all 1,438 real TLDs excluded — because permitting every Moshpit ending doesn't scale (18,224 endings ≈ 214 KB of constraints on every handshake, stale the next time one is sold). That's why a machine could reach
.2600over HTTPS and not.hacker.This gate refused that root. It required a permitted DNS subtree, and the new shape has none by design — so
dns enable's trust step would refuse every root the proxy now mints.The hard part
"No permitted subtree" is also exactly what an unconstrained root looks like. RFC 5280 §4.2.1.10 leaves a name type unrestricted when nothing permits it — which is what makes the new shape cover the whole namespace, and what would let a root with no constraints sail through a check that only asked whether a permitted list was absent.
So the difference is established, not assumed, against the same IANA list this tool already refuses to sell endings from (v0.80.0). Below 1,000 excluded TLDs it isn't that shape — it's an unconstrained root with a few names crossed out, and is refused.
Verified against real certificates, not fixtures:
.comand.netA root minted before a TLD was delegated doesn't exclude it — reported as
uncovered, not fatal. Refusing there would mean refusing every root the day IANA adds a name.Also
Stops writing
MOSHPIT_PROXY_TLDSinto the generated unit. It was set from the registry's ending list — a ~150 KB environment variable in a unit file. The proxy now reads unset as "every Moshpit ending", so there's nothing to pass. A test asserts the unit doesn't grow when handed 18,224 endings.Suite: 2747 tests, 0 failures.
🤖 Generated with Claude Code
https://claude.ai/code/session_01ThnQwoieWt8VR6N7gtgnhp