Ariadne 0.1.4: sweep stale BNS root CAs so browsers stop failing after upgrades

Symptom: on any machine that had been through a series of installs, one or
more older "BNS Local Root CA" certs from earlier builds could accumulate in
LocalMachine\Root -- an unconstrained root from before 2026-07, or a rotated
one -- and every install added the current constrained root ALONGSIDE the
stale ones. Two certs with the same Subject-DN defeat browser chain-builders:
Chromium/Edge/Firefox pick one candidate and refuse to try the others, so
every .bch site failed with ERR_CERT_AUTHORITY_INVALID / SEC_ERROR_BAD_SIGNATURE
in every browser EXCEPT Theseus (which trusts the on-chain tls fingerprint
directly, not the machine store).

Reproduced on the dev box: two BNS Local Root CAs present (thumbprints
EB5DBE98... constrained + 23538FD7... unconstrained), DNS answered correctly,
strict Invoke-WebRequest to https://coinspectrum.bch/ failed. Removing the
stale one and re-running the chain-build restored HTTPS 200.

Fix (install.ps1):
- Before Add(imported), enumerate the store and $store.Remove() every
  "BNS Local Root CA" whose thumbprint differs from the one we're about
  to trust. Post-condition: exactly one BNS root remains after install.

Fix (uninstall.ps1):
- Switched from `Get-ChildItem Cert:\LocalMachine\Root` to X509Store direct.
  The Cert: PSDrive is not always loaded in Inno's [UninstallRun] -NoProfile
  context, so uninstall could silently leave the CA behind on the store side
  even while it removed everything else.

Verified end-to-end on this box: 0.1.4 upgrade over 0.1.3 finished cleanly,
BNS Resolver Daemon Running, 127.0.0.1:53 open, exactly one BNS Local Root
CA in the machine store, strict HTTPS to https://coinspectrum.bch/ returned
200 (506,997 bytes) with X509Chain.Build ok=true leaf -> BNS root.

Deployed
- dl.silentmode.st/AriadneResolver-Setup-0.1.4.exe
- s3://bns/silentmode/dl/AriadneResolver-Setup-0.1.4.exe
- silentmode.st manifest advertises 0.1.4
- sha256 30ed5e3bb6d6da5325f854c97976410b4fc63067ed52c810a55e9d2e1bdc4e17
This commit is contained in:
Local Dev 2026-09-27 22:04:00 +02:00
parent c791c3e3d2
commit 5c9fd6ca2f
2 changed files with 8 additions and 8 deletions

View file

@ -22,14 +22,14 @@
{
"id": "ariadne-resolver",
"product": "Ariadne Resolver (Windows)",
"version": "0.1.3",
"date": "2026-09-19",
"version": "0.1.4",
"date": "2026-09-27",
"platform": "win-x64",
"signed": false,
"signingAuthority": null,
"changes": "Resolver library brought level with the desktop reader: per-TLD certificate registry read from the TLD beacon, current NFT owner tracked per name, the port-443 electrum route tried first, and the TLD co-sign rule (a registration under a \"cosign\" or hidden TLD is only recognised when it carries the TLD's certificate). Same daemon, same install; existing installs upgrade in place.",
"changes": "Fixes \"resolver is installed and DNS answers, but every .bch site fails in every browser except Theseus\": if the machine had a stale \"BNS Local Root CA\" left over from an earlier install (e.g. an unconstrained root from before 2026-07), the new install used to add its own root alongside instead of replacing it, and Chromium/Edge/Firefox chain-builders would refuse to try both candidates. install.ps1 now sweeps every prior BNS root whose thumbprint differs from the one being trusted, so exactly one BNS Local Root CA remains after install. uninstall.ps1 switched to X509Store direct (Cert: PSDrive is not always loaded in Inno's UninstallRun context). Same daemon, same NRPT, upgrades in place.",
"files": {
"AriadneResolver-Setup-0.1.3.exe": "79b920b8e4e92aa9a54653035a4873dd996b5d4a9093c43d114e0a3ee4ffb003"
"AriadneResolver-Setup-0.1.4.exe": "30ed5e3bb6d6da5325f854c97976410b4fc63067ed52c810a55e9d2e1bdc4e17"
}
},
{

View file

@ -72,12 +72,12 @@
</div>
<div class="rel">
<h2>Ariadne Resolver — Windows <span style="color:var(--acid)">0.1.3</span></h2>
<div class="meta">Windows 64-bit · unsigned · bundled Node runtime · 2026-09-19 · <b>Same rules as every other client</b> — Resolver library brought level with the desktop reader: per-TLD certificate registry read from the TLD beacon, current NFT owner tracked per name, the port-443 electrum route tried first, and the TLD co-sign rule (a registration under a "cosign" or hidden TLD is only recognised when it carries the TLD's certificate). Same daemon, same install; existing installs upgrade in place.</div>
<h2>Ariadne Resolver — Windows <span style="color:var(--acid)">0.1.4</span></h2>
<div class="meta">Windows 64-bit · unsigned · bundled Node runtime · 2026-09-27 · <b>Stale-root sweep</b> — fixes the "resolver is installed, DNS answers, but every .bch site fails in every browser except Theseus" state. If the machine had a stale <code style="display:inline">BNS Local Root CA</code> left over from an earlier install (an unconstrained root from before 2026-07, or a rotated one), the new install used to add its own root alongside instead of replacing it, and Chromium/Edge/Firefox chain-builders would refuse to try both candidates and fail with <code style="display:inline">ERR_CERT_AUTHORITY_INVALID</code> / <code style="display:inline">SEC_ERROR_BAD_SIGNATURE</code>. install.ps1 now sweeps every prior BNS root whose thumbprint differs from the one being trusted, so exactly one <code style="display:inline">BNS Local Root CA</code> remains after install. uninstall.ps1 switched to <code style="display:inline">X509Store</code> direct (the <code style="display:inline">Cert:</code> PSDrive is not always loaded in Inno's <code style="display:inline">UninstallRun</code> context). Same daemon, same NRPT rules, upgrades in place.</div>
<div class="file">
<div class="n"><a href="https://dl.silentmode.st/AriadneResolver-Setup-0.1.3.exe">AriadneResolver-Setup-0.1.3.exe</a> — ~24 MB</div>
<code>79b920b8e4e92aa9a54653035a4873dd996b5d4a9093c43d114e0a3ee4ffb003</code>
<div class="n"><a href="https://dl.silentmode.st/AriadneResolver-Setup-0.1.4.exe">AriadneResolver-Setup-0.1.4.exe</a> — ~24 MB</div>
<code>30ed5e3bb6d6da5325f854c97976410b4fc63067ed52c810a55e9d2e1bdc4e17</code>
</div>
</div>