One Source Tree, Two Builds, Two Answers: What the 90-Second Video Shows
On 27 October we published a short video of bomwerk 1.0.0-rc.2 running against nightmare, our open test repository. It lasts about a minute: https://youtu.be/_T6Wko0zadw
This post explains the part that goes by fastest. What observe and trim do, and why the answer changes between two builds of the same files.
The problem in one repository
Most SBOM (Software Bill of Materials) tools answer one question: what does this repository declare or contain? For a C project, that is everything in the tree. But a tree is not a product. A CMake preset can switch a library on or off, and two presets give two different binaries from identical files.
nightmare has two presets, config-a and config-b. It also vendors zlib 1.2.11, a version with known CVEs. (A CVE, short for Common Vulnerabilities and Exposures, is a public ID for one specific flaw.) So: does zlib 1.2.11 ship? That depends on the preset.
How it asks the build
observe wraps your build command and records what the compiler and linker touched. trim compares that record against an SBOM from scan. This is the sequence from the README:
bomwerk scan . -o sbom.cdx.json
bomwerk observe --trace config-a.jsonl -- cmake --preset config-a
bomwerk observe --trace config-a.jsonl -- cmake --build build/config-a
bomwerk trim sbom.cdx.json --trace config-a.jsonl --root . \
-o sbom-trim-config-a.json
Repeat the last three commands with config-b and its own trace. Both the configure step and the build step run under observe, because configuring records which compiler the build will use.
What came out
This is the committed result in nightmare's docs/RESULTS.md, generated with rc.2:
| component | config-a | config-b |
|---|---|---|
| cjson-prebuilt | used (1 link input) | UNUSED |
| freertos V11.1.0 | UNUSED | used (1 source) |
| sqlite3 3.41.2 | used (1 link input) | UNUSED |
| stb | UNUSED | UNUSED |
| uthash | used (headers only) | UNUSED |
| zlib 1.2.11 | used (10 sources) | UNUSED |
| openssl | UNUSED | UNUSED |
Seven components could be judged. Four are used in A and one in B. zlib is compiled from ten source files in A. In B, it sits in the tree and never reaches the binary.
So an advisory for zlib 1.2.11 is a real question for the A release. For B, the answer is that the build never compiled it. A static scan lists zlib in both and cannot tell them apart.
stb is in the tree and unused in both. OpenSSL is unused in both because building it is opt-in.
What this does not tell you
- Used is not exploitable.
trimsays the code was compiled, linked or included. It does not say the vulnerable function can be reached. - One synthetic repo. nightmare is built to be awkward, and I wrote its answer key by hand. On it, bomwerk finds 10 of 12 ground-truth components and over-reports 2.
- Declared-only components are skipped. Conan, vcpkg and npm entries have no place in the tree, so
trimdoes not judge them. - Toolchains.
observesupports GCC and Clang on Linux and macOS today. - Release state. rc.2 is a release candidate built from source. There are no prebuilt or signed binaries yet.
Why a manufacturer cares
Since 11 September 2026, the EU Cyber Resilience Act (CRA) asks manufacturers for an early warning within 24 hours once they learn that a vulnerability in their product is being actively exploited. The first thing you look up then is whether the component is in the release you shipped. If your SBOM lists only what each build used, that is a lookup. If it lists the whole tree, you start a discussion. Whether a given case needs a report is a legal call for you and your counsel.
How the video was made
I did not want a demo you cannot check. The terminal is a real recording from a source build of the release candidate. The edit crops window chrome, cuts between shots, speeds up builds and holds a last frame. It never retypes or redraws terminal text. A small script types each command so there are no typos, but the output is whatever the binary printed. The narration is a synthetic voice. The video description lists what is not shown.
You can also skip the video. Clone nightmare and run python3 tools/compare_tools.py --bomwerk /path/to/bomwerk --write. It rebuilds the comparison from pinned tool versions.
Free repo scan: bomwerk.com
Not sure what your current SBOM is missing? We'll assess one repository across its supported ecosystems, explain the evidence gaps, and go deeper on C/C++ where the build context allows.
Get a free scan of one repo