Skip to content

hollow v1.0.0

Choose a tag to compare

@DevInIndia DevInIndia released this 30 Aug 18:05
· 5 commits to main since this release
build: publish four targets, and let a container check the hash

One published hash covered one platform, and the download most people would
reach for was the one nobody could verify. make release now cross-compiles the
same four targets the verify gate already builds, from one TARGETS list so that
a target which ships is a target known to compile, and writes dist/SHA256SUMS
with bare filenames so sha256sum -c works where a downloader unpacks. README
carries all four rows and says outright that only linux/amd64 is gated, because
three unverifiable hashes presented as checked would undo the point of the one
that is.

The hash gate needed hardening before that table could exist. It took the first
64-hex string in README.md, which was correct while exactly one hash was
published and would have become a silent trap the moment the rows were
reordered: the build would have been compared against another platform's hash
and failed with nothing to suggest why. It now finds the hash by the platform
named beside it.

The Dockerfile is a second build path and turned out to be a second check. It is
multi-stage, ending at scratch, one layer and 5.11 MB, and its builder is pinned
to golang:1.25.0 rather than golang:1.25 because the floating tag was go1.25.14
and produced a different binary. That is the correct result and the reason for
the pin, and with it the binary inside the image is byte identical to the
published linux/amd64 hash, verified by copying it out. Three absences are
deliberate and each is commented: no CA bundle, since DNS over UDP and TCP
carries no TLS and trust comes from the root hints; no /etc/resolv.conf, since
hollow walks from the root rather than asking the host; and no go mod download,
which is the first line of nearly every Go Dockerfile and has nothing to do
here. It runs as uid 65534, which port 15353 rather than 53 is what allows, and
CMD binds 0.0.0.0 because inside a container loopback is the container's own and
a published port would reach nothing.

Tested rather than shipped on faith: built, run with -p, and answered both a UDP
and a TCP dig by walking from the root as an unprivileged user in an image with
no shell and no resolver configuration.

dist/ joins /build/ in .gitignore, and .dockerignore keeps the planning notes,
the release binaries and .git out of the build context that one COPY would
otherwise sweep in.

Two Honest Limitations had gone stale and are corrected here rather than left to
be found by a judge. One said reload belongs on a control socket "which is not
built"; the socket has been built for two commits, and the accurate statement is
that it deliberately carries no command that changes what the server is doing,
which is what makes an unauthenticated loopback port defensible. The other said
there is no rate limiting, three bullets above the one describing the rate
limiter.

make verify is green, including the gate reading the new table.