Hermetic & reproducible builds

Same inputs, same bytes, no network.

Advanced14 min · lesson 8 of 18

A hermetic build is one that runs in isolation with all its inputs declared up front and no access to the network or the ambient host — it cannot fetch a dependency mid-build, read an environment secret, or depend on whatever happens to be installed on the machine. That isolation is what makes a build’s output trustworthy: if the build can reach out to the internet while running, an attacker who controls what it fetches controls what it produces, and your provenance is a lie.

HERMETIC BUILD TO REPRODUCIBLE VERIFY
1Declare & pin inputs
all deps vendored/pinned up front
2Verified fetch phase
pull only the pinned inputs, separate step
3Build hermetic
--network=none, no ambient host, no mid-build fetch
4Verify reproducible
build twice, diff digests: bytes must match
Hermeticity removes attacker-controllable inputs; reproducibility lets anyone confirm the output matches the source, the foundation under higher SLSA levels.
terminal
# the anti-pattern: a build that fetches at build time is not hermetic
# RUN curl https://example.com/install.sh | sh <- attacker-controllable input
# hermetic: all dependencies vendored/pinned, fetched in a separate, verified fetch phase,
# then the build runs with --network=none against only those pinned inputs.

Reproducible builds: same inputs, same bytes

A reproducible build is one where the same source and the same declared inputs always produce the byte-for-byte identical artifact, no matter who builds it or when. This is a powerful verification tool: if two independent builders produce the same bytes from the same source, you have strong evidence the build was not tampered with — nobody injected anything, because the output matches. Achieving it means eliminating sources of non-determinism: embedded timestamps, build paths, random ordering, locale.

terminal
# a common reproducibility fix: pin the timestamp so the build is not "now"
$ export SOURCE_DATE_EPOCH=$(git log -1 --format=%ct) # commit time, deterministic
# plus: sorted file ordering, stripped build paths, no random seeds
# verify: build twice (or on two machines) and diff the digests — they should match

Why the two together matter

Hermetic and reproducible reinforce each other. Hermeticity removes the uncontrolled inputs that make builds forgeable; reproducibility lets anyone independently confirm the output corresponds to the source. Together they turn "trust our build server" into "verify the artifact matches the source, from anywhere" — which is the strongest form of build integrity and the technical foundation under the higher SLSA levels. Tools like Bazel and Nix are built around these properties; even without them, vendoring dependencies and cutting network access at build time gets you most of the way.

A build that curls the internet cannot be trusted
The single most common break in build integrity is a build step that downloads something at build time — a script, a binary, a dependency from an unpinned source. That fetch is an input an attacker can control, and it undermines every guarantee downstream: your signed, high-SLSA artifact faithfully packages whatever the attacker served. Vendor and pin your inputs, fetch them in a verified phase, and run the actual build with no network.