Skip to content

fix(dns): a proxy this run started is a proxy it can trust - #481

Merged
ralyodio merged 1 commit into
mainfrom
fix/trust-the-proxy-we-started
Aug 31, 2026
Merged

fix(dns): a proxy this run started is a proxy it can trust#481
ralyodio merged 1 commit into
mainfrom
fix/trust-the-proxy-we-started

Conversation

@ralyodio

Copy link
Copy Markdown
Contributor

Proxy detection asked the proxy for a certificate under a.<ending>. The proxy will not present one for a name with no key published in the registry — deliberately, so a browser gets a TLS failure it can explain rather than a reset mid-request. And dns enable cannot invent a name somebody registered: the registry lists endings, not names. a.<ending> is the best it could construct, and that's exactly the shape the proxy refuses.

So the check could not pass on a correctly configured machine. Three lines apart, both true as written:

ok   proxy holds 127.0.0.1:443
--   no pinned-TLS proxy on this machine

The bridge was then started without proxy mode, so every Moshpit name answered its origin and a stock client got a certificate no CA had signed — on a machine that had, in the same run, installed the proxy, started it, watched it take the port, and installed the local root into the system trust store.

v0.88.0 made the probe name parseable, which moved the failure from ERR_INVALID_URL to ERR_TLS_CERT_ALTNAME_INVALID and no further. A name that parses is still a name with no pin.

The probe was the wrong instrument

It exists for a proxy that something else installed, where the question is genuinely open. That isn't the question here: this run wrote the unit, restarted it, and confirmed the port held. That's stronger evidence of whose proxy it is than any handshake.

So that's used, and the probe is kept for the case it was written for.

Tests

Three, driving dns enable itself rather than the helper:

  • a proxy this run started turns proxy mode on — and the bridge is asserted to have actually been told (proxy: "127.0.0.1"), without which names still answer their origin
  • a proxy it did not start is still probed
  • no proxy at all still brings DNS up, because an optional component must never cost a machine its resolver

Suite: 2768 tests, 0 failures.

Known, not fixed here

A bridge that is already running keeps the mode it started with. On a machine where one is up, this takes effect on the next restart of the bridge rather than immediately.

🤖 Generated with Claude Code

https://claude.ai/code/session_01ThnQwoieWt8VR6N7gtgnhp

Proxy detection asked the proxy for a certificate under `a.<ending>`, and the
proxy will not present one for a name with no key published in the registry.
That refusal is deliberate — it produces a TLS failure a browser can explain
rather than a reset mid-request — and `dns enable` has no way to invent a name
somebody has registered, because the registry lists endings and not names.
`a.<ending>` is the best it could construct, and that is precisely the shape the
proxy refuses.

So the check could not pass on a correctly configured machine. Three lines
apart, both true as written:

    ok   proxy holds 127.0.0.1:443
    --   no pinned-TLS proxy on this machine

The bridge was then started without proxy mode, so every Moshpit name answered
its origin directly and a stock client got a certificate no CA had signed — on a
machine that had, in the same run, installed the proxy, started it, watched it
take the port, and installed the local root into the system trust store.

v0.88.0 made the probe name parseable, which moved the failure from
ERR_INVALID_URL to ERR_TLS_CERT_ALTNAME_INVALID and no further: a name that
parses is still a name with no pin.

The probe was the wrong instrument. It exists for a proxy that something else
installed, where the question is genuinely open. It is not the question here:
this run wrote the unit, restarted it, and confirmed the port held. That is
stronger evidence of whose proxy it is than any handshake, so it is used, and
the probe is kept for the case it was written for.

Three tests, driving `dns enable` rather than the helper: a proxy this run
started turns proxy mode on and the bridge is checked to have actually been told
(`proxy: "127.0.0.1"` — without that names still answer their origin); a proxy
it did not start is still probed; and no proxy at all still brings DNS up,
because an optional component must never cost a machine its resolver.

Suite: 2768 tests, 0 failures.

Known and not fixed here: a bridge that is already running keeps the mode it
started with, so on a machine where one is up this takes effect on the next
restart of it rather than immediately.

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 2 file(s) this pull request changes.

HIGH/CRITICAL: 1

Severity Rule Location
HIGH tls-verification-disabled src/dns.mjs:766
90 pre-existing finding(s) elsewhere in the repository — **HIGH/CRITICAL**: 7 | **MEDIUM**: 73 | **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
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
MEDIUM sql-template-interpolation apps/pwa/src/moshpit.mjs:1147

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

Snippets are redacted; ThreatCrush never prints matched credential material.

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