
Proof-of-concept and disclosure pack for CVE-2026-61628, an unauthenticated TOCTOU privilege escalation in nginx-ignition 2.41.0 that allows admin account creation.
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · CVE-2026-61628
nginx-ignition 2.41.0 - lucasdillmann
I am @abraxas_null. Loopback lab. The client is CVE-2026-61628-Abraxas-Labs.py.
Onboarding is anonymous. First-boot POST /api/users/onboarding/finish is AllowAnonymous. Check-then-Save. Two requests that both see an empty table both become admins. A single 200 on a virgin box is unauthenticated admin. n200>=2 distinct usernames is the TOCTOU. Not WordPress. Patched in 2.41.1.
| CVE | CVE-2026-61628 · CVE.org |
| CWE | CWE-362 |
| CVSS | High: 8.1 CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H |
| Product | nginx-ignition |
| Affected | all versions through 2.41.0 (inclusive) |
| Patched | 2.41.1 and later |
| Auth | unauthenticated |
| License | GNU Affero GPL v3.0 |
| Lab | 127.0.0.1 only |
Hit a freshly started instance before anyone finishes the wizard, or race two finishes. You get a JWT with Users=READ_WRITE. That is instance takeover. After onboarding, every request 403. That is the product working.
NVD named the anonymous finish handler. I read AllowAnonymous, then the check-then-Save, then fired concurrent POSTs at a fresh compose stack.
GET /api/users/onboarding/status until finished=false. POST finish with a unique username. GET /api/users/current with the JWT. For the race, many concurrent finishes before anyone has committed a user.
Wrong turns: GET (route is POST JSON name / username / password); hitting a host that finished onboarding last week; one 200 and calling it a race (that is the unauthenticated-admin bug; n200>=2 is the TOCTOU); waiting for an HTML dashboard (the tell is small JSON with a token field).
Port 18090. dillmann/nginx-ignition:2.41.0 plus Postgres. Fresh volume. Do not click the wizard first.
Target only 127.0.0.1:18090 (or the loopback you bound).
cd lab
docker compose up --force-recreate
python3 ../CVE-2026-61628-Abraxas-Labs.py
Witness: Unauthenticated 200, JWT, users_perm=READ_WRITE on /api/users/current. Race: n200>=2 and more than one admin username.
Ways to lose without learning anything:
Update nginx-ignition to 2.41.1 or newer. Re-run CVE-2026-61628-Abraxas-Labs.py against the patched build: unauthenticated finish must not mint an admin JWT.
github.com/lucasdillmann/nginx-ignition/security/advisories/GHSA-pxcx-fv34-x9p5
github.com/lucasdillmann/nginx-ignition/commit/0586b4e55ab780676d3553a2592979dfa2fb0183
Abraxas Labs: abraxaslabs.tech · github.com/abraxas · @abraxas_null
GNU Affero GPL v3.0. See LICENSE.
The client talks to loopback. Using it against systems you do not own is not authorized by Abraxas Labs. No warranty.