Skip to content

fix(trust): accept a root that excludes the internet instead of listing Moshpit - #474

Merged
ralyodio merged 1 commit into
mainfrom
fix/trust-exclusion-root
Aug 30, 2026
Merged

fix(trust): accept a root that excludes the internet instead of listing Moshpit#474
ralyodio merged 1 commit into
mainfrom
fix/trust-exclusion-root

Conversation

@ralyodio

Copy link
Copy Markdown
Contributor

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 .2600 over 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:

root verdict
minted by the new proxy accepted — "excludes all 1438 real top-level domains"
no name constraints at all refused
excludes only .com and .net refused — "excludes only 2"

A 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_TLDS into 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

…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
@github-actions

Copy link
Copy Markdown

ThreatCrush Security Scan

1 finding(s) in the 4 file(s) this pull request changes.

MEDIUM: 1

Severity Rule Location
MEDIUM insecure-temp-file test/trust.test.mjs:284
90 pre-existing finding(s) elsewhere in the repository — **HIGH/CRITICAL**: 8 | **MEDIUM**: 72 | **LOW**: 10

Not introduced by this pull request. The full set is in the Security tab.

Severity Rule Location
HIGH js-ssrf-outbound-request apps/pwa/public/sw.js:45
HIGH tls-verification-disabled apps/pwa/src/lib/moshpit-gateway.mjs:299
HIGH sh-remote-script-execution install.sh:86
HIGH sh-remote-script-execution install.sh:90
HIGH sh-remote-script-execution install.sh:202
HIGH sh-remote-script-execution install.sh:213
HIGH sh-remote-script-execution install.sh:219
HIGH tls-verification-disabled src/dns.mjs:766
MEDIUM sql-template-interpolation apps/pwa/src/moshpit.mjs:139
MEDIUM sql-template-interpolation apps/pwa/src/moshpit.mjs:153
MEDIUM sql-template-interpolation apps/pwa/src/moshpit.mjs:179
MEDIUM sql-template-interpolation apps/pwa/src/moshpit.mjs:373
MEDIUM sql-template-interpolation apps/pwa/src/moshpit.mjs:377
MEDIUM sql-template-interpolation apps/pwa/src/moshpit.mjs:422
MEDIUM sql-template-interpolation apps/pwa/src/moshpit.mjs:671
MEDIUM sql-template-interpolation apps/pwa/src/moshpit.mjs:867
MEDIUM sql-template-interpolation apps/pwa/src/moshpit.mjs:869
MEDIUM sql-template-interpolation apps/pwa/src/moshpit.mjs:928
MEDIUM sql-template-interpolation apps/pwa/src/moshpit.mjs:974
MEDIUM sql-template-interpolation apps/pwa/src/moshpit.mjs:1044

…and 70 more. Full results in the Security tab.

Snippets are redacted; ThreatCrush never prints matched credential material.

@ralyodio
ralyodio merged commit efa83e0 into main Aug 30, 2026
6 checks passed
@ralyodio ralyodio mentioned this pull request Aug 30, 2026
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