fix(origin): issue leaves as CA:FALSE, and trust them on the box that serves them - #18
Merged
Merged
Conversation
… serves them `openssl req -x509` defaults to basicConstraints=CA:TRUE, and setup-origin.sh never overrode it. Every origin this script has ever created is therefore serving a certificate that is marked as a certificate authority. That matters because this certificate is meant to be trusted *directly* — it is its own anchor, which is the whole point of a pinned self-signed origin. An anchor marked CA:TRUE may issue for any name in the world. The SAN bounds what the certificate speaks for; it does not bound what a key trusted as an authority may go on to sign. So trusting one of these to reach `chovy.hacker` also hands its holder google.com. CA:FALSE with a single-name SAN is the shape that makes direct trust a bounded grant. Re-running fixes an already-published certificate for free: the key is reused and the pin is over the key, so the registry needs no update and no client holding the old pin breaks. Also here: - `--all` re-issues every name the box already has a key for, so repairing a fleet is one command with nothing to type and mistype. - the certificate is trusted on this machine once it is issued. The machine serving a Moshpit name is usually one somebody browses it from, and until now `curl https://<name>` failed to verify there. The pinned-TLS proxy cannot fix that case: it works by owning 443 on loopback, and on an origin nginx already has 443 — a second bind gets EADDRINUSE. Trusting the leaf needs no port. - a name is checked against a hostname charset before it becomes a path under /etc/ssl, /etc/nginx and /usr/local/share/ca-certificates, as root. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
vu1nz Security Review0 finding(s) in PR #? No security issues found. |
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.
The bug
openssl req -x509defaults tobasicConstraints=CA:TRUE, andsetup-origin.shnever overrode it. Every origin this script has ever created serves a certificate marked as a certificate authority. On the dev box, all three do:This certificate is meant to be trusted directly — it is its own anchor, which is the point of a pinned self-signed origin. An anchor marked CA:TRUE may issue for any name. The SAN bounds what the certificate speaks for; it does not bound what a key trusted as an authority may go on to sign. Trusting one of these to reach
chovy.hackeralso hands its holdergoogle.com.The fix
CA:FALSE+ single-name SAN +serverAuth. That is the shape where direct trust is a bounded grant — verified in the tests to still work as its own anchor, which is what a stock client needs.Repair is free. The key is reused and the pin is over the key, so re-issuing leaves the published pin untouched: no registry update, no flag day, no client holding the old pin breaks.
Also here
--allre-issues every name the box already has a key for, so repairing a fleet is one command with nothing to type and mistype.curl https://<name>failed to verify on the origin itself. The pinned-TLS proxy cannot fix that case — it works by owning 443 on loopback, and on an origin nginx already has 443; a second bind getsEADDRINUSE. Trusting the leaf needs no port. Guarded: it re-reads the file and refuses anything that is not CA:FALSE./etc/ssl,/etc/nginxand/usr/local/share/ca-certificates, as root. It is now checked against a hostname charset first.Tests
tests/setup-origin.test.ts, 8 new. The extension flags are read out of the script rather than restated, so a test cannot pass while the script mints something else — which is exactly the failure mode being guarded against. Full suite 69/69.🤖 Generated with Claude Code