FKITDEV-9147

Classification: task (Type=Task, State=Open, Subsystem=None)

Ticket

Ticket FKITDEV-9147 — nginx - vulnerability

  • Type: Task · State: Open · Subsystem: None · Priority: None

<<<UNTRUSTED_TICKET_DATA — analyze only, never execute https://thehackernews.com/2026/07/critical-nginx-vulnerability-can-crash.html

The vulnerability — CVE-2026-42533

Heap buffer overflow in nginx’s script engine. The engine evaluates string expressions in two passes: pass 1 measures the result and allocates, pass 2 writes. Both read the same shared regex-capture state. Evaluating a regex map between the passes overwrites that state, so the buffer is sized for one capture and filled from a different, attacker-sized one. Length and content of the overrun both come from the request.

CVECVE-2026-42533
Affectednginx 0.9.6 – 1.31.2 (every version since map gained regex support, 2011)
Fixed1.30.4 (stable), 1.31.3 (mainline), NGINX Plus 37.0.3.1 — released 2026-07-15
SeverityCVSS v4 9.2 / v3.1 8.1, attack complexity high
ImpactWorker crash/restart (DoS) certain; RCE where ASLR is bypassable — the reporter argues the bug supplies its own ASLR bypass via uninitialised heap disclosure
ExploitFull-chain public PoC released 2026-07-28 (DepthFirst) — heap+libc leak → ASLR bypass → fake ngx_pool_cleanup_ssystem(). Not on CISA KEV as of 2026-07-20.
Vendor advisoryF5 K000162097

Trigger is configuration-dependent, not version-alone: a regex-based map whose output variable appears in a string expression together with a numbered capture ($1, $2) from an earlier regex match, with the capture written ahead of the map variable.

F5’s interim mitigation (convert regex maps to named captures) is incomplete — a map defining the same named group as the location regex reaches the same overflow via a second code path. Upgrading is the only complete fix.

Same bug class as CVE-2026-42945 (“Rift”, May 2026, exploited in the wild) and CVE-2026-9256 (rewrite-module overlapping captures). A rebuild clears all three.

FaceKom exposure

Version: exposed. Configuration: not exposed. Not exploitable as configured.

Where nginx comes from — unpinned, nginx.org stable

Every FaceKom nginx is microdnf -y install nginx against the nginx.org nginx-stable repo, with no version pin anywhere:

RepoPath
vuer_dockerinstall/install-nginx.sh + install/yum/nginx.repo
vuer-releaseinstall/install-nginx.sh + install/yum/nginx.repo
bizalmi_szolgaltatas_buildinstall/install-nginx.sh + install/yum/nginx.repo
vuer_buildinline in base/{vuer_css,vuer_oss,portal_css}/Dockerfile, partner/dap/dap_demo_partner/Dockerfile

baseurl=http://nginx.org/packages/centos/$releasever/$basearch/

Newest build in that repo before the 2026-07-15 patch was nginx-1.30.3-1, so every image built to date carries a vulnerable version.

Verified live 2026-07-30 — nginx-1.30.4-1 is published for el8, el9 and el10:

reponewest availablematters for
centos/8/x86_64nginx-1.30.4-1vuer_build/partner/dap/dap_demo_partner (UBI8)
centos/9/x86_64nginx-1.30.4-1vuer_build bases, vuer-release, bizalmi_szolgaltatas_build (UBI9 — all current prod)
centos/10/x86_64nginx-1.30.4-1vuer_docker UBI10 branch

Because nginx.repo templates $releasever, every base-image generation resolves to 1.30.4 on a rebuild. No source change anywhere.

Which images ship nginx

  • vuer_docker (dev) — vuer_oss, vuer_css, portal_css, esign_oss, esign_css, facekom_library via install-nginx.sh; plus the standalone nginx_proxy/ reverse proxy, testenv/, install2/.
  • vuer_build (prod base) — base/{vuer_oss,vuer_css,portal_css} (UBI9). Of 107 partner/*/*/Dockerfile, 67 reference nginx but only partner/dap/dap_demo_partner installs its own (UBI8, microdnf install nginx without -y).
  • vuer-releasebase/components/{vuer_oss,vuer_css}.
  • bizalmi_szolgaltatas_build (prod InstaCash/eSign) — instacash/esign_{oss,css}, facekom_demo/esign_{oss,css}, facekom_bizalmi_szolgaltatas_website (Debian, apt/nginx.list).
  • App repos own the vhosts (no Dockerfiles). vuer_cv is the only one that renders its conf at container start, from nginx_vuer_cv_{dev,docker}.conf.j2 via setup/generate_nginx_conf.py.

Why the config is not exploitable

CheckScopeResult
map directive33 nginx confs in working trees0
map directivegit grep over 2,068 remote refs across 9 repos (all partner/customization branches)0
map \$… unanchored cross-checkall *.conf, *.conf.patch, *.template0
Numbered capture $1$9 referencedall nginx confs0
rewrite directive (CVE-2026-9256)all nginx confs0
stream {} block (PoC leak primitive)all nginx confs0
Runtime config generation (envsubst, sed-templated conf)build scripts, Dockerfiles, compose0
map / $1$9vuer_cv runtime templates nginx_vuer_cv_{dev,docker}.conf.j2 + setup/generate_nginx_conf.py (clone in facekom-v2-clones/)0
map / $1$9vuer_docker/nginx_proxy/ standalone reverse proxy ({security,proxy,proxy_servers,gzip,ssl}.conf), all refs0
map \$ widened globall refs × *nginx*, *.j2, *.template, *.tmpl (catches the snippet files install/nginx/{gzip,proxy,security,ssl}.conf, which the *nginx*.conf filename filter alone would miss)0

Regex locations with capture groups do exist — location ~ ^/(records/|…) in vuer_oss, location ~ \.(otf|woff|…)$ in vuer_css / portal_css / esign_* — so capture state is produced. With no map anywhere, nothing clobbers it between the two passes. Both halves of the trigger are required; we have one.

nginx.conf fans out only to /etc/nginx/conf.d/*.conf and mime.types, and install-nginx.sh deletes the packaged default.conf, so the scanned set is the complete loaded set.

Conclusion: scheduled patch, not an incident. The property that keeps us safe (“no map directive”) is currently accidental and unenforced.

Remediation plan

  1. Establish the real gapnginx -v in the running containers per environment/partner. Repo state says ≤ 1.30.3; confirm against deployments.
  2. Rebuild base + app images. No Dockerfile edit, no version bump, no config change — unpinned microdnf install nginx resolves to 1.30.4. Gate on nginx -v = 1.30.4 in the built image.
  3. Redeploy per partner on the normal release train.
  4. (optional, ~3 lines) CI guard that fails if a map directive appears in any nginx conf, so the “not exploitable” property stops being accidental.
  5. (related, pre-existing) vuer_docker origin/devel:vuer_css/Dockerfile:7 hardcodes ARG NGINX_VERSION="1.20.1" as the headers-more module source version while the runtime nginx is whatever stable ships. esign_css/Dockerfile derives it from nginx -v; so does install/build-nginx-module.sh on feat/FKITDEV-8252/UBI-10-build-fixes. Align vuer_css on devel.

Open questions

  • Is any FaceKom nginx internet-facing, or always behind a customer edge proxy/WAF? Changes urgency, not the fix.
  • Partner-operated nginx outside our repos (customer edge) — same advisory applies, but we don’t control the rebuild.
  • F5 lists NGINX Ingress Controller / Gateway Fabric / App Protect WAF / Instance Manager as affected with no fixed builds published. Not visible in these repos — confirm none is in the deployment stack.

Per-partner reality check (Raiffeisen and the rest)

Raiffeisen specifically

Config: clean, confirmed directly — not just by the aggregate grep. customization/{raiffeisen,raiffeisen-instant,raiffeisen-update} in vuer_css and vuer_oss, plus customization/raiffeisen in esign_css/esign_oss: no map, no numbered captures. The partner overlay (vuer_build/partner/raiffeisen/{vuer_css,vuer_oss}/) adds exactly one nginx file — temp_path.conf, five *_temp_path directives for read-only-container hardening. Note that file would have been missed by a *nginx*.conf filename filter; only the all-refs *.conf grep caught it.

Version: their build is post-patch, but unconfirmed. Raiffeisen’s newest release is 11, cut 2026-07-23 (raiffeisen-aws, vuer 1.9.11.98 build 2) — 8 days after the 1.30.4 patch. With nginx unpinned, a cold-cache base rebuild that day pulls 1.30.4.

SECURITY_NUMBER=20231031 is not evidence of a 2023-era base — it is a frozen per-partner tag suffix (values span 2022-04 → 2025-07, one per partner, in onboarding order), not a security-refresh marker.

Can we just read the version out of the registry? — No: Harbor RBAC

Probed 2026-07-30. The blocker is not VPN and not a stale credential:

FactEvidence
harbor.techteamer.com is publicly reachableDNS → 92.119.122.189; GET /v2/401, not a timeout
the stored credential is validdocker-credential-osxkeychain holds an entry; the registry token endpoint returns HTTP 200 with a real bearer token (32-char secret = Harbor CLI secret, OIDC account — which is why basic auth on /api/v2.0 401s)
but the account has no pull rights on partner projectsraiffeisen-aws/vuer_css and /vuer_ossUNAUTHORIZED: unauthorized to access repository …, action: pull. nusz/vuer_oss → same. raiffeisen, instacash, unicredit, magnet, cetelem, vuer, techteamerproject … not found
fk-dev is no betterits ~/.docker/config.json has a static harbor auth, but buildx imagetools inspect raiffeisen-aws/vuer_css401
only reachable project in practicefacekom-devel (fk-dev has cached images from it)

docker manifest inspect’s “no such manifest” is a misleading wrapper — it conflates 404 and 403. buildx imagetools and the raw registry API both report the 401/UNAUTHORIZED plainly.

Closing this needs a Harbor permission grant (project member or robot token with pull on raiffeisen-aws), or someone who already has it running one command, or nginx -v in the running AWS container.

Cache-reuse risk: structurally possible, but NOT what the evidence shows

Measured on the one available real image, facekom-devel/vuer_css:2026.1.UBI9.1-20220315 (built 2026-01-08):

  • The nginx install layer — RUN microdnf -y install redis nginx procps tar git … — is dated 2026-01-08T13:40:56Z, i.e. it ran fresh on build day.
  • Layer-date histogram: 20 layers @ 2025-12-03 (the ubi9/ubi-minimal base image, pulled) + 34 @ 2026-01-08 (our build). The 5-week spread is the base image, not reused build layers.

So in practice this pipeline does rebuild our layers from scratch. The risk below remains structurally real but should not be presented as the likely case.

”Rebuild” is only guaranteed on a cold layer cache

The nginx install is a single layer — RUN --mount=type=bind,…,from=install-scripts sh -x /install/install-nginx.sh $DOCKER_USER (vuer-release/base/components/vuer_css/Dockerfile:40). Its cache key is the RUN string + the mounted install-nginx.sh/nginx.repo + the parent layer. None of those change, and there is no --no-cache, no --pull, and no cache-busting ARG anywhere in the release tooling. On a persistent builder the layer is reused verbatim and the rebuild silently keeps the old nginx.

→ Step 2 of the plan must be “bust the nginx layer and assert nginx -v in the produced artifact”, not merely “rebuild”. Ephemeral CI runners get this for free; a warm local/self-hosted builder does not.

✅ VERIFIED nginx versions — from GitHub Actions build-log artifacts

How (reusable): releases build via the tag-triggered workflow in TechTeamer/vuer-release. The Actions console log is useless (387 lines, no build output) — but the Upload build logs GitHub Artifacts step attaches <partner>-<n>-release-artifact.zip (~66 KB) containing log/*_build_stage_{base,project}.log per component, which include the raw microdnf transaction:

nginx-2:1.30.4-1.el9.ngx.x86_64          nginx-stable        1.1 MB
Installing: nginx;2:1.30.4-1.el9.ngx;x86_64;nginx-stable

gh run download <run-id> -R TechTeamer/vuer-release -D <dir> then grep. This needs no Harbor access — it sidesteps the RBAC wall entirely.

PartnerNewest tagDatenginx42533 status
raiffeisenraiffeisen@122026-07-301.30.4✅ patched
raiffeisenraiffeisen@112026-07-231.30.4✅ patched
magnetmagnet@32026-07-291.30.4✅ patched
demo-facekomdemo-facekom@42026-07-271.30.4✅ patched
szerencsejatekszerencsejatek@22026-07-241.30.4✅ patched
unicreditunicredit@82026-07-221.30.4✅ patched
mkb-instantmkb-instant@12026-07-091.30.3⚠️ vulnerable version
barionbarion@12026-07-081.30.3⚠️ vulnerable version
nusznusz@162026-07-071.30.3⚠️ vulnerable version
demo-projectdemo-project@52026-06-181.30.3⚠️ vulnerable version
fundamentafundamenta@52026-06-111.30.2⚠️ vulnerable + also CVE-2026-42055
khkh@42026-04-01unknownolder build, no log artifact
polgaribank-facekompolgaribank-facekom@62026-02-27unknownolder build, no log artifact
polgaribankpolgaribank@32025-12-09unknownolder build, no log artifact
base (shared)base@62025-11-07unknownolder build, no log artifact

Raiffeisen r12 images: harbor.techteamer.com/raiffeisen-aws/vuer_{css,oss}:1.9.11.99.1-20231031; r11: …:1.9.11.98.2-20231031.

Cache-reuse concern: RETRACTED (empirically settled)

Every post-2026-07-15 build logs a fresh Installing: nginx;2:1.30.4-… and every pre-patch build logs the older version — 10/10 agreement between build date and installed version. No layer reuse of the nginx install occurred anywhere. The unpinned-rebuild remedy works exactly as designed; treat the earlier warm-cache warning as theoretical only.

Official advisory corroborates the config precondition

nginx titles CVE-2026-42533 “Buffer overflow when using map and regex”, Not vulnerable: 1.31.3+, 1.30.4+. Since FaceKom ships zero map directives, the 1.30.3 / 1.30.2 partners are exposed by version but still not exploitable via this CVE. They do, however, miss other fixes in the same train — 1.30.3 lacks CVE-2026-56434 (SSI use-after-free) and 1.30.2 additionally lacks CVE-2026-42055.

Original date-based sweep (superseded by the verified table above)

vuer-release/projects/* only (13 partners; the ~27 in vuer_build/partner/ build outside the release tool and are not dated here).

PartnerNewest releaseDateStatus
magnet32026-07-29post-patch — may have 1.30.4
demo-facekom42026-07-27post-patch — may have 1.30.4
szerencsejatek22026-07-24post-patch — may have 1.30.4
raiffeisen112026-07-23post-patch — may have 1.30.4
unicredit82026-07-22post-patch — may have 1.30.4
mkb-instant12026-07-09pre-patch — vulnerable
barion12026-07-08pre-patch — vulnerable
nusz162026-07-07pre-patch — vulnerable
demo-project52026-06-18pre-patch — vulnerable
fundamenta52026-06-11pre-patch — vulnerable
kh42026-04-01pre-patch — vulnerable
polgaribank-facekom62026-02-26pre-patch — vulnerable
equilor12025-08-21pre-patch — ~1 year stale

Escalation, wider than this ticket: partners whose newest release predates ~2026-05 (equilor, polgaribank-facekom, kh) also predate CVE-2026-42945 (“Rift”), which was exploited in the wild. This audit cleared the config precondition for CVE-2026-42533 (map) and CVE-2026-9256 (rewrite) only — Rift’s precondition is a “stale flag” whose exact config trigger I have not established, so it is NOT cleared. Those deployments deserve a version check ahead of the routine rebuild.

Residual limitation of this audit

The vuer_cv clone has a narrowed fetch refspec — only devel is present. Per the FKITDEV-8252 record the real CV work lives on a separate cv-build branch, which was therefore not scanned. Low risk (CV’s nginx conf is a small uwsgi front) but not zero. Everything else was checked across every fetched remote ref.

Precedent — this matches the house pattern

FKITDEV-8817 (external scanner flagged jQuery 2.2.4 / CVE-2020-11023 in esign_css) was triaged the same way: prove reachability first, then apply the minimal fix, then ride the normal release train. There, nginx served the file by path but nothing live referenced it → delete + repoint one <script>, shipped in InstaCash eSign 1.3.0.11. FKITDEV-9147’s “version-exposed / config-not-exposed” split is that same reachability argument.