Skip to content
KitploitKITPLOIT
ToolsBlog
Submit
ToolsBlog
Submit

Hacking, PenTest, and Cybersecurity Tools for Your Security Arsenal!

Kitploit is a directory of hacking, cybersecurity, and pentesting tools. Discover the latest project updates to find vulnerabilities, analyze systems, automate testing, and strengthen your security.

··Feeds·Contact·Privacy·© 2026 Kitploit

Tool Directory

Categories

View all categories
Loading categories
nginx-cve-fix — Source-built nginx 1.25.5 container with backported CVE-2026-42945 fix, OpenSSL bump, full provenance chain, and VEX attestation. | Kitploit
Tools/GitHubGitHub/barappteam/nginx-cve-fix
Vulnerability ScannersContainer SecurityVulnerability AnalysisConfiguration AuditingDevSecOpsSupply Chain Security
GitHubbarappteam/nginx-cve-fix

nginx-cve-fix

Source-built nginx 1.25.5 container with backported CVE-2026-42945 fix, OpenSSL bump, full provenance chain, and VEX attestation.

View Repository
3 months agoNot yet reviewed

Most Popular

View all →

Discover the most used tools by our community.

Explore all tools

Browse our collection of tools

View all tools →
Share

Nginx CVE Fix - Source-Built Drop-in for nginx:1.25-bookworm

A source-built nginx 1.25.5 container image that remediates two CVEs present in the official nginx:1.25-bookworm image while preserving upstream runtime behavior.

CVEComponentSeverityTechniqueVerification model
CVE-2024-6119OpenSSL / libssl3HighDependency version bumpScanner-verifiable: libssl3 3.0.20 visible in dpkg database
CVE-2026-42945nginx ngx_http_rewrite_moduleCriticalBackported source patchProvenance-verifiable: patch derivation + regression test + build attestation + VEX

These represent two distinct remediation models:

  1. Version bump (CVE-2024-6119) - the fixed library version is directly visible to scanners via the dpkg database. No additional attestation needed.
  2. Source backport (CVE-2026-42945) - the package version remains 1.25.5, so scanners cannot distinguish the patched binary from an unpatched one. Remediation is demonstrated through source provenance, build-time verification, and regression testing. VEX provides the scanner-layer signal.

Parity status

The nginx -V configure arguments of this image match those of nginx:1.25-bookworm (compared character-by-character after normalizing the -ffile-prefix-map build path; verified in test/compat.py::test_nginx_version). The test suite (make test) validates 89 assertions covering image metadata, dynamic modules, filesystem layout, entrypoint behavior, dpkg packaging, and HTTP request handling against the live upstream image.

Known differences from upstream (not validated as identical):

  • The built with OpenSSL X.X.X line in nginx -V reflects the builder's libssl-dev version, which may differ from upstream's compile-time OpenSSL.
  • Binary content is not byte-for-byte identical (different compilation environment, different toolchain invocation timestamps).
  • The image package set differs - debian:bookworm-slim base rather than the official image's inherited package tree.
  • Runtime libssl3 version is whatever bookworm currently provides (3.0.20 at time of writing), not the pinned version in the upstream image.

Quick Start

root@kitploit:~
# Build everything (builder → .deb → final image)
make image

# Run automated compatibility tests
make test

# Run CVE-2026-42945 regression test
make test-cve

# Verify patch provenance (re-derives from upstream tarballs)
make verify-patch

# Scan and demonstrate VEX
make scan

One command to build, test, and scan:

root@kitploit:~
make all

Repository Structure

root@kitploit:~
build/
  Dockerfile.build          Builder image (debian:bookworm-slim + compilation deps)
  build.sh                  Fetch → verify → patch → compile → package nginx
  generate-vex.sh           Generate OpenVEX document for backported CVE
  verify-patch.sh           Re-derive patch from upstream tarballs (audit tool)
  patches/
    CVE-2026-42945.patch           Backported one-line fix from nginx 1.30.1
    CVE-2026-42945.provenance.json Machine-readable patch provenance and derivation metadata

test/
  compat.py                 89-assertion compatibility test suite (runs against live upstream)
  test_cve_2026_42945.py    CVE-specific regression test (exercises vulnerable code path)

