Skip to content

build: upgrade the locked NGINX package to 1.30.5 - #36

Merged
joey-huckabee merged 1 commit into
mainfrom
build/nginx-1.30.5-security-refresh
Sep 18, 2026
Merged

joey-huckabee merged 1 commit into
mainfrom
build/nginx-1.30.5-security-refresh

Conversation

@joey-huckabee

Copy link
Copy Markdown
Contributor

Why: CVE-2026-90439, and it was reachable

Issue Buffer overflow when using map and regex
Severity major (NGINX's own rating)
Vulnerable 1.29.2 – 1.31.5
Fixed 1.30.5
Was pinned 1.30.4 — in range

All eleven profiles use exactly the affected construct:

map $http_x_request_id $correlation_id {
    "~^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$" $http_x_request_id;

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

Invariant Result
Packages 79 → 79, 0 added, 0 removed
Version changes nginx only
Source packages 59 → 59, 1 swapped
Signing identities unchanged
Repositories unchanged
AMD64 vs ARM64 identical names, versions, sources, base digests

The 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 -V
reports 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, so
that 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. --retry covers a transient error, not a
transfer 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
--retry can act on. A reviewed operation that can hang forever is worse than
one that fails.

A test had silently stopped testing. test_version_and_reviewed_input_drift_are_rejected
hardcoded nginx/1.30.4, so its replace became a no-op the moment the version
moved 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.md asserted the selected version was "not vulnerable to
its 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

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.
@joey-huckabee
joey-huckabee merged commit f15fdf8 into main Sep 18, 2026
5 checks passed
@joey-huckabee
joey-huckabee deleted the build/nginx-1.30.5-security-refresh branch September 18, 2026 05:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant