diff --git a/.github/skills/dev/maintenance/catalog-security-vulnerabilities/SKILL.md b/.github/skills/dev/maintenance/catalog-security-vulnerabilities/SKILL.md index 37f665dda..f2020ee57 100644 --- a/.github/skills/dev/maintenance/catalog-security-vulnerabilities/SKILL.md +++ b/.github/skills/dev/maintenance/catalog-security-vulnerabilities/SKILL.md @@ -23,7 +23,8 @@ provides a quick reference. ```text docs/security/analysis/ README.md ← Process + template - non-affecting/ ← CVEs that do NOT affect us (catalog) + production/ ← CVEs in the production runtime image (catalog) + build/ ← CVEs in build-stage images (catalog) affecting/ ← CVEs that DO affect us (create when needed) ``` @@ -31,19 +32,21 @@ docs/security/analysis/ ### Step 1: Check the Catalog -Before analyzing a new warning, check `docs/security/analysis/non-affecting/` to see if -it has already been evaluated. Every file there documents why a set of CVEs is -non-affecting. If found, the analysis is already done — link the existing document in -any related issue or PR comment. +Before analyzing a new warning, check `docs/security/analysis/production/` and +`docs/security/analysis/build/` to see if it has already been evaluated. Every file there +documents why a set of CVEs is non-affecting. If found, the analysis is already done — +link the existing document in any related issue or PR comment. ### Step 2: Analyse and Document (if not cataloged) If the vulnerability is **not yet cataloged**: 1. Determine whether it affects us (see criteria examples in the README). -2. If **non-affecting**: create a dated file in `non-affecting/` following the template - in the README. Include rationale, future actions, and review cadence. -3. If **affecting**: escalate immediately (see Step 3). +2. Determine the impact context: production runtime (`production/`) or build stage + (`build/`). +3. If **non-affecting**: create a dated file in the appropriate subdirectory following the + template in the README. Include rationale, future actions, and review cadence. +4. If **affecting**: escalate immediately (see Step 3). ### Step 3: Escalate if Affecting diff --git a/.github/skills/dev/maintenance/run-manual-docker-security-scan/SKILL.md b/.github/skills/dev/maintenance/run-manual-docker-security-scan/SKILL.md index 04cf99bb0..f2007a11c 100644 --- a/.github/skills/dev/maintenance/run-manual-docker-security-scan/SKILL.md +++ b/.github/skills/dev/maintenance/run-manual-docker-security-scan/SKILL.md @@ -12,7 +12,8 @@ metadata: - docs/security/docker/scans/README.md - docs/security/docker/scans/torrust-tracker.md - docs/security/analysis/README.md - - docs/security/analysis/non-affecting/ + - docs/security/analysis/production/ + - docs/security/analysis/build/ --- # Run Manual Docker Security Scan @@ -26,7 +27,7 @@ Use this workflow to run and document manual security scans for the tracker prod - Documentation outputs: - `docs/security/docker/scans/torrust-tracker.md` - `docs/security/docker/scans/README.md` - - `docs/security/analysis/non-affecting/CVE-*.md` (when non-affecting CVEs are analyzed) + - `docs/security/analysis/production/CVE-*.md` (when non-affecting CVEs are analyzed) ## Quick Commands @@ -48,7 +49,7 @@ trivy image --severity MEDIUM,HIGH,CRITICAL torrust-tracker:local Before analyzing any CVE, search the existing catalog: ```bash -grep -R "CVE-" docs/security/analysis/non-affecting/ +grep -R "CVE-" docs/security/analysis/ ``` If already present and `requires-recheck-when` conditions have not changed, reuse the existing verdict. @@ -70,7 +71,8 @@ Update: ### Step 4: Document New Non-Affecting CVEs -For any new non-affecting CVE, create `docs/security/analysis/non-affecting/CVE-.md` with: +For any new non-affecting CVE, create `docs/security/analysis/production/CVE-.md` or +`docs/security/analysis/build/CVE-.md` with: - frontmatter fields: - `cve-id` diff --git a/Containerfile b/Containerfile index 0fc624147..d335807e0 100644 --- a/Containerfile +++ b/Containerfile @@ -3,10 +3,14 @@ # Torrust Tracker ## Builder Image -FROM docker.io/library/rust:trixie AS chef +FROM docker.io/library/rust:slim-trixie AS chef WORKDIR /tmp +RUN apt-get update \ + && apt-get install -y --no-install-recommends curl libssl-dev pkg-config \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* RUN curl -L --proto '=https' --tlsv1.2 -sSf https://raw.githubusercontent.com/cargo-bins/cargo-binstall/main/install-from-binstall-release.sh | bash -RUN cargo binstall --no-confirm --locked torrust-cargo-chef@0.1.78 cargo-nextest +RUN cargo binstall --no-confirm --locked torrust-cargo-chef@0.1.78 cargo-nextest@0.9.140 # Note: We use the `torrust-cargo-chef` fork (v0.1.78) while upstream PR # https://github.com/LukeMathWalker/cargo-chef/pull/360 is pending. Once merged, # switch back to upstream `cargo-chef` and remove this comment. @@ -16,10 +20,12 @@ FROM docker.io/library/rust:slim-trixie AS tester WORKDIR /tmp RUN apt-get update \ - && apt-get install -y curl sqlite3 time \ - && apt-get autoclean -RUN curl -L --proto '=https' --tlsv1.2 -sSf https://raw.githubusercontent.com/cargo-bins/cargo-binstall/main/install-from-binstall-release.sh | bash -RUN cargo binstall --no-confirm --locked cargo-nextest + && apt-get install -y --no-install-recommends curl sqlite3 time \ + && curl -L --proto '=https' --tlsv1.2 -sSf https://raw.githubusercontent.com/cargo-bins/cargo-binstall/main/install-from-binstall-release.sh | bash \ + && cargo binstall --no-confirm --locked cargo-nextest@0.9.140 \ + && apt-get purge -y --auto-remove curl \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* # Database initialization: Tests at runtime require a pre-initialized SQLite3 database # to test against a valid (not corrupted) schema. The VACUUM command optimizes the # database file layout. This image layer is inherited by test_debug and test stages. @@ -29,7 +35,11 @@ RUN time mkdir -p /app/share/torrust/default/database/ \ && time sqlite3 /app/share/torrust/default/database/tracker.sqlite3.db "VACUUM;" ## Su Exe Compile -FROM docker.io/library/gcc:trixie AS gcc +FROM docker.io/library/debian:trixie-slim AS gcc +RUN apt-get update \ + && apt-get install -y --no-install-recommends gcc libc6-dev \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* COPY ./contrib/dev-tools/su-exec/ /usr/local/src/su-exec/ RUN cc -Wall -Werror -g /usr/local/src/su-exec/su-exec.c -o /usr/local/bin/su-exec \ && chmod +x /usr/local/bin/su-exec diff --git a/docs/issues/open/1463-1457-use-rust-slim-builder-image.md b/docs/issues/open/1463-1457-use-rust-slim-builder-image.md new file mode 100644 index 000000000..3df698353 --- /dev/null +++ b/docs/issues/open/1463-1457-use-rust-slim-builder-image.md @@ -0,0 +1,340 @@ +--- +doc-type: issue +issue-type: task +status: open +priority: p3 +github-issue: 1463 +spec-path: docs/issues/open/1463-1457-use-rust-slim-builder-image.md +branch: "1463-1457-use-rust-slim-builder-image" +related-pr: "https://github.com/torrust/torrust-tracker/pull/2007" +last-updated-utc: 2026-07-20 00:00 +semantic-links: + skill-links: + - create-issue + - catalog-security-vulnerabilities + related-artifacts: + - Containerfile + - .github/workflows/container.yaml + - .github/workflows/security-scan.yaml + - docs/security/docker/scans/torrust-tracker.md + - docs/security/docker/scans/build-images.md + - docs/security/docker/scans/README.md + - docs/security/analysis/README.md + - docs/security/analysis/build/2026-06-10_containerfile-trixie-cves.md + - docs/adrs/20260603000000_keep_unit_tests_inside_container_build.md +--- + + + + +# Issue #1463 - Minimize Containerfile build-stage images + +## Goal + +Replace the `chef` stage's `rust:trixie` base image with `rust:slim-trixie` if the +complete container build and test workflow needs only a small, explicit set of added +packages. Independently minimize the existing `tester` stage and evaluate whether the +separate `gcc` stage has a practical slimmer alternative. Reduce build-image size, +installed package inventory, vulnerability exposure, and maintenance burden without +weakening build or test coverage. + +## Background + +The Containerfile currently uses `rust:trixie` for the shared `chef` stage and +`rust:slim-trixie` for the separate `tester` stage. Because all dependency and build +stages inherit from `chef`, changing this one base image affects the complete Rust build +path. The final production image inherits from `gcr.io/distroless/cc-debian13:debug`, so +this change does not directly reduce the size or package inventory of the published +runtime image. + +Issue #1463 originally reported that `cargo binstall` was unavailable after trying the +slim image. The current tester stage demonstrates the likely cause and remedy: slim does +not include `curl`, so the `cargo-binstall` installer must be preceded by a minimal package +installation. The issue's April 2026 comments also concluded that full and slim Trixie +images had the same vulnerabilities at that time. A later repository security analysis +and the fresh measurements below show that slim now has a materially smaller package and +scanner-finding inventory. Scanner results are time-sensitive and must be captured again +during implementation. + +### Preliminary investigation + +Measurements were taken on 2026-07-20 for fresh `linux/amd64` pulls: + +| Metric | `rust:trixie` | `rust:slim-trixie` | Difference | +| ---------------------------- | -------------------- | ------------------- | ---------------------------- | +| Image digest | `sha256:9a2cd304...` | `sha256:5c6f46a...` | Different current images | +| Docker image size | 1,662.7 MB | 921.0 MB | 741.7 MB smaller (44.6%) | +| Installed Debian packages | 455 | 119 | 336 fewer packages (73.8%) | +| Trivy vulnerability findings | 2,148 | 1,008 | 1,140 fewer findings (53.1%) | + +The Trivy totals use Trivy 0.69.3 and its database as of the measurement date. They count +findings rather than unique CVEs and are evidence for comparison, not a permanent security +claim. + +The slim image already contains `bash`, `cc`, `gcc`, and `perl`. It does not contain +`curl`, `make`, `g++`, `pkg-config`, `git`, or `xz`. An isolated probe installed only +`curl` with `--no-install-recommends`, then successfully installed and executed the exact +tools used by the current Containerfile: + +- `torrust-cargo-chef` 0.1.78 +- `cargo-nextest` 0.9.140 + +This resolves the tool-installation uncertainty but does not prove that every workspace +dependency compiles or links under slim. The complete multi-stage build remains the +decisive check. + +### Chef implementation result + +The complete release build showed that `curl` alone is insufficient: `openssl-sys` needs +the `pkg-config` command and OpenSSL development headers. Adding `libssl-dev` and +`pkg-config` resolved that failure. The final chef stage passed the full `release` target, +including dependency cooking, release archive creation, containerized tests, and final +image assembly. + +| Metric | Full Rust baseline | Final slim chef | Difference | +| ---------------------------- | ------------------ | --------------- | ---------------------------- | +| Image size | 1,662.7 MB | 1,067.4 MB | 595.3 MB smaller (35.8%) | +| Installed Debian packages | 455 | 145 | 310 fewer packages (68.1%) | +| Trivy vulnerability findings | 2,148 | 1,072 | 1,076 fewer findings (50.1%) | + +The explicitly installed chef packages are: + +- `curl`: downloads the `cargo-binstall` installer. +- `libssl-dev`: provides OpenSSL headers and libraries required by `openssl-sys`. +- `pkg-config`: lets `openssl-sys` discover the system OpenSSL installation. + +### Tester implementation result + +The tester stage now installs setup and runtime tools in one layer with +`--no-install-recommends`. After `cargo-nextest` is installed, setup-only `curl` and its +unused dependencies are removed. The final stage retains only the tools used later: + +- `sqlite3`: initializes the test database schema. +- `time`: preserves the existing build-step timing instrumentation. +- `cargo-nextest`: extracts and runs the archived test suite. + +The final tester stage is 975.9 MB with 123 Debian packages and 1,014 Trivy findings. +`curl` is absent, while `sqlite3`, `time`, and `cargo-nextest` are executable. The full +`release` target passed archive extraction, containerized tests, and final image assembly. + +### GCC implementation result + +The `gcc:trixie` image has been replaced by `debian:trixie-slim` plus only `gcc` and +`libc6-dev`. An initial probe with `gcc` alone failed because `su-exec.c` includes +`sys/types.h`; adding `libc6-dev` supplied the required libc headers. The final stage +compiled `su-exec`, the full `release` target passed, and `su-exec` executed successfully +inside the distroless runtime image. + +| Metric | `gcc:trixie` baseline | Final slim GCC | Difference | +| ---------------------------- | --------------------- | -------------- | ---------------------------- | +| Image size | 1,556.4 MB | 274.3 MB | 1,282.1 MB smaller (82.4%) | +| Installed Debian packages | 464 | 114 | 350 fewer packages (75.4%) | +| Trivy vulnerability findings | 2,165 | 1,008 | 1,157 fewer findings (53.4%) | + +## Scope + +### In Scope + +- Re-measure the current full and slim Rust image size, installed package count, and + vulnerability findings using pinned image digests in the evidence. +- Change the `chef` stage from `rust:trixie` to `rust:slim-trixie`. +- Install only packages demonstrated to be necessary, using `--no-install-recommends` and + removing APT index files in the same layer. +- Independently review and minimize the existing `rust:slim-trixie` tester stage, including + its explicitly installed and transitive APT packages. +- Build and test every Containerfile target exercised by the container and testing CI + workflows. +- Compare the resulting chef/build-stage package inventory and vulnerability findings with + the baseline, including packages reintroduced by APT dependencies. +- Evaluate slimmer alternatives for the `gcc:trixie` stage and adopt one only if compiling + `su-exec` remains simple and the resulting package inventory is clearly reduced. +- Update the existing Trixie vulnerability analysis with the new image digest, findings, + and build-stage rationale. +- Re-scan the final production `release` image and append the result to + `docs/security/docker/scans/torrust-tracker.md`, even if its distroless base is unchanged. +- Add `docs/security/docker/scans/build-images.md` as one consolidated history for the + foundational `chef`, `tester`, and `gcc` stages, and link it from the scan index. +- Implement and validate the `chef`, `tester`, and `gcc` stage changes independently so + each stage can be committed and reviewed separately. +- Keep the full image if slim requires enough added packages or special-case maintenance to + erase the measured simplification benefit; document that decision with evidence. + +### Out of Scope + +- Replacing or changing the distroless runtime image. +- Removing containerized unit tests or reducing test coverage. +- Fixing vulnerabilities in upstream Debian or Docker Official Images. +- Optimizing application dependencies or Rust compilation time. + +## Decision Rule + +Adopt a slimmer image for a stage when all required builds and tests pass and the final +package additions remain a small, understandable build-tool set that preserves a material +reduction in package inventory and scanner findings. Review that package list qualitatively; +no fixed percentage or package cap is required. If compilation requires reconstructing most +of a full image's general-purpose toolchain, retain the current image and record the measured +blocker instead of adding a large maintenance list. + +## Scan Recording Policy + +The production and build-stage reports answer different questions and must remain separate: + +- `docs/security/docker/scans/torrust-tracker.md` records the deployed `release` image's + security posture. Re-scan it after these build-stage changes to prove the final artifact + did not regress, even though its distroless base is unchanged. +- `docs/security/docker/scans/build-images.md` records one consolidated comparison of the + foundational `chef`, `tester`, and `gcc` stages. Keeping these related ephemeral stages + together makes package and finding differences easier to review without overstating them + as production exposure. +- `docs/security/analysis/` remains the single catalog for durable CVE impact decisions. + Scan reports should link to catalog entries rather than repeat full exploitability + analyses. + +Continue daily automated scanning for the published production image. Scan the foundational +build stages when their base images or installed packages change and during the quarterly +security review. Do not add daily build-stage SARIF uploads in this issue; these unpublished, +ephemeral stages have a lower risk and would mix build-chain findings into the production +security signal. + +## Implementation Plan + +Status values: `TODO`, `IN_PROGRESS`, `BLOCKED`, `DONE`. + +| ID | Status | Task | Notes / Expected Output | +| --- | ------ | ----------------------------------------- | ------------------------------------------------------------------------------------------------------------------------ | +| T1 | DONE | Establish a fresh base-image baseline | Digests, sizes, package counts, tool inventory, and Trivy summaries recorded in this spec | +| T2 | DONE | Probe minimal cargo-tool installation | Exact pinned tools install and run on slim after adding only `curl` | +| T3 | DONE | Change and validate the chef stage | Slim base plus three demonstrated packages; full `release` build and containerized tests passed; delivered independently | +| T4 | DONE | Minimize and validate the tester stage | Setup-only curl removed; SQLite, time, and nextest retained; full `release` test path passed; delivered independently | +| T5 | DONE | Evaluate and validate a slimmer GCC stage | Debian slim plus GCC and libc headers builds and runs `su-exec`; full `release` path passed; delivered independently | +| T6 | DONE | Measure the resulting build stages | Final chef, tester, and GCC size, package, and Trivy evidence recorded | +| T7 | DONE | Apply the decision rule | Each stage has a small demonstrated package set and remains materially smaller | +| T8 | DONE | Record build-stage scan history | Consolidated `build-images.md` records chef, tester, and GCC commands, digests, package counts, and findings | +| T9 | DONE | Refresh production scan history | Rebuilt release image scanned with 5 MEDIUM, 0 HIGH, and 0 CRITICAL findings; release health check passed | +| T10 | DONE | Update security analysis documentation | Catalog summary now records current bases, digests, scan date, counts, commands, and build-only conclusion | + +## Progress Tracking + +### Workflow Checkpoints + +- [x] Spec drafted for the existing GitHub issue +- [x] Spec reviewed and approved by user/maintainer +- [x] GitHub issue number and parent EPIC added to this spec +- [ ] (Optional, recommended for complex issues) Spec-only PR merged into `develop` before implementation +- [x] Implementation completed +- [x] Automatic verification completed (`linter all`, relevant tests, and any pre-push checks) +- [x] Manual verification scenarios executed and recorded (status + evidence) +- [x] Acceptance criteria reviewed after implementation and updated with evidence +- [ ] Reviewer validated acceptance criteria and updated checkboxes +- [ ] Committer verified spec progress is up to date before commit +- [ ] Issue closed and spec moved from `docs/issues/open/` to `docs/issues/closed/` + +### Progress Log + +- 2026-07-20 00:00 UTC - GitHub Copilot - Read issue #1463 and both comments; created the local issue branch and drafted this spec - local investigation results recorded above +- 2026-07-20 00:00 UTC - GitHub Copilot - Compared fresh full/slim images and verified the pinned cargo tools install on slim with only `curl` added - T1 and T2 completed +- 2026-07-20 00:00 UTC - User/maintainer - Approved the stage-by-stage scope, independent commits, and separate runtime/build-image scan reports - specification approved +- 2026-07-20 00:00 UTC - GitHub Copilot - Changed chef to `rust:slim-trixie`; the first release build exposed missing OpenSSL discovery tools, so `libssl-dev` and `pkg-config` were added - package requirements demonstrated by build failure +- 2026-07-20 00:00 UTC - GitHub Copilot - Built the complete `release` target with containerized tests and measured 145 packages, 1,067.4 MB, and 1,072 Trivy findings in the final chef stage - T3 and M3 completed +- 2026-07-20 00:00 UTC - GitHub Copilot - Consolidated tester setup into one layer, removed setup-only curl, and retained only SQLite, time, and nextest - tester minimized to 123 packages and 1,014 Trivy findings +- 2026-07-20 00:00 UTC - GitHub Copilot - Built the complete `release` target with the minimized tester in 131.4 s; containerized tests and final assembly passed - T4 and M4 completed +- 2026-07-20 00:00 UTC - GitHub Copilot - Replaced `gcc:trixie` with Debian slim plus GCC and libc headers; reduced the stage to 274.3 MB, 114 packages, and 1,008 findings - T5, T6, and T7 completed +- 2026-07-20 00:00 UTC - GitHub Copilot - Built the complete `release` target and executed `su-exec` successfully inside the distroless runtime - M5 and M6 completed +- 2026-07-20 00:00 UTC - GitHub Copilot - Scanned all finalized build stages with one Trivy database and created the consolidated build-image history - T8 and M7 completed +- 2026-07-20 00:00 UTC - GitHub Copilot - Scanned the 188.6 MB release image (5 MEDIUM, 0 HIGH, 0 CRITICAL) and observed repeated `200 OK` built-in health checks - T9, T10, and M8 completed +- 2026-07-20 00:00 UTC - GitHub Copilot - Reorganized CVE catalog from flat `non-affecting/` to impact-context subdirectories (`production/`, `build/`); updated all cross-references in skills, scan reports, and security overview - documentation committed +- 2026-07-20 00:00 UTC - User/maintainer - Pruned ~32 GB of Docker images and 76 GB of BuildKit cache left from this issue's implementation and earlier experiments - disk space recovered +- 2026-07-20 00:00 UTC - GitHub Copilot - Pushed branch to fork and opened PR #2007 against develop - issue implementation complete + +## Acceptance Criteria + +- [x] AC1: The `chef` stage uses `rust:slim-trixie`, or evidence documents why the slim image fails the decision rule and the full image is retained. +- [x] AC2: Every package explicitly added to the slim chef stage is tied to a reproducible build or tool-installation requirement. +- [x] AC3: The tester stage is independently minimized and validated without reducing existing test scope. +- [x] AC4: Before/after evidence records image digests, image sizes, installed package counts, and vulnerability findings using the same commands and scanner database. +- [x] AC5: The adopted result has a materially smaller installed package inventory than `rust:trixie`; no target percentage is assumed before transitive dependencies are measured. +- [x] AC6: The `gcc` stage uses a practical slimmer alternative, or measured evidence documents why `gcc:trixie` is retained. +- [x] AC7: The chef, tester, and GCC changes are implemented, validated, and committed independently. +- [x] AC8: `build-images.md` provides a consolidated scan history for the foundational build stages without mixing their lower-risk status into the production report. +- [x] AC9: `torrust-tracker.md` contains a new post-change release-image scan proving the production artifact did not regress. +- [x] AC10: The existing security analysis catalog summarizes the implemented images, current scan evidence, comparison commands, and the fact that these stages are build-time only. +- [x] `linter all` exits with code `0`. +- [x] Relevant container workflow tests pass. +- [x] Manual verification scenarios are executed and documented (status + evidence). +- [x] Acceptance criteria are re-reviewed after implementation and reflect actual behavior. +- [x] Documentation is updated when behavior or workflow changes. + +## Verification Plan + +Define verification before implementation starts and execute it before closing the issue. + +### Automatic Checks + +- `linter all` +- Build the Containerfile targets used by `.github/workflows/container.yaml`. +- Build the Containerfile targets used by the container-based test workflow. +- After each independent stage change, rerun the narrowest dependent Containerfile target + before changing another stage. +- Run the repository's pre-push checks when the implementation is ready for review. + +### Manual Verification Scenarios + +Status values: `TODO`, `IN_PROGRESS`, `DONE`, `FAILED`, `BLOCKED`. + +| ID | Scenario | Command/Steps | Expected Result | Status | Evidence | +| --- | ------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------ | ------ | ------------------------------------------------------------------- | +| M1 | Compare fresh base images | Pull both images by tag, record resolved digests, inspect `.Size`, and count the Debian package-query output | Reproducible baseline shows the exact size and package-inventory delta | DONE | Preliminary investigation table in this spec | +| M2 | Verify minimal cargo tooling | On `rust:slim-trixie`, install only `curl` with `--no-install-recommends`, run the existing `cargo-binstall` installer, then install the pinned tools | `cargo chef --version` and `cargo nextest --version` succeed | DONE | Preliminary investigation and progress log in this spec | +| M3 | Validate chef change independently | Build the dependent release path without relying on host artifacts before changing tester or GCC | Chef-dependent compilation succeeds and the change is ready for its own commit | DONE | Local `release` build passed in 236.7 s; image `sha256:0b497b43...` | +| M4 | Validate tester change independently | Run the complete containerized test paths after changing tester and before changing GCC | Existing tests execute successfully and the tester change is ready for its own commit | DONE | Local `release` build passed in 131.4 s; image `sha256:0b497b43...` | +| M5 | Inspect added package closure | List explicit and transitive packages after the APT install and compare them with the full image | Every explicit package is necessary and the resulting inventory remains materially smaller | DONE | Chef, tester, and GCC implementation-result measurements | +| M6 | Evaluate a slimmer GCC stage | Compare practical candidate images, compile `su-exec`, and inspect the resulting package closure | Adopt a clearly simpler candidate or document why the current GCC image remains preferable | DONE | 114 packages; release build and runtime `su-exec` smoke test passed | +| M7 | Scan foundational build stages | Build tagged `chef`, `tester`, and `gcc` targets, then scan all three with the same Trivy version/database | Consolidated report shows comparable findings and preserves their build-time risk context | DONE | `docs/security/docker/scans/build-images.md` | +| M8 | Scan and smoke-test release image | Build and scan `release`, start it, and exercise its configured health check | Production scan history is refreshed; runtime starts and becomes healthy | DONE | 5 MEDIUM, 0 HIGH/CRITICAL; repeated health-check `200 OK` responses | + +Notes: + +- Manual verification is mandatory even when automated tests pass. +- If a scenario fails, record the failure and diagnosis in the progress log before proceeding. +- Scanner totals are comparable only when the scanner version and vulnerability database are + held constant for both images. + +### Acceptance Verification + +| AC ID | Status (`TODO`/`DONE`) | Evidence | +| ----- | ---------------------- | ------------------------------------------------------------------ | +| AC1 | DONE | `Containerfile` uses `rust:slim-trixie`; full release build passed | +| AC2 | DONE | Chef implementation result package rationale | +| AC3 | DONE | Tester build/test evidence from M4 | +| AC4 | DONE | Before/after implementation-result tables | +| AC5 | DONE | Package inventory comparison from M5 | +| AC6 | DONE | GCC-stage comparison and runtime smoke test from M6 | +| AC7 | DONE | Independent commit history and stage-specific validation logs | +| AC8 | DONE | Consolidated build-image scan report from M7 | +| AC9 | DONE | Updated production scan report from M8 | +| AC10 | DONE | Updated security catalog entry | + +## Risks and Trade-offs + +- The full and slim images are mutable tags. Record resolved digests with every comparison + so later scans can explain changed results. +- APT-installing missing tools can gradually recreate the full image and transfer + maintenance from the upstream image to this Containerfile. The decision rule prevents + adopting slim when that trade-off is poor. +- Fewer packages and scanner findings reduce potential build-stage exposure, but do not + directly harden the published runtime image because chef is discarded after the build. +- Slim may expose undeclared native-tool assumptions in transitive Rust dependencies. Treat + those failures as useful dependency evidence and add only tools required by reproducible + failures. +- Base-image download and cold-build time should improve, while package installation adds a + network-dependent APT step. Compare cold builds if the net CI effect is material. +- The current cargo tool probe was performed on `linux/amd64`; CI and supported build + platforms must also succeed before closing the issue. + +## References + +- Parent EPIC: +- Original issue and comments: +- Related security-scanning issue: +- Trixie upgrade PR: +- Security analysis process issue: diff --git a/docs/pr-reviews/pr-2007-copilot-suggestions.md b/docs/pr-reviews/pr-2007-copilot-suggestions.md new file mode 100644 index 000000000..fd9abdba6 --- /dev/null +++ b/docs/pr-reviews/pr-2007-copilot-suggestions.md @@ -0,0 +1,62 @@ +--- +semantic-links: + skill-links: + - process-copilot-suggestions + related-artifacts: + - .github/skills/dev/pr-reviews/process-copilot-suggestions/SKILL.md +--- + + + + +# PR #2007 Copilot Suggestions Tracking + +Source: Copilot PR review threads for https://github.com/torrust/torrust-tracker/pull/2007 + +Status legend: + +- `action`: code/docs change applied +- `no-action`: suggestion reviewed; no code change needed +- `resolved`: thread resolved in PR + +## Workflow + +1. Download all review threads (including resolved/outdated state and thread IDs). +2. Add one row per thread in the Suggestions table. +3. Process suggestions one by one: + - decide `action` or `no-action` + - if `action`, apply change and validate + - if needed, commit changes + - resolve the PR thread +4. Set `Thread State` to `resolved` once resolved in PR. + +## Processing Log + +- 2026-07-20: Started processing suggestions. +- 2026-07-20: Completed processing suggestions (batch 1 — YAML + README). +- 2026-07-20: Completed processing suggestions (batch 2 — APT cache cleanup). +- 2026-07-20: Completed processing suggestions (batch 3 — cargo-nextest pinning, cspell, security README). +- 2026-07-21: Completed processing suggestions (batch 4 — broken link no-action, GCC casing fix); added explanatory replies to all batch 1–2 threads. + +## Suggestions + +| # | Thread ID | Path | URL | Suggestion Summary | Decision | Status | Thread State | +| --- | ----------------------- | ------------------------------------------------------------------------- | -------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------- | --------- | ------ | ------------ | +| 1 | `PRRT_kwDOGp2yqc6SUumy` | `.github/skills/dev/maintenance/run-manual-docker-security-scan/SKILL.md` | [comment](https://github.com/torrust/torrust-tracker/pull/2007#discussion_r3616188738) | YAML frontmatter `related-artifacts` list is malformed: `docs/security/analysis/build/` is not indented under `related-artifacts` | action | DONE | resolved | +| 2 | `PRRT_kwDOGp2yqc6SUunN` | `docs/security/analysis/README.md` | [comment](https://github.com/torrust/torrust-tracker/pull/2007#discussion_r3616188775) | README describes `review-date` but actual CVE docs use `date-analyzed` | action | DONE | resolved | +| 3 | `PRRT_kwDOGp2yqc6SWeDs` | `Containerfile` (chef stage) | [comment](https://github.com/torrust/torrust-tracker/pull/2007#discussion_r3616827507) | Missing `apt-get clean` in chef stage APT layer — .deb archives remain in the image | action | DONE | resolved | +| 4 | `PRRT_kwDOGp2yqc6SWeED` | `Containerfile` (tester stage) | [comment](https://github.com/torrust/torrust-tracker/pull/2007#discussion_r3616827539) | Missing `apt-get clean` in tester stage APT layer — .deb archives remain | action | DONE | resolved | +| 5 | `PRRT_kwDOGp2yqc6SWeEV` | `Containerfile` (gcc stage) | [comment](https://github.com/torrust/torrust-tracker/pull/2007#discussion_r3616827560) | Missing `apt-get clean` in gcc stage APT layer — .deb archives remain | action | DONE | resolved | +| 6 | `PRRT_kwDOGp2yqc6SW8iK` | `Containerfile` (chef stage) | [comment](https://github.com/torrust/torrust-tracker/pull/2007#discussion_r3616827507) | `cargo-nextest` installed without pinned version — non-reproducible build | action | DONE | resolved | +| 7 | `PRRT_kwDOGp2yqc6SW8in` | `project-words.txt` | [comment](https://github.com/torrust/torrust-tracker/pull/2007#discussion_r3616827507) | `Uumy` is an opaque thread ID fragment, not a stable project term — pollutes dictionary | action | DONE | resolved | +| 8 | `PRRT_kwDOGp2yqc6SW8jK` | `docs/pr-reviews/pr-2007-copilot-suggestions.md` | [comment](https://github.com/torrust/torrust-tracker/pull/2007#discussion_r3616827507) | Tracker file should use `` instead of adding ID fragments to global dictionary | action | DONE | resolved | +| 9 | `PRRT_kwDOGp2yqc6SW8jn` | `docs/security/README.md` | [comment](https://github.com/torrust/torrust-tracker/pull/2007#discussion_r3616827507) | Security overview still lists old build-stage base images (`rust:trixie`, `gcc:trixie`) | action | DONE | resolved | +| 10 | `PRRT_kwDOGp2yqc6SW8j-` | `Containerfile` (tester stage) | [comment](https://github.com/torrust/torrust-tracker/pull/2007#discussion_r3616827507) | `cargo-nextest` in tester stage also unpinned — non-reproducible test execution | action | DONE | resolved | +| 11 | `PRRT_kwDOGp2yqc6SX-aD` | `docs/security/docker/scans/build-images.md` | [comment](https://github.com/torrust/torrust-tracker/pull/2007#discussion_r3616827507) | Link targets `non-affecting/` path which does not exist after catalog reorganization | no-action | DONE | resolved | +| 12 | `PRRT_kwDOGp2yqc6SX-aS` | `docs/security/docker/scans/README.md` | [comment](https://github.com/torrust/torrust-tracker/pull/2007#discussion_r3616827507) | Stage column uses uppercase `GCC` — inconsistent with `gcc` in Containerfile and scan report | action | DONE | resolved | + +## Notes + +- Keep this file as an audit log of review handling for the PR. +- Prefer concise decisions with explicit rationale. +- If no code changes are needed, explain why in `Decision`. diff --git a/docs/security/README.md b/docs/security/README.md index 9e96cbd12..c1691cf31 100644 --- a/docs/security/README.md +++ b/docs/security/README.md @@ -37,7 +37,8 @@ When a security issue is detected (Docker Scout, dependabot, manual audit, conta **Documents**: - [Analysis README](analysis/README.md) — process and document index -- [Non-affecting CVEs](analysis/non-affecting/) — analyzed and accepted vulnerabilities +- [Non-affecting CVEs](analysis/production/) — analyzed and accepted vulnerabilities in the production runtime image +- [Build-stage CVEs](analysis/build/) — analyzed and accepted vulnerabilities in build-stage images --- @@ -53,7 +54,7 @@ This priority increases if the build images are ever used in a long-running serv **Scope**: -- Base build images: `rust:trixie`, `rust:slim-trixie`, `gcc:trixie` +- Base build images: `rust:slim-trixie` (chef + tester), `debian:trixie-slim` (gcc) - Rust dependency vulnerabilities (`cargo audit` / RustSec) - CI/CD pipeline security @@ -75,10 +76,13 @@ See [`docker/scans/README.md`](docker/scans/README.md) for the latest status of See [`analysis/README.md`](analysis/README.md) for cataloged vulnerability evaluations. -**Non-affecting CVE catalog**: [`analysis/non-affecting/`](analysis/non-affecting/) — +**Non-affecting CVE catalog**: [`analysis/production/`](analysis/production/) — per-CVE files documenting why each vulnerability does not affect the tracker and what conditions would change the verdict. +**Build-stage CVE catalog**: [`analysis/build/`](analysis/build/) — +per-CVE and bulk files documenting vulnerabilities in ephemeral build images. + ## Related Documentation - [Docker Image Security](docker/README.md) — scanning instructions and scan history diff --git a/docs/security/analysis/README.md b/docs/security/analysis/README.md index 1603635de..8319e2ce0 100644 --- a/docs/security/analysis/README.md +++ b/docs/security/analysis/README.md @@ -4,7 +4,8 @@ semantic-links: - catalog-security-vulnerabilities related-artifacts: - Containerfile - - docs/security/analysis/non-affecting/ + - docs/security/analysis/production/ + - docs/security/analysis/build/ - docs/adrs/20260603000000_keep_unit_tests_inside_container_build.md - docs/security/docker/scans/torrust-tracker.md --- @@ -29,8 +30,10 @@ container image vulnerability scanning), we create an analysis document here to: ```text docs/security/analysis/ ├── README.md # This file — index and process -├── non-affecting/ # Vulnerabilities that do NOT affect us -│ ├── CVE-{id}.md # Per-CVE files (preferred for individual CVEs) +├── production/ # CVEs in the production runtime image (release stage) +│ └── CVE-{id}.md # Per-CVE files +├── build/ # CVEs in build-stage images (chef, tester, gcc) +│ ├── CVE-{id}.md # Per-CVE files │ └── {date}_{source}.md # Bulk scan/event files (for bulk triage) └── affecting/ # (future) Vulnerabilities that DO affect us ``` @@ -38,48 +41,56 @@ docs/security/analysis/ ## Catalog Strategy We use **one catalog** for all vulnerability sources (Docker scans, cargo-audit, dependabot, -etc.). A vulnerability is a vulnerability regardless of origin. +etc.), organized by the impact context of the affected image. A vulnerability is a +vulnerability regardless of origin, but its risk profile depends on whether it appears in +the production runtime or in an ephemeral build stage. ### Per-CVE Files (preferred) -Individual CVEs from container scans are documented in their own file: +Individual CVEs from container scans are documented in their own file under the appropriate +subdirectory: ```text -non-affecting/ -├── CVE-2026-5435.md # glibc TSIG -├── CVE-2026-5450.md # glibc scanf -├── CVE-2026-5928.md # glibc ungetwc -├── CVE-2026-6238.md # glibc DNS response -└── CVE-2026-27171.md # zlib CRC32 +production/ +├── CVE-2026-5435.md # glibc TSIG — production runtime +├── CVE-2026-5450.md # glibc scanf — production runtime +├── CVE-2026-5928.md # glibc ungetwc — production runtime +├── CVE-2026-6238.md # glibc DNS response — production runtime +└── CVE-2026-27171.md # zlib CRC32 — production runtime + +build/ +├── CVE-2026-20889.md # libraw — chef/tester/gcc build stages +└── ... ``` **Advantages**: - `grep -r CVE-2026-5435` finds it instantly. - Fast to check "have we seen this before?" on any new scan. -- Each file carries its own `review-date`, `review-cadence`, and `requires-recheck-when` +- Each file carries its own `date-analyzed`, `review-cadence`, and `requires-recheck-when` in frontmatter. +- Impact context is immediately visible from the directory name. ### Bulk Scan/Event Files -For bulk triage (e.g. a full Docker Scout report with dozens of CVEs), a single event-based -file can be used instead of creating individual CVE files. Example: +For bulk triage (e.g. a full Docker Scout report with dozens of CVEs from build stages), +a single event-based file can be used instead of creating individual CVE files. Example: ```text -non-affecting/ -└── 2026-06-10_containerfile-trixie-cves.md # Bulk triage of 100+ CVEs +build/ +└── 2026-06-10_containerfile-trixie-cves.md # Bulk triage of 100+ build-stage CVEs ``` ## Process ### When a security warning appears -1. **Check the catalog**: `grep -r '' docs/security/analysis/non-affecting/` to +1. **Check the catalog**: `grep -r '' docs/security/analysis/` to see if this vulnerability has already been analyzed. If it has, verify the `requires-recheck-when` conditions still hold. If they do, you're done. -2. **If not yet cataloged**: create a new per-CVE analysis document in `non-affecting/` - following the template below. +2. **If not yet cataloged**: create a new per-CVE analysis document in the appropriate + subdirectory (`production/` or `build/`) following the template below. 3. **If it DOES affect us**: escalate immediately. Create an issue and a fix. The analysis document should describe the impact, affected components, and remediation plan. diff --git a/docs/security/analysis/non-affecting/2026-06-10_containerfile-trixie-cves.md b/docs/security/analysis/build/2026-06-10_containerfile-trixie-cves.md similarity index 68% rename from docs/security/analysis/non-affecting/2026-06-10_containerfile-trixie-cves.md rename to docs/security/analysis/build/2026-06-10_containerfile-trixie-cves.md index e010ca6df..ed98c7b2b 100644 --- a/docs/security/analysis/non-affecting/2026-06-10_containerfile-trixie-cves.md +++ b/docs/security/analysis/build/2026-06-10_containerfile-trixie-cves.md @@ -1,14 +1,15 @@ --- -date-analyzed: 2026-06-10 -source: Docker DX (docker-language-server) / Docker Scout +date-analyzed: 2026-07-20 +source: Trivy 0.69.3 / Docker DX (docker-language-server) status: non-affecting review-cadence: quarterly requires-recheck-when: any build-stage image (`chef`, `tester`, `gcc`) is used in a runtime context -image-digest: sha256:19dfb952582d0e17841fdb8cd70febfb6cb0761c4e0cd84f3cb1f07bb3281a8d +image-digest: sha256:5c6f46a6e4472ab1ca7ba7d494e6677f2f219ebc02f32025d3986f057635ec9c semantic-links: related-artifacts: - Containerfile - docs/adrs/20260603000000_keep_unit_tests_inside_container_build.md + - docs/security/docker/scans/build-images.md --- # Containerfile trixie-based image vulnerabilities @@ -19,42 +20,27 @@ The VS Code Docker DX extension (docker-language-server) flagged vulnerabilities `Containerfile` on the three `FROM` instructions that use Debian trixie-based base images. Line numbers drift as the file changes; the stages are the stable reference: -| Line (approx.) | Image | Stage | Purpose | -| -------------- | ------------------ | -------- | ------------------------------------- | -| 6 | `rust:trixie` | `chef` | Install `cargo-chef`, `cargo-nextest` | -| 15 | `rust:slim-trixie` | `tester` | Run unit tests inside container build | -| 32 | `gcc:trixie` | `gcc` | Compile `su-exec` from source | +| Image | Stage | Purpose | +| ---------------------- | -------- | ------------------------------------- | +| `rust:slim-trixie` | `chef` | Install `cargo-chef`, `cargo-nextest` | +| `rust:slim-trixie` | `tester` | Run unit tests inside container build | +| `debian:trixie-slim` | `gcc` | Compile `su-exec` from source | ## Vulnerability Summary -All three images are **upstream Docker Official Images** based on Debian trixie -(Debian 13/testing). The scanner reports CVEs in the OS-level packages shipped by -those images, not in anything we add. +All three stages use **upstream Docker Official Images** based on Debian trixie. The +implemented stages were rebuilt and scanned together on 2026-07-20 with Trivy 0.69.3 and +the vulnerability database updated at 2026-07-20 13:19:47 UTC. -| Image | C | H | M | L | Unspecified | Total | -| ------------------ | --- | --- | --- | --- | ----------- | ----- | -| `rust:trixie` | 4 | 26 | 27 | 178 | 27 | 262 | -| `rust:slim-trixie` | 1 | 6 | 6 | 84 | 1 | 98 | -| `gcc:trixie` | 4 | 31 | 27 | 182 | 27 | 271 | +| Stage | Debian packages | Critical | High | Medium | Low | Unknown | Total | +| -------- | --------------- | -------- | ---- | ------ | --- | ------- | ----- | +| `chef` | 145 | 4 | 65 | 309 | 617 | 77 | 1,072 | +| `tester` | 123 | 4 | 51 | 301 | 579 | 79 | 1,014 | +| `gcc` | 114 | 4 | 51 | 299 | 577 | 77 | 1,008 | -### Notable critical CVEs - -| CVE | CVSS | Package | -| -------------- | ---- | --------- | -| CVE-2026-20889 | 9.8 | `libraw` | -| CVE-2026-21413 | 9.8 | `libraw` | -| CVE-2026-45447 | 9.8 | `openssl` | -| CVE-2026-33278 | 9.1 | `unbound` | - -### Notable high-severity CVEs - -| CVE | CVSS | Package | -| -------------- | ---- | ----------------------- | -| CVE-2026-41142 | 8.8 | `openexr` | -| CVE-2026-42216 | 8.8 | `openexr` | -| CVE-2026-32740 | 8.8 | `libheif` | -| CVE-2026-42959 | 8.7 | `unbound` | -| CVE-2026-7383 | 8.1 | `openssl` (slim-trixie) | +These totals count findings, not unique CVEs. The chef stage also contains installed Cargo +tools, so Trivy scans both OS and language-specific files there. Detailed reproducibility, +image IDs, and base digests are maintained in the consolidated build-image scan report. ## Why This Does NOT Affect Us @@ -73,9 +59,9 @@ during `docker build` and are never: | Stage | Base image | Exposed to traffic? | Persisted after build? | | ----------- | ------------------------ | --------------------- | ---------------------- | -| `chef` | `rust:trixie` | ❌ No | ❌ No | +| `chef` | `rust:slim-trixie` | ❌ No | ❌ No | | `tester` | `rust:slim-trixie` | ❌ No | ❌ No | -| `gcc` | `gcc:trixie` | ❌ No | ❌ No | +| `gcc` | `debian:trixie-slim` | ❌ No | ❌ No | | **Runtime** | `distroless/cc-debian13` | ✅ Yes (UDP/HTTP/API) | ✅ Yes | ### 2. Runtime image is different @@ -88,7 +74,7 @@ but those are not present in this warning. ### 3. Upstream image trust boundary -All three flagged images are **Docker Official Images** (`library/rust`, `library/gcc`). +All three flagged images are **Docker Official Images** (`library/rust`, `library/debian`). We pull them from Docker Hub's official repository, which is the same trust boundary as any `FROM` statement in any Dockerfile. The CVEs exist in the upstream images themselves; they are not introduced by our Containerfile. @@ -112,16 +98,16 @@ the build image) could produce compromised binaries. However: | Action | Cadence | Owner | | -------------------------------------------------------------------- | ---------------------- | ----- | -| Monitor Docker Hub for updated `rust:trixie` and `gcc:trixie` images | Quarterly | TBD | +| Monitor Docker Hub for updated slim Rust and Debian images | Quarterly | TBD | | Rebuild container image and verify warning count decreases | After upstream updates | TBD | | Re-evaluate if these stages become part of the runtime image | On architecture change | TBD | | Check if Docker fixes these CVEs in fresh `trixie` tags | Next quarterly review | TBD | ## References -- Docker Hub `rust:trixie` (linux/amd64): -- Docker Hub `rust:slim-trixie` (linux/amd64): -- Docker Hub `gcc:trixie` (linux/amd64): +- Docker Hub `rust:slim-trixie` (linux/amd64): +- Docker Hub `debian:trixie-slim` (linux/amd64): +- Consolidated build-stage scan history: `docs/security/docker/scans/build-images.md` - ADR: Keep unit tests inside container build: `docs/adrs/20260603000000_keep_unit_tests_inside_container_build.md` @@ -141,3 +127,4 @@ the build image) could produce compromised binaries. However: | Date | Change | | ---------- | ------------------------------------------------ | | 2026-06-10 | Initial analysis — CVEs determined non-affecting | +| 2026-07-20 | Replaced stale bases and counts after issue #1463 | diff --git a/docs/security/analysis/non-affecting/CVE-2026-27171.md b/docs/security/analysis/production/CVE-2026-27171.md similarity index 100% rename from docs/security/analysis/non-affecting/CVE-2026-27171.md rename to docs/security/analysis/production/CVE-2026-27171.md diff --git a/docs/security/analysis/non-affecting/CVE-2026-5435.md b/docs/security/analysis/production/CVE-2026-5435.md similarity index 100% rename from docs/security/analysis/non-affecting/CVE-2026-5435.md rename to docs/security/analysis/production/CVE-2026-5435.md diff --git a/docs/security/analysis/non-affecting/CVE-2026-5450.md b/docs/security/analysis/production/CVE-2026-5450.md similarity index 100% rename from docs/security/analysis/non-affecting/CVE-2026-5450.md rename to docs/security/analysis/production/CVE-2026-5450.md diff --git a/docs/security/analysis/non-affecting/CVE-2026-5928.md b/docs/security/analysis/production/CVE-2026-5928.md similarity index 100% rename from docs/security/analysis/non-affecting/CVE-2026-5928.md rename to docs/security/analysis/production/CVE-2026-5928.md diff --git a/docs/security/analysis/non-affecting/CVE-2026-6238.md b/docs/security/analysis/production/CVE-2026-6238.md similarity index 100% rename from docs/security/analysis/non-affecting/CVE-2026-6238.md rename to docs/security/analysis/production/CVE-2026-6238.md diff --git a/docs/security/docker/README.md b/docs/security/docker/README.md index 384881088..49838ecb0 100644 --- a/docs/security/docker/README.md +++ b/docs/security/docker/README.md @@ -51,6 +51,23 @@ trivy image --severity HIGH,CRITICAL torrust-tracker:local trivy image --severity MEDIUM,HIGH,CRITICAL torrust-tracker:local ``` +### Build-stage scans + +Build and scan the foundational stages after changing their base images or installed +packages, and during the quarterly security review: + +```bash +for stage in chef tester gcc; do + docker build --target "$stage" --tag "torrust-tracker:$stage-local" \ + --file Containerfile . + trivy image --scanners vuln "torrust-tracker:$stage-local" +done +``` + +Record these results in [`scans/build-images.md`](scans/build-images.md), separately from +the deployed release image. Use the same Trivy version and vulnerability database for all +comparisons. + ### Severity Levels - `CRITICAL`: Exploitable vulnerabilities with severe impact diff --git a/docs/security/docker/scans/README.md b/docs/security/docker/scans/README.md index ae9614919..570011b49 100644 --- a/docs/security/docker/scans/README.md +++ b/docs/security/docker/scans/README.md @@ -4,9 +4,10 @@ Historical security scan results for the Torrust Tracker Docker image. ## Current Status Summary -| Image | Stage | MEDIUM | HIGH | CRITICAL | Status | Last Scan | Details | -| ----------------- | ------- | ------ | ---- | -------- | -------- | ------------ | -------------------------- | -| `torrust-tracker` | release | 5 | 0 | 0 | ✅ Clean | Jun 29, 2026 | [View](torrust-tracker.md) | +| Image | Stage | MEDIUM | HIGH | CRITICAL | Exposure | Last Scan | Details | +| ----------------- | --------------------- | ------- | ----- | -------- | ---------- | ------------ | -------------------------- | +| `torrust-tracker` | release | 5 | 0 | 0 | Production | Jul 20, 2026 | [View](torrust-tracker.md) | +| Build stages | `chef`/`tester`/`gcc` | 299-309 | 51-65 | 4 | Build only | Jul 20, 2026 | [View](build-images.md) | ## Build and Scan @@ -18,4 +19,8 @@ docker build -t torrust-tracker:local -f Containerfile . trivy image --severity HIGH,CRITICAL torrust-tracker:local ``` +Build stages are scanned after base-image or package changes and during quarterly review. +Their consolidated history is kept separate from production findings because they are +ephemeral, unpublished images. + See [`../README.md`](../README.md) for detailed scanning instructions. diff --git a/docs/security/docker/scans/build-images.md b/docs/security/docker/scans/build-images.md new file mode 100644 index 000000000..2d76666e8 --- /dev/null +++ b/docs/security/docker/scans/build-images.md @@ -0,0 +1,71 @@ +# Container Build Images - Security Scans + +Security scan history for the foundational `chef`, `tester`, and `gcc` stages in the +Torrust Tracker `Containerfile`. These images are ephemeral build inputs. They are not +published or deployed, so their findings must not be interpreted as production exposure. + +## Current Status + +| Stage | Base | Size | Debian packages | UNKNOWN | LOW | MEDIUM | HIGH | CRITICAL | Total | +| -------- | -------------------- | ---------- | --------------- | ------- | --- | ------ | ---- | -------- | ----- | +| `chef` | `rust:slim-trixie` | 1,067.4 MB | 145 | 77 | 617 | 309 | 65 | 4 | 1,072 | +| `tester` | `rust:slim-trixie` | 975.9 MB | 123 | 79 | 579 | 301 | 51 | 4 | 1,014 | +| `gcc` | `debian:trixie-slim` | 274.3 MB | 114 | 77 | 577 | 299 | 51 | 4 | 1,008 | + +## July 20, 2026 - Slim Build Stages + +- Trivy version: 0.69.3 +- Vulnerability database version: 2 +- Database updated: 2026-07-20 13:19:47 UTC +- Detected OS: Debian 13.6 +- Scan scope: OS and language-specific vulnerabilities reported by `trivy image --scanners vuln` + +### Image identities + +| Stage | Local image ID | +| -------- | ------------------------------------------------------------------------- | +| `chef` | `sha256:e8fac2fe73835c3c5a2762c4491dc48dd70fdfd03234955d9c28f67dcdd3aeda` | +| `tester` | `sha256:73696ee861456424ee3099d2c1a6b97071d93fb7a198ee28431e9d62dea30056` | +| `gcc` | `sha256:3ff67dd07ecdc8208a37c6628235ef8ebaebfa1d469a72d1a055d23cb80a0485` | + +The resolved base-image digests were: + +- `rust:slim-trixie`: `sha256:5c6f46a6e4472ab1ca7ba7d494e6677f2f219ebc02f32025d3986f057635ec9c` +- `debian:trixie-slim`: `sha256:020c0d20b9880058cbe785a9db107156c3c75c2ac944a6aa7ab59f2add76a7bd` + +### Comparison with replaced images + +| Stage | Previous image / result | Final image / result | Reduction | +| ------ | --------------------------------- | --------------------------------- | ------------------------------------------ | +| `chef` | 1,662.7 MB / 455 packages / 2,148 | 1,067.4 MB / 145 packages / 1,072 | 595.3 MB / 310 packages / 1,076 findings | +| `gcc` | 1,556.4 MB / 464 packages / 2,165 | 274.3 MB / 114 packages / 1,008 | 1,282.1 MB / 350 packages / 1,157 findings | + +The tester already used the slim Rust base. Its setup-only `curl` dependency is now purged; +the final stage retains `sqlite3`, `time`, and `cargo-nextest` and has 123 Debian packages. + +## Reproduction + +```bash +docker build --target chef --tag torrust-tracker:chef-local --file Containerfile . +docker build --target tester --tag torrust-tracker:tester-local --file Containerfile . +docker build --target gcc --tag torrust-tracker:gcc-local --file Containerfile . + +docker image inspect torrust-tracker:chef-local --format '{{.Id}} {{.Size}}' +docker run --rm --entrypoint dpkg-query torrust-tracker:chef-local \ + -W '-f=${binary:Package}\n' | wc -l +trivy image --scanners vuln torrust-tracker:chef-local +``` + +Repeat the inspect, package-query, and Trivy commands for `tester-local` and `gcc-local`. +Scanner totals are comparable only when the Trivy version and vulnerability database are +held constant. + +## Risk Context + +The stages run only during `docker build`, expose no services, and are discarded after the +release image is assembled. Their packages can still affect build-chain integrity, so they +are scanned after base or package changes and during quarterly review. Daily automation +continues to scan the separately documented production image. + +See the durable impact analysis in +[`../../analysis/build/2026-06-10_containerfile-trixie-cves.md`](../../analysis/build/2026-06-10_containerfile-trixie-cves.md). diff --git a/docs/security/docker/scans/torrust-tracker.md b/docs/security/docker/scans/torrust-tracker.md index 7bd374ad7..df1c3349e 100644 --- a/docs/security/docker/scans/torrust-tracker.md +++ b/docs/security/docker/scans/torrust-tracker.md @@ -6,7 +6,7 @@ Security scan history for the `torrust-tracker` Docker image. | Stage | MEDIUM | HIGH | CRITICAL | Status | Last Scan | | ------- | ------ | ---- | -------- | -------- | ------------ | -| release | 5 | 0 | 0 | ✅ Clean | Jun 29, 2026 | +| release | 5 | 0 | 0 | ✅ Clean | Jul 20, 2026 | ## Build & Scan Commands @@ -30,6 +30,24 @@ trivy image --severity MEDIUM,HIGH,CRITICAL torrust-tracker:local ## Scan History +### July 20, 2026 - Post-build-stage-minimization verification + +**Image**: `torrust-tracker:1463-gcc` +**Image ID**: `sha256:3b8859fd30f921d4be511efb5a9578252841c624bf3f895057cd46b795666687` +**Runtime base digest**: `gcr.io/distroless/cc-debian13@sha256:3be83724bcda99b72307e8d3cea256b3cfa5678b5198c1351bf66d2bc60d9cf9` +**Trivy Version**: 0.69.3 +**Vulnerability DB Updated**: 2026-07-20 13:19:47 UTC +**Base OS**: Debian 13.6 (trixie, distroless/cc-debian13) +**Status**: ✅ **Clean** - 5 MEDIUM, 0 HIGH, 0 CRITICAL + +The rebuilt release image is 188.6 MB and contains 13 OS packages. A full-severity scan +also reported 7 LOW findings, for 12 findings total. The five MEDIUM findings and affected +packages (`libc6` and `zlib1g`) are unchanged from the June baseline below. The independent +chef, tester, and GCC image reductions therefore did not regress the deployed artifact. + +The image was also started locally and its built-in health check returned repeated +`200 OK` responses with container status `healthy`. + ### June 29, 2026 - Baseline **Image**: `torrust-tracker:local` diff --git a/project-words.txt b/project-words.txt index 7b2405573..6f8ee347a 100644 --- a/project-words.txt +++ b/project-words.txt @@ -106,6 +106,7 @@ DNSSEC dockerhub doctest downloadedi +dpkg dtolnay dylib EADDRINUSE