artifacts/
  patch-attestation.json    Build-time patch attestation (tracked)
  nginx_*.deb               Compiled package (gitignored - rebuilt via `make build-source`)
  nginx                     Compiled binary (gitignored)
Containerfile               Final runtime image definition
Makefile                    Orchestrates build → test → scan pipeline
vex.json                    Generated OpenVEX v0.2.0 document
baseline-trivy.txt          Point-in-time Trivy scan of nginx:1.25-bookworm
baseline-grype.txt          Point-in-time Grype scan of nginx:1.25-bookworm
fixed-trivy.txt             Trivy scan of the fixed image
fixed-grype.txt             Grype scan of the fixed image (without VEX)
fixed-grype-vex.txt         Grype scan of the fixed image (with VEX applied)

Build Process

Architecture

root@kitploit:~
debian:bookworm-slim (builder)
  └─ build.sh
       ├─ curl nginx-1.25.5.tar.gz (SHA256-verified)
       ├─ curl njs-0.8.4 from github.com/nginx/njs
       ├─ patch -p1 < CVE-2026-42945.patch
       ├─ ./configure (flags identical to upstream nginx -V)
       ├─ make: release binary, debug binary, 4 dynamic module families (×2 release/debug)
       ├─ make: NJS modules (×2 release/debug) + njs CLI binary
       └─ dpkg-deb → nginx_1.25.5-1~bookworm+echo1_<arch>.deb

debian:bookworm-slim (runtime)
  ├─ apt-get install runtime deps (libssl3 ≥ 3.0.14 enforced)
  ├─ dpkg -i nginx_*.deb
  └─ COPY --from=upstream /docker-entrypoint.sh + /docker-entrypoint.d/

The Containerfile does NOT copy /etc/nginx from upstream. All configuration files are shipped inside the .deb and tracked by dpkg's conffile mechanism. This is required for the 10-listen-on-ipv6-by-default.sh entrypoint script, which uses dpkg-query to detect whether default.conf has been user-modified.

Integrity Guarantees

  • Source tarballs: All source archives (nginx, NJS) are SHA256-verified against hardcoded hashes before extraction. Build aborts on mismatch.
  • Build from source: ./configure && make inside a clean Debian container. No upstream binaries, no apt install nginx.
  • No network access during compilation: dependencies are installed in the builder Docker image layer; build.sh only fetches pinned source archives.

Reproducibility

The build is mostly reproducible but not hermetic:

  • nginx source version and SHA256 are pinned and verified before extraction.
  • NJS version and SHA256 are pinned and verified before extraction.
  • Builder dependencies are enumerated in Dockerfile.build but not version-pinned.
  • Debian runtime packages are resolved from live bookworm repositories at build time, so minor versions can drift between builds.

To improve reproducibility, pin the base image digest:

root@kitploit:~
docker pull debian:bookworm-slim
docker inspect debian:bookworm-slim --format='{{index .RepoDigests 0}}'
# Then use: FROM debian:bookworm-slim@sha256:<digest>

CVE Remediation Details

CVE-2024-6119 - OpenSSL Version Bump

How the fix works:

The .deb package declares Depends: libssl3 (>= 3.0.14), which forces apt-get install to pull an OpenSSL version that includes the fix. The current Debian bookworm repositories provide 3.0.20, which fixes CVE-2024-6119 and dozens of other OpenSSL CVEs from the baseline (CVE-2024-2511, CVE-2024-5535, CVE-2024-4741, CVE-2023-5678, CVE-2023-6129, CVE-2023-6237, CVE-2024-9143, CVE-2025-15467, CVE-2025-69420).

Scanner behavior: Grype and Trivy see libssl3 3.0.20 in the dpkg database and recognise that 3.0.20 ≥ 3.0.14, so CVE-2024-6119 is no longer reported. No VEX needed - the version bump is self-evident.

Verification:

root@kitploit:~
grep "CVE-2024-6119" baseline-grype.txt  # present
grep "CVE-2024-6119" fixed-grype.txt     # absent

CVE-2026-42945 - Backported Patch

Vulnerability:

ngx_http_script_regex_end_code() in src/http/ngx_http_script.c failed to reset e->is_args when processing a rewrite regex result. If is_args was set by a preceding script engine operation, subsequent buffer length calculations in the redirect/rewrite path would be incorrect, causing a heap buffer overflow of attacker-controlled size via crafted request URIs.

The fix (one line):

root@kitploit:~
// Added before the existing e->quote = 0; at line 1205
e->is_args = 0;

Patch provenance:

How the patch was created:

  1. Downloaded nginx-1.25.5.tar.gz (SHA256 verified against pinned hash)
  2. Downloaded nginx-1.30.1.tar.gz (SHA256 verified: 99765000d974896b31ca5882d8c279ce3fe7ef6f5c6f9f0a967ed7fd3407f9cc)
  3. Ran diff src/http/ngx_http_script.c between the two trees
  4. The diff produced exactly one line - the e->is_args = 0; addition
  5. Extracted as a unified diff patch with context lines
  6. Verified the patch applies cleanly to nginx 1.25.5
  7. Both source trees are retained in research/ for independent verification

Regression testing:

The test suite test/test_cve_2026_42945.py exercises the vulnerable code path by sending requests through rewrite rules that manipulate query string state (is_args). It validates:

  • Rewrite redirects with trailing ? (query strip) produce well-formed responses
  • Chained rewrites that toggle is_args state don't crash the worker
  • Long query strings (4KB+) don't cause buffer overflow artifacts (null bytes, overlong Location headers)
  • 100 rapid mixed requests don't cause worker crashes
  • The worker process survives all test cases without SIGSEGV or heap corruption

Run: make test-cve

Scanner behavior:

Because the package version remains 1.25.5, scanners will flag CVE-2026-42945 when the advisory is present in their database. This is expected - scanners match by (package-name, upstream-version) and cannot inspect whether source has been patched. The VEX document suppresses this finding with machine-readable justification. The scanner suppression is a communication mechanism, not the primary evidence of remediation. The primary evidence is the patch provenance chain and regression test above.


VEX (Vulnerability Exploitability eXchange)

Why VEX is needed

Scanners identify packages by (name, version) from the dpkg database. Our package is nginx 1.25.5-1~bookworm+echo1 - scanners parse this as upstream version 1.25.5 and flag all CVEs affecting nginx ≤ 1.25.5.

For backported fixes, the scanner cannot determine that the vulnerable code has been patched. The version intentionally remains 1.25.5 to preserve package compatibility. VEX provides a machine-readable attestation that the CVE has been addressed, linked to verifiable evidence.

VEX credibility chain

The VEX statement for CVE-2026-42945 is NOT mere paperwork. It is backed by:

  1. Patch provenance - build/patches/CVE-2026-42945.provenance.json documents the exact upstream source, derivation method, and file hashes
  2. Build-time verification - build.sh asserts the fix marker is present in the compiled source, aborting the build on failure
  3. Build attestation - artifacts/patch-attestation.json records pre/post-patch file hashes generated during the build
  4. Regression test - test/test_cve_2026_42945.py exercises the vulnerable code path without crash or corruption
  5. Independent re-derivation - make verify-patch downloads both upstream tarballs and demonstrates the committed patch is the minimal security diff

What the VEX covers

CVEStatusJustificationEvidence
CVE-2026-42945fixedvulnerable_code_not_presentBackport patch + provenance + regression test + build gate

The VEX scope is intentionally narrow: only CVEs that this project actively remediated with verifiable evidence are covered. Findings that are merely "expected to be mitigated" by the shipped version are not suppressed - this avoids using VEX as a blanket suppression tool.

How it works

The build/generate-vex.sh script produces an OpenVEX v0.2.0 document. The scanner command to apply it:

root@kitploit:~
# Without VEX - CVE is reported (version-based match):
grype nginx-fixed > fixed-grype.txt

# With VEX - CVE is suppressed with justification:
grype nginx-fixed --vex vex.json > fixed-grype-vex.txt

Scanner evidence

The VEX suppression is observable in saved scan artifacts. Note that scanner databases are rebuilt periodically and CVE presence may vary between runs. The saved baseline-grype.txt and fixed-grype.txt files are point-in-time evidence. The VEX document's validity does NOT depend on scanner DB state - it is independently verifiable via the provenance chain above.


Scanner Integrity

Package naming decision

The package is named nginx (not nginx-custom). This is critical because:

  1. Honest reporting: If the package were renamed, scanners would not recognise it as nginx and ALL nginx CVEs would silently vanish - including unfixed ones. That's a false sense of security.
  2. VEX demonstration: VEX can only suppress a CVE that the scanner actually reports. Renamed packages make VEX unnecessary (and untestable).
  3. Package management: Naming it nginx allows it to satisfy dependencies and be managed by standard Debian tooling.

Scanner database volatility

Scanner advisory databases are rebuilt periodically. A CVE present one week may be absent the next. This project does NOT rely on scanner output as the primary proof of remediation. The evidence chain is:

  1. Patch provenance (verifiable independently of any scanner)
  2. Build-time attestation (generated during compilation)
  3. Regression test (exercises the vulnerable code path)
  4. VEX suppression (scanner-layer acknowledgment)

Saved scan files are point-in-time evidence only.

What scanners see (fixed image)

PackageVersionCVE-2024-6119CVE-2026-42945
libssl33.0.20-1~deb12u1Not reported (fixed by version)n/a
nginx1.25.5-1~bookworm+echo1n/aReported when in DB (backport invisible to scanner)

With --vex vex.json, the CVE-2026-42945 finding (if present in the scanner DB) is suppressed. The VEX document's validity is established by the provenance chain (patch derivation, build attestation, regression test), not by scanner output alone.


Compatibility Test

The test suite (test/compat.py) boots both nginx:1.25-bookworm and nginx-fixed as Docker containers and compares behavior. Each assertion directly tests the live fixed image against the live upstream image.

89 assertions. All passing.

Additionally, test/test_cve_2026_42945.py provides ~20 assertions specifically targeting the backported CVE fix (see "Regression testing" above).

What is NOT tested

  • HTTP/3 QUIC protocol behavior (only the --with-http_v3_module flag presence is verified; no UDP/QUIC traffic is sent)
  • Performance or latency characteristics under load
  • All possible nginx configuration directives
  • Behavior of seldom-used dynamic modules (GeoIP, image_filter, XSLT) beyond verifying the .so files are present on disk

Run:

root@kitploit:~
make test

Image Size

ImageSize (arm64, docker images)
nginx:1.25-bookworm~278 MB
nginx-fixed~332 MB

The fixed image is larger than upstream. This is expected: the official image uses pre-compiled binaries in optimized layers, while ours installs build artifacts and full runtime dependencies (including libraries for all 12 dynamic modules) into a debian:bookworm-slim base. The size difference is a tradeoff for source-level build control, not a regression in functionality.


Residual Risk Assessment

CVEs remaining in the fixed image

The fixed image still contains vulnerabilities in system libraries not addressed by this project (point-in-time; run make scan for current state):

These are inherited from debian:bookworm-slim and are outside the scope of this project's nginx-focused CVE remediation.

Limitations of this approach

  1. Not hermetic. Base image and apt packages are resolved at build time from live Debian repositories. Pinning the base image SHA and using apt snapshots would improve reproducibility.
  2. No behavioral QUIC testing. HTTP/3 support is compiled in (verified by flag) but no QUIC traffic is exercised in the test suite.
  3. No performance validation. The 50-concurrent-request test proves correctness, not throughput or latency equivalence.
  4. Module loading only. Dynamic modules (GeoIP, image_filter, XSLT) are verified to be present and loadable, but their feature behavior is not exercised beyond basic load.
  5. Single-architecture evidence. Tests run on the build host architecture only (arm64 in development; would need CI for multi-arch).

Future improvements (not implemented)

  1. Pin base image digest and use apt snapshot URLs for hermetic builds.
  2. Strip unnecessary packages (ncurses, util-linux) pulled as transitive deps.
  3. Generate SBOM (make sbom target exists, uses syft) and link to VEX via SBOM purl.
  4. Sign the image with cosign and attach VEX + SBOM + patch-attestation as OCI attestations.
  5. Add CI pipeline (GitHub Actions) for automated build → test → scan → push.
  6. Add HTTP/3 protocol test (QUIC client, certificate setup, UDP port).
  7. Consider distroless base to eliminate OS-level CVE noise entirely.
  8. Add ASan (AddressSanitizer) build variant to prove no heap corruption under test load.

Build Flags vs. Upstream

The ./configure flags in build.sh are identical to those reported by nginx -V in the official nginx:1.25-bookworm image. This is verified by test/compat.py::test_nginx_version, which normalizes the -ffile-prefix-map=<path> difference and compares the remaining flags character-by-character.

Noteworthy flags (all present in both images):


Debian Package

The .deb package metadata:

root@kitploit:~
Package: nginx
Version: 1.25.5-1~bookworm+echo1
Depends: libc6 (>= 2.34), libcrypt1 (>= 1:4.1.0), libpcre2-8-0 (>= 10.22),
         libssl3 (>= 3.0.14), zlib1g (>= 1:1.2.11), libgeoip1 (>= 1.6.12),
         libgd3 (>= 2.1.0~alpha~), libxml2 (>= 2.7.4), libxslt1.1 (>= 1.1.25),
         lsb-base (>= 3.0-6), adduser
Provides: httpd, nginx, nginx-r1.25.5
Conflicts: nginx-common, nginx-core
Replaces: nginx-common, nginx-core

Key packaging decisions:

  • libssl3 (>= 3.0.14) - explicitly requires patched OpenSSL (upstream declares >= 3.0.0). This is the mechanism that enforces CVE-2024-6119 fix.
  • Provides: nginx-r1.25.5 - satisfies dynamic module packages that depend on this virtual package.
  • Conffiles registered with dpkg: /etc/nginx/nginx.conf and /etc/nginx/conf.d/default.conf. This is required for the IPv6 entrypoint script's dpkg-query --showformat check.
  • postinst creates nginx user/group with uid/gid 101 and shell /bin/false (matching upstream - verified in test suite).
  • Ships: nginx binary, nginx-debug binary, all 12 .so modules, full /etc/nginx config tree, init.d/systemd/logrotate files, man page, HTML defaults, and /etc/nginx/modules → /usr/lib/nginx/modules symlink.

Design Decisions and Tradeoffs

  1. Package named nginx, not nginx-custom. If renamed, scanners would not match it against nginx advisories - all nginx CVEs would silently disappear from reports, including unfixed ones. Keeping the name nginx ensures honest scanner reporting and makes VEX meaningful.

  2. VEX requires CVE visibility. The purpose of VEX is to suppress a CVE that is already reported. If the scanner doesn't find the CVE (due to package renaming or DB timing), VEX has nothing to suppress.

  3. libssl3 (>= 3.0.14) as package dependency. Rather than hoping the runtime base happens to have a patched OpenSSL, the .deb hard-requires a version that contains the fix for CVE-2024-6119.

  4. Scanner database volatility. Advisory databases rebuild periodically. A CVE present one week may be absent the next. The saved scan files in this repo are point-in-time evidence; current scans may differ.

  5. AI tools used. GitHub Copilot assisted with patch analysis (comparing nginx 1.25.5 and 1.30.1 source trees), test suite structure, identifying the package-rename scanner evasion issue, and VEX document authoring. Debian packaging details and Grype version-matching heuristics required manual verification.

Download Tool
FieldValue
ComponentOpenSSL / libssl3
SeverityHigh (CVSS 7.5)
TypeDenial of Service via X.509 name checks
Baseline version3.0.11-1~deb12u2
Fixed version3.0.14-1~deb12u2 (or later)
Our version3.0.20-1~deb12u1
NVDhttps://nvd.nist.gov/vuln/detail/CVE-2024-6119
Advisoryhttps://openssl-library.org/news/secadv/20240903.txt
FieldValue
Componentnginx ngx_http_rewrite_module
SeverityMedium (nginx.org classification)
Baseline versionnginx 1.25.5
Fixed innginx 1.30.1 (released 2026-05-13)
NVDhttps://nvd.nist.gov/vuln/detail/CVE-2026-42945
Advisoryhttps://my.f5.com/manage/s/article/K000161019
Upstream CHANGESnginx 1.30.1 CHANGES: "heap memory buffer overflow in rewrite module"
EvidenceLocation / Value
Upstream commit2046b45aa0c6e712c216b9075886f3f26e9b4ca9
Upstream authorRoman Arutyunyan (arut), committed by Sergey Kandaurov (pluknet), 2026-05-13
Upstream PRnginx/nginx#1350
Upstream tagsrelease-1.31.0, release-1.30.1
Related prior fix74d9399 (2012, similar is_args escaping issue)
Patch filebuild/patches/CVE-2026-42945.patch
Provenance metadatabuild/patches/CVE-2026-42945.provenance.json
Source tarball (vulnerable)https://nginx.org/download/nginx-1.25.5.tar.gz SHA256:2fe2294f8af4144e7e842eaea884182a84ee7970e...
Source tarball (fixed)https://nginx.org/download/nginx-1.30.1.tar.gz SHA256:99765000d974896b31ca5882d8c279ce3fe7ef6f...
Vulnerable file SHA256c4b10c95b00e43d731a61f2380d406155e037f3cfb40a3bf58711ecefddc799a
Fixed file SHA256a6182175a22d88f66b9a61ae051bdcfece10d1bb2e643f7f175eb07589143403
Derivation methoddiff src/http/ngx_http_script.c between the two tarballs (confirmed identical to upstream commit)
Lines changed1 (addition only)
Patch applies cleanlyVerified: patch --dry-run -p1 < build/patches/CVE-2026-42945.patch exits 0
Build-time verificationbuild.sh verifies e->is_args = 0 is present in source after patching, aborts build if not
Build-time attestationWritten to artifacts/patch-attestation.json during build
Regression testtest/test_cve_2026_42945.py - exercises the vulnerable code path
Patch verification scriptmake verify-patch - independently re-derives the patch from upstream tarballs
CategoryWhat is comparedAssertion count
Image metadataEntrypoint, Cmd, ExposedPorts, User, StopSignal, Env, Labels7
nginx -V argumentsConfigure flags identical (normalized for -ffile-prefix-map path)1
Dynamic modulesAll 12 upstream .so files present + /etc/nginx/modules symlink13
nginx-debug binary--with-debug and --with-http_v3_module present in debug -V2
Filesystem layout~20 key paths, log symlinks to /dev/stdout and /dev/stderr~20
User/group configgetent passwd/group nginx output identical2
dpkg conffilesdpkg-query reports default.conf and nginx.conf as conffiles1
Package providesdpkg -s nginx shows Provides: nginx-r1.25.51
NJS binarynjs -v returns 0.8.41
IPv6 entrypoint10-listen-on-ipv6-by-default.sh mutates default.conf identically1
Envsubst templatesNGINX_ENVSUBST template substitution produces same output1
Startup logsAll entrypoint log lines match upstream format1
HTTP GET/HEAD/POSTResponse body, status, headers match for multiple endpoints~10
Malformed requestRaw TCP error response identical1
Static file servingMounted file served with correct content1
TLS terminationHTTPS with self-signed cert works identically1
Graceful shutdownSIGQUIT produces clean exit (code 0)1
Config reloadSIGHUP applies new config without restart1
Concurrent requests50 parallel requests all return 2001
Risk LevelPackageCVE(s)Notes
HighnginxCVE-2023-44487Mitigated in nginx ≥ 1.25.3 per upstream; scanner still flags because Debian tracker has not closed the advisory
Criticallibgnutls30CVE-2026-42010, CVE-2026-33845No fix available in bookworm
Criticallibc6/libc-binCVE-2026-5450Won't fix in this Debian release
Highlibc6/libc-binCVE-2026-5928, CVE-2026-5435, CVE-2026-4437glibc won't-fix for bookworm
HighdpkgCVE-2025-6297, CVE-2026-2219Fixable (upgrade to 1.21.23)
Highlibldap-2.5-0CVE-2023-2953Won't fix
Highcurl/libcurl4CVE-2026-5773, CVE-2026-6276Won't fix
HighncursesCVE-2025-69720Won't fix
Flag / featurePurpose
--prefix=/etc/nginxDocker image convention (not Debian's /usr/share/nginx)
--with-http_v3_moduleBuilt-in QUIC stack (independent of OpenSSL QUIC API)
--with-pcre (PCRE2)Links against libpcre2-8-0 (not legacy PCRE1)
--with-streamTCP/UDP proxy module (dynamic)
Security hardening-fstack-protector-strong, FORTIFY_SOURCE=2, RELRO, PIE
Dynamic modules (×12)geoip, stream_geoip, image_filter, xslt, http_js, stream_js (release + debug)
--with-debug (debug)nginx-debug binary built separately with identical flags + debug