From c78209d990a1d163a23404bd5c7b5638a93d6dff Mon Sep 17 00:00:00 2001 From: shashial <10578726+shashial@users.noreply.github.com> Date: Fri, 21 Aug 2026 12:26:16 +0100 Subject: [PATCH 1/6] Build release binaries with cargo auditable to embed dependency data --- .github/workflows/release.yaml | 6 ++++- Makefile | 43 +++++++++++++++++++++++++--------- README.md | 13 ++++++++++ docker/Dockerfile.rbuilder | 5 ++-- docker/Dockerfile.reproducible | 1 + 5 files changed, 54 insertions(+), 14 deletions(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index f4a152475..d9f3f8bc2 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -146,6 +146,10 @@ jobs: if: steps.platform-check.outputs.skip != 'true' && matrix.platform == 'mac' uses: dtolnay/rust-toolchain@stable + - name: Install cargo-auditable (Mac) + if: steps.platform-check.outputs.skip != 'true' && matrix.platform == 'mac' + run: cargo install cargo-auditable@0.7.5 --locked + - name: Build binaries (Mac) if: steps.platform-check.outputs.skip != 'true' && matrix.platform == 'mac' env: @@ -157,7 +161,7 @@ jobs: if [[ -n "$FEATURES" ]]; then FEATURE_FLAG="--features $FEATURES" fi - cargo build --profile ${{ matrix.profile }} $FEATURE_FLAG \ + cargo auditable build --profile ${{ matrix.profile }} $FEATURE_FLAG \ --bin rbuilder \ --bin rbuilder-operator \ --bin tbv-bidding-service \ diff --git a/Makefile b/Makefile index 1df6805a6..5ed6e1cbc 100644 --- a/Makefile +++ b/Makefile @@ -71,21 +71,26 @@ else BUILD_ENV = endif +# The cargo-auditable embedded data is sorted and timestamp-free +.PHONY: install-cargo-auditable +install-cargo-auditable: + @command -v cargo-auditable >/dev/null 2>&1 || cargo install cargo-auditable@0.7.5 --locked + .PHONY: build -build: ## Build (release version) - $(BUILD_ENV) cargo build --features "$(FEATURES) jemalloc-unprefixed" --locked $(if $(BUILD_TARGET),--target $(BUILD_TARGET)) --profile $(BUILD_PROFILE) --workspace +build: install-cargo-auditable ## Build (release version) + $(BUILD_ENV) cargo auditable build --features "$(FEATURES) jemalloc-unprefixed" --locked $(if $(BUILD_TARGET),--target $(BUILD_TARGET)) --profile $(BUILD_PROFILE) --workspace .PHONY: build-bid-scraper -build-bid-scraper: ## Build the bid-scraper binary (release version) - $(BUILD_ENV) cargo build --features "$(FEATURES)" --locked $(if $(BUILD_TARGET),--target $(BUILD_TARGET)) --bin bid-scraper --profile $(BUILD_PROFILE) +build-bid-scraper: install-cargo-auditable ## Build the bid-scraper binary (release version) + $(BUILD_ENV) cargo auditable build --features "$(FEATURES)" --locked $(if $(BUILD_TARGET),--target $(BUILD_TARGET)) --bin bid-scraper --profile $(BUILD_PROFILE) .PHONY: build-rbuilder-operator -build-rbuilder-operator: ## Build the rbuilder-operator binary (release version) - $(BUILD_ENV) cargo build --features "$(FEATURES) jemalloc-unprefixed" --locked $(if $(BUILD_TARGET),--target $(BUILD_TARGET)) --bin rbuilder-operator --profile $(BUILD_PROFILE) +build-rbuilder-operator: install-cargo-auditable ## Build the rbuilder-operator binary (release version) + $(BUILD_ENV) cargo auditable build --features "$(FEATURES) jemalloc-unprefixed" --locked $(if $(BUILD_TARGET),--target $(BUILD_TARGET)) --bin rbuilder-operator --profile $(BUILD_PROFILE) .PHONY: build-rbuilder-rebalancer -build-rbuilder-rebalancer: ## Build the rbuilder-rebalancer binary (release version) - $(BUILD_ENV) cargo build --features "$(FEATURES) jemalloc-unprefixed" --locked $(if $(BUILD_TARGET),--target $(BUILD_TARGET)) --bin rbuilder-rebalancer --profile $(BUILD_PROFILE) +build-rbuilder-rebalancer: install-cargo-auditable ## Build the rbuilder-rebalancer binary (release version) + $(BUILD_ENV) cargo auditable build --features "$(FEATURES) jemalloc-unprefixed" --locked $(if $(BUILD_TARGET),--target $(BUILD_TARGET)) --bin rbuilder-rebalancer --profile $(BUILD_PROFILE) .PHONY: build-dev build-dev: ## Build (debug version) @@ -106,9 +111,10 @@ docker-image-test-relay: ## Build a test relay Docker image ##@ Debian Packages # Define binary paths for smart dependencies -BID_SCRAPER_BIN := target/$(if $(BUILD_TARGET),$(BUILD_TARGET)/)$(BUILD_PROFILE)/bid-scraper -RBUILDER_OPERATOR_BIN := target/$(if $(BUILD_TARGET),$(BUILD_TARGET)/)$(BUILD_PROFILE)/rbuilder-operator -RBUILDER_REBALANCER_BIN := target/$(if $(BUILD_TARGET),$(BUILD_TARGET)/)$(BUILD_PROFILE)/rbuilder-rebalancer +BUILD_OUTPUT_DIR := target/$(if $(BUILD_TARGET),$(BUILD_TARGET)/)$(BUILD_PROFILE) +BID_SCRAPER_BIN := $(BUILD_OUTPUT_DIR)/bid-scraper +RBUILDER_OPERATOR_BIN := $(BUILD_OUTPUT_DIR)/rbuilder-operator +RBUILDER_REBALANCER_BIN := $(BUILD_OUTPUT_DIR)/rbuilder-rebalancer .PHONY: install-cargo-deb install-cargo-deb: @@ -150,6 +156,21 @@ build-deb: build-deb-bid-scraper build-deb-rbuilder-operator build-deb-rbuilder- ##@ Dev +.PHONY: install-cargo-audit +install-cargo-audit: + @command -v cargo-audit >/dev/null 2>&1 || cargo install cargo-audit@0.22.2 --locked + +.PHONY: audit-bin +audit-bin: install-cargo-audit ## Scan built binaries for vulnerable dependencies (uses the audit data embedded by "make build") + @fail=0; \ + for bin in $(BUILD_OUTPUT_DIR)/*; do \ + if [ -f "$$bin" ] && [ -x "$$bin" ]; then \ + echo "==> $$bin"; \ + cargo audit bin "$$bin" || fail=1; \ + fi; \ + done; \ + exit $$fail + .PHONY: lint lint: ## Run the linters cargo fmt -- --check diff --git a/README.md b/README.md index 0291fcc88..803cec1c0 100644 --- a/README.md +++ b/README.md @@ -175,6 +175,19 @@ $ sha256sum target/release/rbuilder d92ac33b94e16ed4a035b9dd52108fe78bd9bb160a91fced8e439f59b84c3207 target/release/rbuilder ``` +### Auditable builds + +Release builds (`make build`, the Docker images, and the released binaries) go through +[`cargo auditable`](https://github.com/rust-secure-code/cargo-auditable), which embeds the full +dependency list into each binary. To scan the built binaries against the RustSec advisory database: + +```bash +make audit-bin +``` + +The embedded data can also be picked up by scanners such as `trivy`, `grype`, `syft`. Meaning that container +images built from these binaries can be scanned for Rust dependencies as well. + --- ## Release Stability and Development Process diff --git a/docker/Dockerfile.rbuilder b/docker/Dockerfile.rbuilder index 81dde36ae..30c92533b 100644 --- a/docker/Dockerfile.rbuilder +++ b/docker/Dockerfile.rbuilder @@ -36,6 +36,7 @@ RUN set -eux; \ rm -rf /tmp/sccache.tar.gz /tmp/sccache-v0.8.2-${ARCH_TAG} RUN cargo install cargo-chef --version ^0.1 +RUN cargo install cargo-auditable@0.7.5 --locked ENV CARGO_HOME=/usr/local/cargo @@ -72,14 +73,14 @@ ARG FEATURES RUN --mount=type=cache,target=/usr/local/cargo/registry \ --mount=type=cache,target=/usr/local/cargo/git \ --mount=type=cache,target=$SCCACHE_DIR,sharing=locked \ - cargo build --release --features="$FEATURES" --package=${RBUILDER_BIN} + cargo auditable build --release --features="$FEATURES" --package=${RBUILDER_BIN} FROM builder AS test-relay ARG FEATURES RUN --mount=type=cache,target=/usr/local/cargo/registry \ --mount=type=cache,target=/usr/local/cargo/git \ --mount=type=cache,target=$SCCACHE_DIR,sharing=locked \ - cargo build --release --features="$FEATURES" --package=test-relay + cargo auditable build --release --features="$FEATURES" --package=test-relay # Runtime container for test-relay diff --git a/docker/Dockerfile.reproducible b/docker/Dockerfile.reproducible index c54eeafe4..35719fe44 100644 --- a/docker/Dockerfile.reproducible +++ b/docker/Dockerfile.reproducible @@ -10,6 +10,7 @@ RUN apt-get -o Acquire::Check-Valid-Until=false update && \ libclang-dev \ protobuf-compiler \ cmake +RUN cargo install cargo-auditable@0.7.5 --locked WORKDIR /build COPY . . RUN SOURCE_DATE=1730000000 make build && make build-deb From 7f667537bde9c7eb944a136c1d37f9918ed2e8b6 Mon Sep 17 00:00:00 2001 From: shashial <10578726+shashial@users.noreply.github.com> Date: Mon, 24 Aug 2026 13:57:06 +0100 Subject: [PATCH 2/6] Address PR review: verify embedded audit data and fail empty scans --- .github/workflows/release.yaml | 10 +++++++++- Makefile | 19 +++++++++++++++---- README.md | 26 +++++++++++++------------- docker/Dockerfile.rbuilder | 4 ++++ docker/Dockerfile.reproducible | 4 ++++ 5 files changed, 45 insertions(+), 18 deletions(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index d9f3f8bc2..c3c93eff5 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -161,7 +161,7 @@ jobs: if [[ -n "$FEATURES" ]]; then FEATURE_FLAG="--features $FEATURES" fi - cargo auditable build --profile ${{ matrix.profile }} $FEATURE_FLAG \ + cargo auditable build --locked --profile ${{ matrix.profile }} $FEATURE_FLAG \ --bin rbuilder \ --bin rbuilder-operator \ --bin tbv-bidding-service \ @@ -169,6 +169,14 @@ jobs: --bin bid-scraper \ --bin rbuilder-rebalancer + - name: Verify audit data embedded (Mac) + if: steps.platform-check.outputs.skip != 'true' && matrix.platform == 'mac' + run: | + for bin in rbuilder rbuilder-operator tbv-bidding-service reth-rbuilder bid-scraper rbuilder-rebalancer; do + otool -l "target/${{ matrix.profile }}/${bin}" | grep -q 'dep-v0' \ + || { echo "ERROR: .dep-v0 audit section missing from ${bin}"; exit 1; } + done + - name: Rename binaries if: steps.platform-check.outputs.skip != 'true' env: diff --git a/Makefile b/Makefile index 5ed6e1cbc..83174e615 100644 --- a/Makefile +++ b/Makefile @@ -72,9 +72,12 @@ else endif # The cargo-auditable embedded data is sorted and timestamp-free +CARGO_AUDITABLE_VERSION := 0.7.5 + .PHONY: install-cargo-auditable install-cargo-auditable: - @command -v cargo-auditable >/dev/null 2>&1 || cargo install cargo-auditable@0.7.5 --locked + @cargo install --list | grep -q '^cargo-auditable v$(CARGO_AUDITABLE_VERSION):' \ + || cargo install cargo-auditable@$(CARGO_AUDITABLE_VERSION) --locked .PHONY: build build: install-cargo-auditable ## Build (release version) @@ -156,19 +159,27 @@ build-deb: build-deb-bid-scraper build-deb-rbuilder-operator build-deb-rbuilder- ##@ Dev +CARGO_AUDIT_VERSION := 0.22.2 + .PHONY: install-cargo-audit install-cargo-audit: - @command -v cargo-audit >/dev/null 2>&1 || cargo install cargo-audit@0.22.2 --locked + @cargo install --list | grep -q '^cargo-audit v$(CARGO_AUDIT_VERSION):' \ + || cargo install cargo-audit@$(CARGO_AUDIT_VERSION) --locked .PHONY: audit-bin -audit-bin: install-cargo-audit ## Scan built binaries for vulnerable dependencies (uses the audit data embedded by "make build") - @fail=0; \ +audit-bin: install-cargo-audit ## Scan built binaries for vulnerable dependencies + @scanned=0; fail=0; \ for bin in $(BUILD_OUTPUT_DIR)/*; do \ if [ -f "$$bin" ] && [ -x "$$bin" ]; then \ echo "==> $$bin"; \ cargo audit bin "$$bin" || fail=1; \ + scanned=$$((scanned+1)); \ fi; \ done; \ + if [ "$$scanned" -eq 0 ]; then \ + echo "error: no binaries found in $(BUILD_OUTPUT_DIR), run 'make build' first"; \ + exit 1; \ + fi; \ exit $$fail .PHONY: lint diff --git a/README.md b/README.md index 803cec1c0..fdfbe1e23 100644 --- a/README.md +++ b/README.md @@ -156,25 +156,25 @@ curl http://localhost:5555/relay/v1/data/bidtraces/proposer_payload_delivered ### Reproducible builds -You only need to set the `SOURCE_DATE_EPOCH` environment variable to ensure that the build is reproducible: +On x86_64, `make build` produces reproducible binaries: it selects the `reproducible` build +profile, sets `SOURCE_DATE_EPOCH` from the last commit timestamp, and applies the required +compiler flags (see the Makefile). Building the same commit twice yields bit-identical binaries: ```bash -# Use last commit timestamp as the build date -$ export SOURCE_DATE_EPOCH=$(git log -1 --pretty=%ct) - # build #1 -$ rm -rf target/ -$ cargo build --release -$ sha256sum target/release/rbuilder -d92ac33b94e16ed4a035b9dd52108fe78bd9bb160a91fced8e439f59b84c3207 target/release/rbuilder +$ make build +$ sha256sum target/x86_64-unknown-linux-gnu/reproducible/rbuilder-operator # build #2 -$ rm -rf target/ -$ cargo build --release -$ sha256sum target/release/rbuilder -d92ac33b94e16ed4a035b9dd52108fe78bd9bb160a91fced8e439f59b84c3207 target/release/rbuilder +$ make clean && make build +$ sha256sum target/x86_64-unknown-linux-gnu/reproducible/rbuilder-operator +# both hashes match ``` +The released Linux artifacts are built this way inside a pinned-toolchain image +([`docker/Dockerfile.reproducible`](./docker/Dockerfile.reproducible)), and reproducibility is +re-verified periodically by the `reproducible-build-test` CI workflow. + ### Auditable builds Release builds (`make build`, the Docker images, and the released binaries) go through @@ -185,7 +185,7 @@ dependency list into each binary. To scan the built binaries against the RustSec make audit-bin ``` -The embedded data can also be picked up by scanners such as `trivy`, `grype`, `syft`. Meaning that container +The embedded data can also be picked up by scanners such as `trivy`, `grype`, and `syft`, so container images built from these binaries can be scanned for Rust dependencies as well. --- diff --git a/docker/Dockerfile.rbuilder b/docker/Dockerfile.rbuilder index 30c92533b..3df988228 100644 --- a/docker/Dockerfile.rbuilder +++ b/docker/Dockerfile.rbuilder @@ -74,6 +74,8 @@ RUN --mount=type=cache,target=/usr/local/cargo/registry \ --mount=type=cache,target=/usr/local/cargo/git \ --mount=type=cache,target=$SCCACHE_DIR,sharing=locked \ cargo auditable build --release --features="$FEATURES" --package=${RBUILDER_BIN} +RUN readelf -S /app/target/release/${RBUILDER_BIN} | grep -q '\.dep-v0' \ + || { echo "ERROR: .dep-v0 audit section missing from ${RBUILDER_BIN}"; exit 1; } FROM builder AS test-relay ARG FEATURES @@ -81,6 +83,8 @@ RUN --mount=type=cache,target=/usr/local/cargo/registry \ --mount=type=cache,target=/usr/local/cargo/git \ --mount=type=cache,target=$SCCACHE_DIR,sharing=locked \ cargo auditable build --release --features="$FEATURES" --package=test-relay +RUN readelf -S /app/target/release/test-relay | grep -q '\.dep-v0' \ + || { echo "ERROR: .dep-v0 audit section missing from test-relay"; exit 1; } # Runtime container for test-relay diff --git a/docker/Dockerfile.reproducible b/docker/Dockerfile.reproducible index 35719fe44..02cbf04f6 100644 --- a/docker/Dockerfile.reproducible +++ b/docker/Dockerfile.reproducible @@ -14,6 +14,10 @@ RUN cargo install cargo-auditable@0.7.5 --locked WORKDIR /build COPY . . RUN SOURCE_DATE=1730000000 make build && make build-deb +RUN set -e; for bin in rbuilder-operator rbuilder-rebalancer bid-scraper; do \ + readelf -S "/build/target/x86_64-unknown-linux-gnu/reproducible/${bin}" | grep -q '\.dep-v0' \ + || { echo "ERROR: .dep-v0 audit section missing from ${bin}"; exit 1; }; \ + done FROM scratch AS artifacts COPY --from=builder /build/target/x86_64-unknown-linux-gnu/ / From c39059fc361c03a7b0d362681f76b833e46643ec Mon Sep 17 00:00:00 2001 From: shashial <10578726+shashial@users.noreply.github.com> Date: Mon, 24 Aug 2026 14:36:35 +0100 Subject: [PATCH 3/6] Fix clippy 1.98 lints blocking CI --- crates/bid-scraper/src/best_bid_ws_connector.rs | 1 + crates/eth-sparse-mpt/src/utils.rs | 2 +- crates/rbuilder-operator/src/bidding_service_wrapper/mod.rs | 2 ++ crates/rbuilder/src/mev_boost/bloxroute_grpc.rs | 1 + 4 files changed, 5 insertions(+), 1 deletion(-) diff --git a/crates/bid-scraper/src/best_bid_ws_connector.rs b/crates/bid-scraper/src/best_bid_ws_connector.rs index 24ae1830e..325ac9450 100644 --- a/crates/bid-scraper/src/best_bid_ws_connector.rs +++ b/crates/bid-scraper/src/best_bid_ws_connector.rs @@ -85,6 +85,7 @@ impl BestBidWSConnector(request: R) -> Result where R: IntoClientRequest + Unpin, diff --git a/crates/eth-sparse-mpt/src/utils.rs b/crates/eth-sparse-mpt/src/utils.rs index 42a31abfa..4c5f19e8b 100644 --- a/crates/eth-sparse-mpt/src/utils.rs +++ b/crates/eth-sparse-mpt/src/utils.rs @@ -126,7 +126,7 @@ pub fn mismatch(xs: &[u8], ys: &[u8]) -> usize { #[inline] fn mismatch_chunks(xs: &[u8], ys: &[u8]) -> usize { - let off = std::iter::zip(xs.chunks_exact(N), ys.chunks_exact(N)) + let off = std::iter::zip(xs.as_chunks::().0, ys.as_chunks::().0) .take_while(|(x, y)| x == y) .count() * N; diff --git a/crates/rbuilder-operator/src/bidding_service_wrapper/mod.rs b/crates/rbuilder-operator/src/bidding_service_wrapper/mod.rs index 40a2bf40f..1de7e43a8 100644 --- a/crates/rbuilder-operator/src/bidding_service_wrapper/mod.rs +++ b/crates/rbuilder-operator/src/bidding_service_wrapper/mod.rs @@ -1,3 +1,5 @@ +#![allow(clippy::result_large_err)] + #[rustfmt::skip] pub mod bidding_service; pub mod client; diff --git a/crates/rbuilder/src/mev_boost/bloxroute_grpc.rs b/crates/rbuilder/src/mev_boost/bloxroute_grpc.rs index a1a238ede..75267e5fc 100644 --- a/crates/rbuilder/src/mev_boost/bloxroute_grpc.rs +++ b/crates/rbuilder/src/mev_boost/bloxroute_grpc.rs @@ -14,6 +14,7 @@ use rbuilder_primitives::mev_boost::SubmitBlockRequest; use std::sync::Arc; /// Bloxroute gRPC types. +#[allow(clippy::result_large_err)] pub mod types { tonic::include_proto!("bloxroute"); } From 3def517b88be0985f914d5f427eb1823ef3c95ad Mon Sep 17 00:00:00 2001 From: shashial <10578726+shashial@users.noreply.github.com> Date: Thu, 27 Aug 2026 19:26:40 +0100 Subject: [PATCH 4/6] single-source cargo-auditable versions --- .github/workflows/release.yaml | 3 ++- .tool-versions | 2 ++ Makefile | 4 ++-- README.md | 3 +++ crates/rbuilder-operator/src/bidding_service_wrapper/mod.rs | 4 ++-- docker/Dockerfile.rbuilder | 3 ++- docker/Dockerfile.reproducible | 5 +++-- 7 files changed, 16 insertions(+), 8 deletions(-) create mode 100644 .tool-versions diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index c3c93eff5..15fdf0669 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -148,7 +148,8 @@ jobs: - name: Install cargo-auditable (Mac) if: steps.platform-check.outputs.skip != 'true' && matrix.platform == 'mac' - run: cargo install cargo-auditable@0.7.5 --locked + run: | + cargo install cargo-auditable@"$(awk '$1 == "cargo-auditable" {print $2}' .tool-versions)" --locked - name: Build binaries (Mac) if: steps.platform-check.outputs.skip != 'true' && matrix.platform == 'mac' diff --git a/.tool-versions b/.tool-versions new file mode 100644 index 000000000..bc7c7c5be --- /dev/null +++ b/.tool-versions @@ -0,0 +1,2 @@ +cargo-auditable 0.7.5 +cargo-audit 0.22.2 diff --git a/Makefile b/Makefile index 83174e615..2689d676f 100644 --- a/Makefile +++ b/Makefile @@ -72,7 +72,7 @@ else endif # The cargo-auditable embedded data is sorted and timestamp-free -CARGO_AUDITABLE_VERSION := 0.7.5 +CARGO_AUDITABLE_VERSION := $(shell awk '$$1 == "cargo-auditable" {print $$2}' .tool-versions) .PHONY: install-cargo-auditable install-cargo-auditable: @@ -159,7 +159,7 @@ build-deb: build-deb-bid-scraper build-deb-rbuilder-operator build-deb-rbuilder- ##@ Dev -CARGO_AUDIT_VERSION := 0.22.2 +CARGO_AUDIT_VERSION := $(shell awk '$$1 == "cargo-audit" {print $$2}' .tool-versions) .PHONY: install-cargo-audit install-cargo-audit: diff --git a/README.md b/README.md index fdfbe1e23..e3ff4a4df 100644 --- a/README.md +++ b/README.md @@ -188,6 +188,9 @@ make audit-bin The embedded data can also be picked up by scanners such as `trivy`, `grype`, and `syft`, so container images built from these binaries can be scanned for Rust dependencies as well. +The pinned `cargo-auditable` and `cargo-audit` versions used by all build paths live in +[`.tool-versions`](./.tool-versions). + --- ## Release Stability and Development Process diff --git a/crates/rbuilder-operator/src/bidding_service_wrapper/mod.rs b/crates/rbuilder-operator/src/bidding_service_wrapper/mod.rs index 1de7e43a8..b05d93c7f 100644 --- a/crates/rbuilder-operator/src/bidding_service_wrapper/mod.rs +++ b/crates/rbuilder-operator/src/bidding_service_wrapper/mod.rs @@ -1,7 +1,7 @@ -#![allow(clippy::result_large_err)] - #[rustfmt::skip] +#[allow(clippy::result_large_err)] pub mod bidding_service; +#[allow(clippy::result_large_err)] pub mod client; pub mod conversion; pub mod fast_streams; diff --git a/docker/Dockerfile.rbuilder b/docker/Dockerfile.rbuilder index 3df988228..facead2a0 100644 --- a/docker/Dockerfile.rbuilder +++ b/docker/Dockerfile.rbuilder @@ -36,7 +36,8 @@ RUN set -eux; \ rm -rf /tmp/sccache.tar.gz /tmp/sccache-v0.8.2-${ARCH_TAG} RUN cargo install cargo-chef --version ^0.1 -RUN cargo install cargo-auditable@0.7.5 --locked +COPY .tool-versions /tmp/.tool-versions +RUN cargo install cargo-auditable@"$(awk '$1 == "cargo-auditable" {print $2}' /tmp/.tool-versions)" --locked ENV CARGO_HOME=/usr/local/cargo diff --git a/docker/Dockerfile.reproducible b/docker/Dockerfile.reproducible index 02cbf04f6..d9224b555 100644 --- a/docker/Dockerfile.reproducible +++ b/docker/Dockerfile.reproducible @@ -10,11 +10,12 @@ RUN apt-get -o Acquire::Check-Valid-Until=false update && \ libclang-dev \ protobuf-compiler \ cmake -RUN cargo install cargo-auditable@0.7.5 --locked +COPY .tool-versions /tmp/.tool-versions +RUN cargo install cargo-auditable@"$(awk '$1 == "cargo-auditable" {print $2}' /tmp/.tool-versions)" --locked WORKDIR /build COPY . . RUN SOURCE_DATE=1730000000 make build && make build-deb -RUN set -e; for bin in rbuilder-operator rbuilder-rebalancer bid-scraper; do \ +RUN set -e; for bin in rbuilder rbuilder-operator tbv-bidding-service reth-rbuilder bid-scraper rbuilder-rebalancer; do \ readelf -S "/build/target/x86_64-unknown-linux-gnu/reproducible/${bin}" | grep -q '\.dep-v0' \ || { echo "ERROR: .dep-v0 audit section missing from ${bin}"; exit 1; }; \ done From d5b0b6afa1db07804f169de6dd5304d9477a36af Mon Sep 17 00:00:00 2001 From: shashial <10578726+shashial@users.noreply.github.com> Date: Thu, 27 Aug 2026 20:20:16 +0100 Subject: [PATCH 5/6] fix review --- .cargo-auditable-version | 1 + .github/workflows/release.yaml | 12 +++-------- .tool-versions | 2 -- Makefile | 30 +++++---------------------- README.md | 37 +++++++++++++++------------------- docker/Dockerfile.rbuilder | 6 ++++-- docker/Dockerfile.reproducible | 6 ++++-- 7 files changed, 33 insertions(+), 61 deletions(-) create mode 100644 .cargo-auditable-version delete mode 100644 .tool-versions diff --git a/.cargo-auditable-version b/.cargo-auditable-version new file mode 100644 index 000000000..8bd6ba8c5 --- /dev/null +++ b/.cargo-auditable-version @@ -0,0 +1 @@ +0.7.5 diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 15fdf0669..71cde3ae3 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -149,7 +149,9 @@ jobs: - name: Install cargo-auditable (Mac) if: steps.platform-check.outputs.skip != 'true' && matrix.platform == 'mac' run: | - cargo install cargo-auditable@"$(awk '$1 == "cargo-auditable" {print $2}' .tool-versions)" --locked + v="$(cat .cargo-auditable-version)" + [ -n "$v" ] || { echo "ERROR: could not read cargo-auditable version from .cargo-auditable-version"; exit 1; } + cargo install cargo-auditable@"$v" --locked - name: Build binaries (Mac) if: steps.platform-check.outputs.skip != 'true' && matrix.platform == 'mac' @@ -170,14 +172,6 @@ jobs: --bin bid-scraper \ --bin rbuilder-rebalancer - - name: Verify audit data embedded (Mac) - if: steps.platform-check.outputs.skip != 'true' && matrix.platform == 'mac' - run: | - for bin in rbuilder rbuilder-operator tbv-bidding-service reth-rbuilder bid-scraper rbuilder-rebalancer; do - otool -l "target/${{ matrix.profile }}/${bin}" | grep -q 'dep-v0' \ - || { echo "ERROR: .dep-v0 audit section missing from ${bin}"; exit 1; } - done - - name: Rename binaries if: steps.platform-check.outputs.skip != 'true' env: diff --git a/.tool-versions b/.tool-versions deleted file mode 100644 index bc7c7c5be..000000000 --- a/.tool-versions +++ /dev/null @@ -1,2 +0,0 @@ -cargo-auditable 0.7.5 -cargo-audit 0.22.2 diff --git a/Makefile b/Makefile index 2689d676f..abaea2c31 100644 --- a/Makefile +++ b/Makefile @@ -72,11 +72,14 @@ else endif # The cargo-auditable embedded data is sorted and timestamp-free -CARGO_AUDITABLE_VERSION := $(shell awk '$$1 == "cargo-auditable" {print $$2}' .tool-versions) +CARGO_AUDITABLE_VERSION := $(shell cat .cargo-auditable-version) +ifeq ($(strip $(CARGO_AUDITABLE_VERSION)),) +$(error could not read cargo-auditable version from .cargo-auditable-version) +endif .PHONY: install-cargo-auditable install-cargo-auditable: - @cargo install --list | grep -q '^cargo-auditable v$(CARGO_AUDITABLE_VERSION):' \ + @cargo install --list | grep -qxF 'cargo-auditable v$(CARGO_AUDITABLE_VERSION):' \ || cargo install cargo-auditable@$(CARGO_AUDITABLE_VERSION) --locked .PHONY: build @@ -159,29 +162,6 @@ build-deb: build-deb-bid-scraper build-deb-rbuilder-operator build-deb-rbuilder- ##@ Dev -CARGO_AUDIT_VERSION := $(shell awk '$$1 == "cargo-audit" {print $$2}' .tool-versions) - -.PHONY: install-cargo-audit -install-cargo-audit: - @cargo install --list | grep -q '^cargo-audit v$(CARGO_AUDIT_VERSION):' \ - || cargo install cargo-audit@$(CARGO_AUDIT_VERSION) --locked - -.PHONY: audit-bin -audit-bin: install-cargo-audit ## Scan built binaries for vulnerable dependencies - @scanned=0; fail=0; \ - for bin in $(BUILD_OUTPUT_DIR)/*; do \ - if [ -f "$$bin" ] && [ -x "$$bin" ]; then \ - echo "==> $$bin"; \ - cargo audit bin "$$bin" || fail=1; \ - scanned=$$((scanned+1)); \ - fi; \ - done; \ - if [ "$$scanned" -eq 0 ]; then \ - echo "error: no binaries found in $(BUILD_OUTPUT_DIR), run 'make build' first"; \ - exit 1; \ - fi; \ - exit $$fail - .PHONY: lint lint: ## Run the linters cargo fmt -- --check diff --git a/README.md b/README.md index e3ff4a4df..7778de613 100644 --- a/README.md +++ b/README.md @@ -156,40 +156,35 @@ curl http://localhost:5555/relay/v1/data/bidtraces/proposer_payload_delivered ### Reproducible builds -On x86_64, `make build` produces reproducible binaries: it selects the `reproducible` build -profile, sets `SOURCE_DATE_EPOCH` from the last commit timestamp, and applies the required -compiler flags (see the Makefile). Building the same commit twice yields bit-identical binaries: +`make build` produces reproducible binaries on x86_64: it sets the `SOURCE_DATE_EPOCH` +environment variable (last commit timestamp) and the required compiler flags automatically: ```bash # build #1 +$ rm -rf target/ $ make build -$ sha256sum target/x86_64-unknown-linux-gnu/reproducible/rbuilder-operator +$ sha256sum target/x86_64-unknown-linux-gnu/reproducible/rbuilder + target/x86_64-unknown-linux-gnu/reproducible/rbuilder # build #2 -$ make clean && make build -$ sha256sum target/x86_64-unknown-linux-gnu/reproducible/rbuilder-operator -# both hashes match -``` +$ rm -rf target/ +$ make build +$ sha256sum target/x86_64-unknown-linux-gnu/reproducible/rbuilder + target/x86_64-unknown-linux-gnu/reproducible/rbuilder -The released Linux artifacts are built this way inside a pinned-toolchain image -([`docker/Dockerfile.reproducible`](./docker/Dockerfile.reproducible)), and reproducibility is -re-verified periodically by the `reproducible-build-test` CI workflow. +# the two hashes are identical +``` ### Auditable builds Release builds (`make build`, the Docker images, and the released binaries) go through [`cargo auditable`](https://github.com/rust-secure-code/cargo-auditable), which embeds the full -dependency list into each binary. To scan the built binaries against the RustSec advisory database: - -```bash -make audit-bin -``` - -The embedded data can also be picked up by scanners such as `trivy`, `grype`, and `syft`, so container -images built from these binaries can be scanned for Rust dependencies as well. +dependency list into each binary. The embedded data can be read by scanners such as +`cargo audit bin`, `trivy`, `grype`, and `syft`, so both the binaries and the container images +built from them can be scanned for Rust dependencies. -The pinned `cargo-auditable` and `cargo-audit` versions used by all build paths live in -[`.tool-versions`](./.tool-versions). +The pinned `cargo-auditable` version used by all build paths lives in +[`.cargo-auditable-version`](./.cargo-auditable-version). --- diff --git a/docker/Dockerfile.rbuilder b/docker/Dockerfile.rbuilder index facead2a0..d74882ecc 100644 --- a/docker/Dockerfile.rbuilder +++ b/docker/Dockerfile.rbuilder @@ -36,8 +36,10 @@ RUN set -eux; \ rm -rf /tmp/sccache.tar.gz /tmp/sccache-v0.8.2-${ARCH_TAG} RUN cargo install cargo-chef --version ^0.1 -COPY .tool-versions /tmp/.tool-versions -RUN cargo install cargo-auditable@"$(awk '$1 == "cargo-auditable" {print $2}' /tmp/.tool-versions)" --locked +COPY .cargo-auditable-version /tmp/cargo-auditable-version +RUN v="$(cat /tmp/cargo-auditable-version)"; \ + [ -n "$v" ] || { echo "ERROR: could not read cargo-auditable version from .cargo-auditable-version"; exit 1; }; \ + cargo install cargo-auditable@"$v" --locked ENV CARGO_HOME=/usr/local/cargo diff --git a/docker/Dockerfile.reproducible b/docker/Dockerfile.reproducible index d9224b555..1b965813b 100644 --- a/docker/Dockerfile.reproducible +++ b/docker/Dockerfile.reproducible @@ -10,8 +10,10 @@ RUN apt-get -o Acquire::Check-Valid-Until=false update && \ libclang-dev \ protobuf-compiler \ cmake -COPY .tool-versions /tmp/.tool-versions -RUN cargo install cargo-auditable@"$(awk '$1 == "cargo-auditable" {print $2}' /tmp/.tool-versions)" --locked +COPY .cargo-auditable-version /tmp/cargo-auditable-version +RUN v="$(cat /tmp/cargo-auditable-version)"; \ + [ -n "$v" ] || { echo "ERROR: could not read cargo-auditable version from .cargo-auditable-version"; exit 1; }; \ + cargo install cargo-auditable@"$v" --locked WORKDIR /build COPY . . RUN SOURCE_DATE=1730000000 make build && make build-deb From 05afbfd9c81761abfb22184460c1e516d6fd887a Mon Sep 17 00:00:00 2001 From: shashial <10578726+shashial@users.noreply.github.com> Date: Thu, 27 Aug 2026 22:55:36 +0100 Subject: [PATCH 6/6] Update Makefile Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com> --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index abaea2c31..626202a79 100644 --- a/Makefile +++ b/Makefile @@ -72,7 +72,7 @@ else endif # The cargo-auditable embedded data is sorted and timestamp-free -CARGO_AUDITABLE_VERSION := $(shell cat .cargo-auditable-version) +CARGO_AUDITABLE_VERSION := $(shell cat $(dir $(firstword $(MAKEFILE_LIST)))/.cargo-auditable-version 2>/dev/null) ifeq ($(strip $(CARGO_AUDITABLE_VERSION)),) $(error could not read cargo-auditable version from .cargo-auditable-version) endif