Deriving Nix Build Inputs
The English user guide is currently in beta preview. Most of the documents have been automatically translated from the Japanese version. Should you find any inaccuracies, please reach out to Flatt Security.
Each image's build inputs can be derived mechanically from the Nix build graph. This derivation is the common foundation for several different features: SBOM generation, upstream malware detection, and upstream zero-day fix detection.
What is a derivation?
In Nix, every build is declared as a derivation. A derivation has inputs such as other derivations, sources, and build scripts, and those inputs are fixed by hashes. The property that the same inputs produce the same output comes directly from this declaration model.
An image is itself a derivation. If you follow its inputs, the build graph expands into the derivations for libraries it depends on, then the derivations for their sources, and so on. The authoritative record of what entered a build is not a hand-written document; it is the build graph itself.
Anyone can inspect a derivation with nix derivation show.
For example, inspecting the hello package from nixpkgs returns JSON that includes the builder, its arguments, and the derivations it depends on (inputDrvs).
$ nix --extra-experimental-features 'nix-command flakes' \
derivation show 'nixpkgs#legacyPackages.x86_64-linux.hello'
{
"name": "hello-2.12.3",
"system": "x86_64-linux",
"builder": "/nix/store/zh1ijdhb6gng1509b1zrilb6xlzx60j6-bash-5.3p9/bin/bash",
"args": [
"-e",
"/nix/store/l622p70vy8k5sh7y5wizi5f2mic6ynpg-source-stdenv.sh",
"/nix/store/shkw4qm9qcw5sc5n1k5jznc83ny02r39-default-builder.sh"
],
"inputDrvs": [
"9w4h6mwgy4vivksdb54jhz6i2dihqv1l-hello-2.12.3.tar.gz.drv",
"g7p7rs03xah2w00a142hzas9h4fkwpck-bash-5.3p9.drv",
"i1fmvnw4pqbjhcygp8rggs6n88jg1bny-version-check-hook.drv",
"l0x59a9gpwqh6rxxx2sxbl5nd72r4bc8-stdenv-linux.drv"
]
}
The entries in inputDrvs are other derivations this derivation depends on.
Following each of them with nix derivation show eventually reaches derivations that fetch sources.
Those source-fetching derivations are the fixed-output derivations described next.
Fixed-output derivations and network access
In this graph, the only derivations allowed to access the external network are fixed-output derivations (FODs). Normal derivations build inside a sandbox and cannot access inputs that were not declared, including the network and undeclared files. FODs are the exception, but they must declare the content hash of the result in advance. If the fetched result does not match the declared hash, the build fails immediately.
| Aspect | Normal derivation | Fixed-output derivation |
|---|---|---|
| Network access | Not allowed | Allowed |
| Output hash | Determined from the built result | Declared in advance; mismatch fails the build |
| Typical use | Compiling and assembling dependencies | Fetching upstream sources such as tarballs and Git repositories |
Source-fetching functions in nixpkgs, whether they fetch tarballs or Git repositories, ultimately reach FODs. An FOD is the build graph's single controlled window to the outside world.
Mechanical upstream source enumeration
By walking the build graph and extracting only FODs, Takumi Images can derive the full set of external sources that contributed to an image. Each FOD retains the source URL or revision and the declared hash as attributes. There is no need to infer origin by reading image definitions or patch files by hand; evaluating the build graph produces the list. The list includes not only packages inside the image but also sources for build tools.
The resulting data looks like this, shortened to one source.
{
"https://github.com/chainguard-dev/apko.git": {
"fetcher": "git:github.com",
"rev": "refs/tags/v1.2.19",
"hash": "sha256-Iia0U/oibPuUYC3adeXvL5m4nhEPHqBvHw7J7Uxn88s=",
"images": ["apko"]
}
}
Which upstream source, revision, and image impact (images) are all determined mechanically.
When a new upstream commit or release appears, comparing it with this list gives the full set of not-yet-incorporated changes and immediately shows which images are affected.
Comparing against upstream's latest releases or commits shows how far the current pin is from upstream.
Three uses
This list is used in three different areas.
The first use is SBOM generation. The SBOM lists the runtime dependency closure of the built image. Like the FOD list, it is obtained mechanically from the evaluated build graph and accurately represents the running container's contents.
The second use is Upstream Malware Detection. Takumi Images continuously monitors the upstream sources pointed to by the FOD list and looks for signs of malicious changes.
The third use is Upstream Zero-Day Fix Detection. The same monitored sources are analyzed for fixes that have not yet been published as vulnerability IDs.