Repository navigation
fix(docker): require the patched Debian Brotli decoder - #6956
Conversation
|
Changed-file classification: backend/runtime. Author-reported runtime / visual state
Checkboxes are author attestations. GitHub Actions results remain the execution evidence for CI; this check does not prove that a local command ran. This comment updates automatically when the description or changed files change. |
Refresh the signed Debian native Brotli package in a shared build-stage base and fail builds below the security backport floor. Verify the actual selected library, native fix marker, valid decoding, and distro Node linkage before accepting the runtime.
Check the inherited system CA store before the shared base makes its first HTTPS package request. Accept the exact fixed Debian 12 marker alongside Debian 13 while retaining package floors, decoder ownership, and valid decoding controls.
There was a problem hiding this comment.
🟡 Changes recommended
The Brotli checker drops subprocess error output and mishandles unexpected package statuses or incomplete records, producing missing or misleading build diagnostics.
2 open issues
What changed in this PR
Hardens Docker images against CVE-2026-111497 by requiring Debian’s patched native Brotli decoder while leaving the Node release line unchanged.
Changes:
- Adds a shared Brotli package layer for builder and runtime stages, checking inherited CA trust before HTTPS package requests.
- Validates Debian package revisions, decoder ownership, native fix markers, successful decoding, and Node’s library selection.
- Adds offline regression coverage for decoder acceptance and Docker guard ordering.
| File | Description |
|---|---|
tests/test_brotli_image_gate.py |
Tests package floors, decoder checks, Node linkage, and Docker guard ordering. |
scripts/check_brotli.py |
Implements Debian package and native decoder acceptance checks. |
Dockerfile |
Shares the guarded Brotli layer and rechecks Node’s decoder after system and Python dependencies. |
Review effort: Max
o3LL
left a comment
There was a problem hiding this comment.
Reviewed e2b0750 (merge-base 57a1859). Merge probe against current dev (0f996f5) is clean.
The gate looks right to me. Debian's tracker lists 1.0.9-2+deb12u1 / 1.1.0-2+deb13u1 as the fixed floors, and the Node-side upstream change (nodejs/node@a18ec92) only exposes the new error constant, so patching the system libbrotli1 is what actually closes this for Debian Node. I ran Node's regression vector from that commit through Debian Node 20.19.2 on 1.1.0-2+deb13u1 and got ERR__ERROR_FORMAT_BLOCK_SWITCH / -17.
Findings
- P3
suggestionnon-blocking: the-17error-string check proves the enum entry exists, not that the bounds check is there. By the time it runs the package floor has already passed, so it would be cheap to also stream the public vector from a18ec92 (200010414141fcffff07002228f00b60f7f41f000000) and requireBrotliDecoderGetErrorCode() == -17. That turns the marker into a behavioural check without changing what gets accepted today.scripts/check_brotli.py:69-77 - P3
nit:brotli-basealready copiescheck_ca_trust.pyto the same path, so theCOPYlines in both child stages are now redundant.Dockerfile:22,Dockerfile:73
Validation
- Ran:
brotli-basebuilt on arm64 and gated1.1.0-2+deb13u1.check-brotli.py --node /usr/bin/nodeaccepted Debian Node in that image. The new tests passed inside the Debian image (37 OK), and the full suite on macOS adds no failures beyond the merge-base. The Trivy job's amd64 build of this head logs all three gates as accepted. - Not run: a full arm64 image build (my local Docker VM ran out of disk), a container boot, Bookworm.
- Residual risk:
zlib.constants.BROTLI_DECODER_ERROR_FORMAT_BLOCK_SWITCHstaysundefinedin Debian Node 20 until Debian rebuilds it. Nothing in the repo reads it, anderr.codeis still set.
PR Hygiene: targets dev, template complete, both Copilot threads look addressed in e2b0750. Part of #6942 is right, since the issue asks for a Node bump this doesn't do. No overlapping PRs found.

Summary
Docker builds can retain an affected native Brotli decoder even when distro Node's own version is unchanged. Check inherited system CA trust before the first HTTPS package request, then refresh
libbrotli1from Debian's signed archives in a shared layer inherited by the wheel builder and runtime, then require Debian's fixed revision, the selected library's package ownership, either exact Debian 12/13 native fix marker spelling and a valid decoding control. Check that distro Node resolves to that same decoder after system dependencies and again after Python dependencies. This accepts Debian's security backports without treating their unchanged upstream version as an affected wheel. The Debian tracker documents the fixed floors and system-library linkage.Target branch
labin the private maintainer-preview repository, ordevin the public repository.mainremains release-curated.Linked Issue
Part of #6942
This covers CVE-2026-111497 in the native decoder selected by Debian Node. The Node release line is unchanged.
Type of Change
Checklist
labin maintainer-preview;devin the public repository)docker compose uporuvicorn app:app) and verified the change works end-to-end. Type-checks and unit tests are not enough.How to Test
python3 -m unittest tests.test_brotli_image_gate tests.test_ca_trust -v: 37 tests passed in an isolated container. These cover Debian 12/13 package-version boundaries, both fixed native marker spellings, unpatched and near-match markers, decoding controls, decoder selection and the first Docker RUN stopping before APT when its CA guard fails. Five added regressions cover failed package-query/ldd stderr, warnings from a successful query, non-installed package statuses, and malformed records. A broader local pytest invocation could not collect because that runner has no pytest installation.brotli-basetarget. Its log shows the system CA guard succeeding before the first HTTPS APT fetch, then acceptance oflibbrotli1 1.1.0-2+deb13u1. Reproduce withpodman build --target brotli-base ..libbrotli1=1.0.9-2+deb12u1over HTTPS using signed APT metadata. Extracted its native libraries and loaded them together in a fresh process: error -17 returned exactlyb"BLOCK_SWITCH", and the checker accepted that decoder and its valid-stream control. The rebuilt exact runtime system-package recipe also passed with Debian 13's fixed decoder and Node linkage. Runpython /usr/local/bin/check-brotli.py --node /usr/bin/nodein a built application image to check its effective selection.libbrotli1=1.1.0-2+b7. Its decoder failed the native fix-marker check, loading it throughLD_LIBRARY_PATHfailed the package-ownership check, and installing it failed the version-floor check. Updating through signed APT metadata to1.1.0-2+deb13u1restored acceptance.Visual / UI changes — REQUIRED if you touched anything that renders
Anything that changes what the UI looks like — buttons, icons, padding, colors, fonts, spacing, layout, CSS, HTML, SVG, or any
static/js/module that draws to the DOM — needs all of the following. PRs that change rendering without these WILL be closed.--red,--fg,--bg,--card,--border, etc.) — do not introduce new color values, font sizes, or spacing units.static/index.html) or plain text.Fira Code) for primary UI text. Don't override.Screenshots / clips
N/A: no UI or rendering changes.