feat(builder): add cargo-auditable to the builder image#97
Merged
Conversation
Release SBOMs currently list only the top-level package because the Rust binaries carry no dependency manifest: syft scans the built artifacts and finds nothing to catalog beyond the package record itself. Install cargo-auditable and a small wrapper so a follow-up goreleaser change can build via `cargo auditable`, embedding each binary's dependency tree in a `.dep-v0` ELF section. syft (>= 1.15; the image ships 1.46) reads that section and emits SBOMs that list every linked crate. cargo-auditable only activates when invoked as `cargo auditable <cmd>` (it inspects argv[1] and refuses otherwise), so goreleaser's Rust `tool:` cannot point at the binary directly; the wrapper restores that invocation while passing through `zigbuild --target=... --release` as usual. This change is additive — nothing references the wrapper yet. Wiring it into build/.goreleaser.yaml and bumping build/Dockerfile's pinned image follow in a separate PR once this image is published. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
ben-miru
added a commit
that referenced
this pull request
Jun 29, 2026
## Why Release SBOMs list **only the top-level package** — no dependency inventory — making them useless for vulnerability scanning. Follow-up to #97, which added `cargo-auditable` + a wrapper to the builder image. This PR wires it into the release and fixes what syft scans. ## What - **`builds.agent.tool: cargo-auditable-zigbuild`** — the wrapper baked into the builder image (#97). With `command: zigbuild`, goreleaser runs `cargo-auditable-zigbuild zigbuild --target=… --release -p=miru-agent`, i.e. `cargo auditable zigbuild …`. Each binary then embeds its full dependency tree in a `.dep-v0` ELF section. - **`sboms`: scan `binary` + `archive`, not `package`.** syft reads the `.dep-v0` section straight out of the binary, and recurses into the tar.gz to find it — both list every linked crate. A `.deb` scan only reads DPKG control metadata and **never inspects the nested binary**, so it could never enumerate dependencies. - **`build/Dockerfile`**: bump the pinned builder image to `43e2c5b` — the image published after #97 merged (verified to contain `cargo-auditable` and the wrapper). ## Why drop the `.deb` SBOM I tested this empirically in the builder image. syft scanning an auditable binary inside a `.deb` returns only the package record (2 entries, no crates); the same binary scanned directly, or inside a tar.gz, returns the full crate list. So the SBOM source has to be the binary/archive. The published SBOMs now cover the binaries (the exact bits shipped inside both the archives and the `.deb`s) and the archives. > [!NOTE] > If a downstream consumer specifically needs a `*.deb`-named SBOM file, say so and I'll keep a `package` entry but repoint its syft invocation at the binary instead of dropping it. ## Validation - `goreleaser check` passes against the new pinned image (`43e2c5b`). - Confirmed the published `agent-builder:43e2c5b` image contains `cargo-auditable` and the wrapper. - End-to-end in that image: the wrapper, invoked exactly as goreleaser assembles it (`cargo-auditable-zigbuild zigbuild --target=… --release`), produces a binary with a `.dep-v0` section, and syft surfaces the embedded crate (`itoa`) from both the raw binary and a tar.gz of it — but not from a `.deb`. The first real release tag after this merges will be the live confirmation; the SBOM that previously showed one package should then list the agent's crates. 🤖 Generated with [Claude Code](https://claude.com/claude-code) <!-- codesmith:footer --> --- <a href="https://app.blacksmith.sh/mirurobotics/codesmith/agent/pr/98"><picture><source media="(prefers-color-scheme: dark)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-dark-v2.svg"><source media="(prefers-color-scheme: light)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-light-v2.svg"><img alt="View with Codesmith" src="https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-dark-v2.svg"></picture></a> <a href="https://backend.blacksmith.sh/track/enable-autofix?expires=1785354982&installation_id=142588636&pr_number=98&repository=mirurobotics%2Fagent&return_to=https%3A%2F%2Fgithub.com%2Fmirurobotics%2Fagent%2Fpull%2F98&signature=6601d178f8c208525372bf77f2f00363ff7065d0575652cd2d2f9bcf39229b7c"><picture><source media="(prefers-color-scheme: dark)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-light.svg"><img alt="Autofix with Codesmith" src="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-dark.svg"></picture></a> <sup>Need help on this PR? Tag <code>/codesmith</code> with what you need. Autofix is disabled.</sup> <!-- codesmith:autofix:disabled --> <!-- /codesmith:footer --> Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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.
Why
Release SBOMs (e.g. for
miru-agent_*.deb) currently list only the top-level package — zero dependency inventory. The cause: the Rust binaries carry no dependency manifest, so when syft scans the built artifacts it finds nothing to catalog beyond the package record itself. An SBOM that lists only the product and none of its dependencies provides no supply-chain value (a vuln scan against it checks nothing about the linked crates).What
Install
cargo-auditablein the builder image, plus a small wrapper script, so a follow-up goreleaser change can build viacargo auditable. That embeds each binary's dependency tree in a.dep-v0ELF section, which syft (≥ 1.15; this image ships 1.46) reads to emit SBOMs listing every linked crate.The wrapper is needed because
cargo-auditableonly activates when invoked ascargo auditable <cmd>— it inspectsargv[1]and refuses to run otherwise — so goreleaser's Rusttool:cannot point at the binary directly. The wrapper restores thecargo auditableinvocation while passing through whatever goreleaser appends (zigbuild --target=… --release -p=miru-agent).Safe to merge on its own
This change is purely additive — nothing references
cargo-auditableor the wrapper yet, so it cannot affect existing builds or releases. Merging publishes a newagent-builderimage (viabuilder.yml).Follow-up (PR 2)
Once this image is published, a second PR will:
build/Dockerfile'sFROM ghcr.io/mirurobotics/agent-builder:<sha>to the new image, andtool: cargo-auditable-zigbuildand switch thesboms:stanza to scan the binary/archive instead of the.deb(syft cannot deep-scan a.deb's nested ELF — confirmed empirically — so the SBOM source must be content syft can read).Validation
Built the new layers on top of the current pinned image and confirmed
cargo-auditableinstalls and the on-PATH wrapper produces a.dep-v0binary via the exactcargo-auditable-zigbuild zigbuild --target=… --releaseinvocation goreleaser will use. Also verified end-to-end that syft surfaces the embedded crates from such a binary (and from a tar.gz of it), while a.debscan does not — which is what drives the PR 2 sbom-source change.🤖 Generated with Claude Code
Need help on this PR? Tag
/codesmithwith what you need. Autofix is disabled.