Skip to content

feat(dns): remint a stale root, and restart the proxy on upgrade - #477

Merged
ralyodio merged 1 commit into
mainfrom
feat/remint-stale-root
Aug 30, 2026
Merged

feat(dns): remint a stale root, and restart the proxy on upgrade#477
ralyodio merged 1 commit into
mainfrom
feat/remint-stale-root

Conversation

@ralyodio

Copy link
Copy Markdown
Contributor

moshcode upgrade then moshcode dns enable was meant to be the whole of it. On a machine that had run the old proxy it wasn't, and both reasons were invisible.

The stale root

moshpit-proxy used to constrain its root by naming the endings it could certify, and it will not replace a root that already exists. So an upgraded machine keeps the narrow root — it works for endings someone once configured and fails for everything else, which is exactly why .2600 reached HTTPS while .hacker didn't.

Nothing reported it, because from every angle the setup looked complete: proxy installed, service running, names resolving.

dns enable now reads the root before starting the proxy and removes it when it carries a permitted DNS subtree — the tell, since the root minted today has none (it excludes the real internet instead of enumerating Moshpit). The proxy mints the current shape on next start, and dns enable installs it into the trust stores in the same run.

That's why this lives here and not in the installer: removing a root without re-trusting is the destructive half on its own.

An unreadable root is left alone — throwing one away because openssl was missing would break a working machine to fix a problem it didn't have.

The unit that never restarted

systemctl enable --now starts a stopped unit and does nothing to a running one. An upgrade left the previous process alive — previous root, previous namespace — and reported success. It enables and restarts now.

Ordering

The remint moved ahead of writing the unit file. The root's shape has nothing to do with whether /etc is writable, and sequencing it behind that meant a machine that couldn't write the unit silently kept its stale root too.

Tests

Six. The detector against a root naming endings, one excluding the internet, no root, and an unreadable one. The lifecycle for issuing a restart rather than only an enable, and for reminting before touching anything else. proxyServicePaths is injectable so none of it writes to /etc.

Suite: 2760 tests, 0 failures.

Effect

rm -rf ~/.moshpit/ca stops being something anyone has to know about. Upgrading is moshcode upgrade then moshcode dns enable.

🤖 Generated with Claude Code

https://claude.ai/code/session_01ThnQwoieWt8VR6N7gtgnhp

`moshcode upgrade` followed by `moshcode dns enable` was supposed to be the
whole of it. On a machine that had run the old proxy it was not, and the two
reasons were invisible.

moshpit-proxy used to constrain its root by naming the endings it could
certify, and it will not replace a root that already exists. So an upgraded
machine kept the narrow root: it works for the endings someone had once
configured and fails for everything else, which is why `.2600` could reach
HTTPS while `.hacker` could not. Nothing reported it, because from every angle
the setup looked complete — proxy installed, service running, names resolving.

`dns enable` now reads the root before starting the proxy, and removes it when
it carries a permitted DNS subtree. That is the tell: the root minted today has
none, because it excludes the real internet instead of enumerating Moshpit. The
proxy mints the current shape on its next start and `dns enable` installs it
into the trust stores in the same run — which is why this belongs here and not
in the installer, where removing a root would be the destructive half on its
own.

An unreadable root is left alone. Throwing one away because openssl was missing
would break a working machine to fix a problem it did not have.

The second reason: `systemctl enable --now` starts a stopped unit and does
nothing at all to a running one. An upgrade therefore left the previous process
alive, still serving the previous root under the previous namespace, and
reported success. It enables and restarts now, which is what makes an upgrade
take effect.

The remint also moved ahead of writing the unit file. The root's shape has
nothing to do with whether /etc is writable, and sequencing it behind that meant
a machine that could not write the unit silently kept its stale root too.

Six tests. The detector is checked against a root naming endings, a root
excluding the internet, no root, and an unreadable one; the lifecycle is checked
for issuing a restart rather than only an enable, and for reminting before it
touches anything else. `proxyServicePaths` is injectable so none of that writes
to /etc.

Suite: 2760 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

0 finding(s) in the 2 file(s) this pull request changes.

Nothing in the files this pull request changes.

91 pre-existing finding(s) elsewhere in the repository — **HIGH/CRITICAL**: 8 | **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
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 71 more. Full results in the Security tab.

Snippets are redacted; ThreatCrush never prints matched credential material.

@ralyodio
ralyodio merged commit 7f81909 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