Skip to content

Turn off APT retries before the unproved APT paths (.github#295) - #1197

Merged
rmcdaniel merged 2 commits into
mainfrom
fix/295-apt-retries
Nov 13, 2026
Merged

rmcdaniel merged 2 commits into
mainfrom
fix/295-apt-retries

Conversation

@rmcdaniel

Copy link
Copy Markdown
Member

Refs durable-workflow/.github#295 (CVE-2026-109518), for the server's two unprotected APT paths named in General's org audit.

Change

  • scripts/perf/Dockerfile.fpm-experiment (parent php:8.3.35-fpm-trixie@ea1c5007, likely apt 3.0.3, below Trixie's 3.0.4 floor) and scripts/conformance/worker-versioning-mixed.Dockerfile (unpinned python:3.13-slim) now write Acquire::Retries "0"; to /etc/apt/apt.conf.d/99-no-retries in the same RUN, before their first apt-get. Without retries, the CVE's redirect-on-retry path can't happen, whatever the parent's apt version.
  • tests/Unit/Support/apt_no_retries_test.py, adapted from cli#143's test for Dockerfiles:
    • Rule: for every tracked Dockerfile, each build stage's first networked APT command (update/install/upgrade/dist-upgrade/full-upgrade) must come after either require-fixed-apt.sh (the production Dockerfile's reviewed fixed-floor proof) or Acquire::Retries "0".
    • Self-check: proves a late guard, a missing guard and a guard in a previous stage are all refused.
    • Fails without the fix: it failed on exactly these two paths before the Dockerfile changes.
  • .github/workflows/public-boundary.yml: one added line runs that test next to the Docker workflow isolation test. Public Boundary runs on every pull request, merge group and push.

Checked

  • apt-config dump in a --network none container reports Acquire::Retries "0"; after the written line.
  • The production Dockerfile is unchanged; it already runs require-fixed-apt.sh before each APT stage.

🤖 Generated with Claude Code

….github#295)

CVE-2026-109518: a vulnerable APT can follow a redirect on a retried package
download and install a swapped package as root. The perf FPM experiment
image (php:8.3.35-fpm-trixie, likely apt 3.0.3) and the worker-versioning
conformance image (unpinned python:3.13-slim) now write
Acquire::Retries "0" before their first APT network call. The production
Dockerfile already proves the fixed floor with require-fixed-apt.sh.

A new test, run by Public Boundary on every change, refuses any tracked
Dockerfile stage whose first networked APT command has neither guard before
it. It failed on exactly these two paths before the change.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…rable-workflow/.github#295)

phpunit-feature.yml builds an inline Dockerfile from the base stage that
runs apt-get. Its APT is the base's, already proved at the fixed floor, but
nothing showed that at the call. The inline stage now re-runs
require-fixed-apt.sh before its apt-get, as the production stage does. The
APT test also reads Dockerfiles inlined in workflows; it flags the old
workflow and passes the new one.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@rmcdaniel

Copy link
Copy Markdown
Member Author

Security PASS at b5a0c48 (CI 67 passed, 1 skipped).

  • Dockerfiles: Dockerfile.fpm-experiment and worker-versioning-mixed.Dockerfile write Acquire::Retries "0"; in the same RUN, before apt-get update. The production Dockerfile keeps require-fixed-apt.sh before each apt stage.
  • Test: apt_no_retries_test.py builds its file list from git ls-files, splits each file per FROM stage, and checks order within the same RUN. That's stricter than the other repos' tests. I ran it locally at this head: it passes, and its self-checks refuse a late guard, a missing guard and a guard in a previous stage. It runs in Public Boundary on every PR, merge group and push.

Non-blocking: .github/workflows/phpunit-feature.yml:288 builds an inline heredoc Dockerfile with apt-get update && apt-get install git jq. It's safe today because it's FROM durable-workflow-server-phpunit-base, the production Dockerfile's base stage, which already passed require-fixed-apt.sh and so carries the fixed apt. But the test can't see inline heredoc Dockerfiles. Either add the retries line there for consistency, or note the inheritance in a comment.

@rmcdaniel

Copy link
Copy Markdown
Member Author

Security PASS at fb82c13, on green CI. This replaces my b5a0c48 comment. The only change from b5a0c48 covers the inline phpunit-feature.yml stage I noted: it now re-runs require-fixed-apt.sh before its apt-get update, as the production stages do. apt_no_retries_test.py now also scans .github/workflows/*.y*ml for inline FROM stages, with a self-check for an unguarded inline heredoc. Every networked apt path in the repo, including inline Dockerfiles, is now guarded and tested.

@rmcdaniel
rmcdaniel enabled auto-merge November 13, 2026 04:47
@sonarqubecloud

Copy link
Copy Markdown

@rmcdaniel
rmcdaniel added this pull request to the merge queue Nov 13, 2026
Merged via the queue into main with commit 6d00b85 Nov 13, 2026
68 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant