build: upgrade the locked NGINX package to 1.30.5 - #36
Merged
Merged
Conversation
CVE-2026-90439 is a major-severity buffer overflow when using `map` with a regular expression. It affects 1.29.2 through 1.31.5 and is fixed in 1.30.5. The pinned 1.30.4 was in range. This is not a routine version bump for this project. Every configuration profile validates the inbound correlation identifier with a regular-expression `map` over `$http_x_request_id`, so the affected construct evaluates a client-supplied header on every request in all eleven profiles. The control that exists to bound an untrusted value was sitting on the vulnerable path. By contrast, the two advisories fixed in 1.30.4 covered the slice and SSI modules, which no profile enables. An advisory against an unused module is a reason to schedule an update; this was a reason to make one promptly. Reviewed diff, identical on both architectures: 79 packages, none added or removed, `nginx` the only version change, signing identities and repositories unchanged. The builder base digest moved alongside it and, unlike the previous refresh, dragged nothing else with it. Local evidence covers bundle verification and component headers on both architectures plus the build, smoke and profile suites; the TLS suite needs openssl, which the local resolver environment lacks, so that evidence comes from CI. Three defects surfaced while running the procedure, each fixed rather than worked around: The resolver hung indefinitely on a stalled CDN connection with 31 of 59 source RPMs fetched. `--retry` covers a transient error, not a transfer that connects and then stops, so there was no path out. Added a connect timeout and a transfer-speed floor, which turns a stall into an error `--retry` can act on. A feature-inventory test hardcoded the pinned NGINX version, so its version-drift check became a no-op the moment the version moved — a test that silently stopped testing. It now reads the version from the inventory. The base-image binding test added with the requirement tree caught the Containerfile still pinning the previous builder digest while both locks had moved. That obligation had no test before that work; this is the first refresh it has seen, and it found the inconsistency. Also corrected the package-source record, which asserted that the previously selected version was not vulnerable to its current 1.30-series advisories. That stopped being true when this CVE published, and a stale advisory claim is worse than none.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why: CVE-2026-90439, and it was reachable
mapand regexAll eleven profiles use exactly the affected construct:
That regex evaluates a client-supplied header on every request. The control
added to bound an untrusted value was sitting on the vulnerable path.
Worth the contrast: the two advisories fixed in 1.30.4 covered the slice and
SSI modules, which no profile enables. An advisory against an unused module is a
reason to schedule an update. This one was a reason to make one promptly.
The scheduled input-drift check from #33 reported 1.30.5 the week it published —
one PR after being written.
Reviewed lock diff (step 6), identical on both architectures
nginxonlyThe builder base digest moved alongside, and unlike the previous refresh it
dragged nothing else with it.
Evidence
Local: both bundles acquired and verified, all 79 component headers checked
against real RPMs on both architectures, image built hermetically,
nginx -Vreports 1.30.5 with an identical feature and module set, smoke and profile
suites pass.
The TLS suite needs
openssl, which the local resolver environment lacks, sothat evidence comes from CI rather than from me.
Three defects found by running the procedure
The resolver hung indefinitely. A stalled CDN connection, 31 of 59 source
RPMs in, no progress for minutes.
--retrycovers a transient error, not atransfer that connects and then stops — there was no path out. Fixed with a
connect timeout and a transfer-speed floor, which converts a stall into an error
--retrycan act on. A reviewed operation that can hang forever is worse thanone that fails.
A test had silently stopped testing.
test_version_and_reviewed_input_drift_are_rejectedhardcoded
nginx/1.30.4, so itsreplacebecame a no-op the moment the versionmoved and the assertion could never fire. It now reads the version from the
inventory, so it cannot rot that way again.
The base-binding test earned its place. The check added with the requirement
tree in #29 — the one obligation that had no test before that work — caught the
Containerfile still pinning the previous builder digest while both locks had
moved. First refresh it has seen, and it found the inconsistency.
Corrected claim
docs/PACKAGE-SOURCE.mdasserted the selected version was "not vulnerable toits current 1.30-series advisories". That stopped being true when this CVE
published. Replaced rather than amended, with a section recording why the
candidate moved. A stale advisory claim is worse than none.
🤖 Generated with Claude Code