CVE-2026-61628
nginx ignition has Unauthenticated Admin Account Creation via Onboarding Race Condition
nginx ignition is a user interface for the nginx web server. Prior to version 2.41.1, POST /api/users/onboarding/finish is registered as anonymous (unauthenticated) and creates a user with full ReadWrite admin permissions. Because the handler uses a check-then-act (TOCTOU) pattern between the "onboarding already completed?" check and the user-creation write, with no atomic guard, a remote unauthenticated attacker who can reach an instance in its pre-onboarding state can create an administrator account for themselves — and concurrent requests can create multiple admin accounts in a single race. Version 2.41.1 patches the issue.
Attack profile
How easy it is to exploit
- Attack vector
- Network
- Complexity
- High
- Privileges needed
- None
- User interaction
- None
What an attacker can affect
- Confidentiality
- High
- Integrity
- High
- Availability
- High
Exploit likelihood
What each source reports
CVE List Score used
8.1
nginx ignition has Unauthenticated Admin Account Creation via Onboarding Race Condition
nginx ignition is a user interface for the nginx web server. Prior to version 2.41.1, POST /api/users/onboarding/finish is registered as anonymous (unauthenticated) and creates a user with full ReadWrite admin permissions. Because the handler uses a check-then-act (TOCTOU) pattern between the "onboarding already completed?" check and the user-creation write, with no atomic guard, a remote unauthenticated attacker who can reach an instance in its pre-onboarding state can create an administrator account for themselves — and concurrent requests can create multiple admin accounts in a single race. Version 2.41.1 patches the issue.
- Record
CVE-2026-61628- CVSS 3.1
- 8.1 High
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H - Weakness
- CWE-362
- Updated
- 2026-11-02
EUVDEUVD-2026-83947
8.1
nginx ignition is a user interface for the nginx web server. Prior to version 2.41.1, POST /api/users/onboarding/finish is registered as anonymous (unauthenticated) and creates a user with full ReadWrite admin permissions. Because the handler uses a check-then-act (TOCTOU) pattern between the "onboarding already completed?" check and the user-creation write, with no atomic guard, a remote unauthenticated attacker who can reach an instance in its pre-onboarding state can create an administrator account for themselves — and concurrent requests can create multiple admin accounts in a single race. Version 2.41.1 patches the issue.
- Record
EUVD-2026-83947- CVSS 3.1
- 8.1 High
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H - Updated
- 2026-11-02
GitHub AdvisoriesGHSA-pxcx-fv34-x9p5
8.1
nginx ignition has Unauthenticated Admin Account Creation via Onboarding Race Condition
Summary
POST /api/users/onboarding/finish is registered as anonymous (unauthenticated) and creates a user with full ReadWrite admin permissions. Because the handler uses a check-then-act (TOCTOU) pattern between the "onboarding already completed?" check and the user-creation write, with no atomic guard, a remote unauthenticated attacker who can reach an instance in its pre-onboarding state can create an administrator account for themselves — and concurrent requests can create multiple admin accounts in a single race.
Affected component
- Endpoint:
POST /api/users/onboarding/finish - Route registration:
api/user/routes.go:49→authorizer.AllowAnonymous(http.MethodPost, "/api/users/onboarding/finish") - Handler:
api/user/onboarding_finish_handler.go
Technical details
The route is explicitly allowed without authentication:
// api/user/routes.go:48-49
authorizer.AllowAnonymous(http.MethodGet, "/api/users/onboarding/status")
authorizer.AllowAnonymous(http.MethodPost, "/api/users/onboarding/finish")
The handler reads the onboarding state, returns 403 if already finished, and otherwise creates a user with every permission set to ReadWrite:
// api/user/onboarding_finish_handler.go
func (h onboardingFinishHandler) handle(ctx *gin.Context) {
alreadyFinished, err := h.commands.OnboardingCompleted(ctx.Request.Context()) // (1) CHECK
if err != nil { panic(err) }
if alreadyFinished {
ctx.Status(http.StatusForbidden)
return
}
requestPayload := &userRequestDTO{}
if err = ctx.BindJSON(requestPayload); err != nil { panic(err) }
domainModel := converter.Wrap(ctx.Request.Context(), toDomain, requestPayload)
domainModel.ID = uuid.New()
domainModel.Enabled = true
domainModel.Permissions = user.Permissions{ // full admin
Hosts: user.ReadWriteAccessLevel,
Streams: user.ReadWriteAccessLevel,
Certificates: user.ReadWriteAccessLevel,
Integrations: user.ReadWriteAccessLevel,
AccessLists: user.ReadWriteAccessLevel,
Settings: user.ReadWriteAccessLevel,
Users: user.ReadWriteAccessLevel,
NginxServer: user.ReadWriteAccessLevel,
Caches: user.ReadWriteAccessLevel,
// ...all remaining permissions ReadWrite/ReadOnly
}
if err = h.commands.Save(ctx.Request.Context(), domainModel, nil); err != nil { // (2) ACT
panic(err)
}
// ...authenticates and returns a JWT for the new admin
}
The gap between (1) OnboardingCompleted() and (2) Save() is not protected by a lock, transaction, or unique constraint. Two or more requests can each pass the alreadyFinished == false check before any of them commits, so every racing request proceeds to create an admin user and receive a valid admin JWT.
Preconditions (stated honestly)
This is exploitable when the instance is in a pre-onboarding state:
- Fresh deployment — the time window between the service coming online and the legitimate operator completing onboarding. During this window any unauthenticated party who can reach the instance can register the first/an additional admin. The race lets an attacker slip an admin account in alongside the operator's, so the operator's onboarding appears to succeed normally while the attacker silently holds admin.
- State reset — if onboarding state can return to "not completed" (e.g. all users removed), the endpoint reopens and becomes a repeatable unauthenticated admin-creation primitive.
The single-request path is a setup-window exposure; the race is what turns "first legitimate admin" into "attacker also gets admin," and what allows multiple admin accounts to be minted from one burst.
Proof of concept
Against an instance that has not yet completed onboarding:
# Fire concurrent onboarding-finish requests; multiple admin accounts are created,
# each returning a valid admin JWT,…
- Record
GHSA-pxcx-fv34-x9p5- CVSS 3.1
- 8.1 High
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H - Weakness
- CWE-362
- Updated
- 2026-11-02
NVD
8.1
nginx ignition is a user interface for the nginx web server. Prior to version 2.41.1, POST /api/users/onboarding/finish is registered as anonymous (unauthenticated) and creates a user with full ReadWrite admin permissions. Because the handler uses a check-then-act (TOCTOU) pattern between the "onboarding already completed?" check and the user-creation write, with no atomic guard, a remote unauthenticated attacker who can reach an instance in its pre-onboarding state can create an administrator account for themselves — and concurrent requests can create multiple admin accounts in a single race. Version 2.41.1 patches the issue.
- Record
CVE-2026-61628- CVSS 3.1
- 8.1 High
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H - Weakness
- CWE-362
- Updated
- 2026-11-02
OSV
8.1
nginx ignition has Unauthenticated Admin Account Creation via Onboarding Race Condition
nginx ignition is a user interface for the nginx web server. Prior to version 2.41.1, POST /api/users/onboarding/finish is registered as anonymous (unauthenticated) and creates a user with full ReadWrite admin permissions. Because the handler uses a check-then-act (TOCTOU) pattern between the "onboarding already completed?" check and the user-creation write, with no atomic guard, a remote unauthenticated attacker who can reach an instance in its pre-onboarding state can create an administrator account for themselves — and concurrent requests can create multiple admin accounts in a single race. Version 2.41.1 patches the issue.
- Record
CVE-2026-61628- CVSS 3.1
- 8.1 High
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H - Weakness
- CWE-362
- Updated
- 2026-11-02
OSVGHSA-pxcx-fv34-x9p5
8.1
nginx ignition has Unauthenticated Admin Account Creation via Onboarding Race Condition
Summary
POST /api/users/onboarding/finish is registered as anonymous (unauthenticated) and creates a user with full ReadWrite admin permissions. Because the handler uses a check-then-act (TOCTOU) pattern between the "onboarding already completed?" check and the user-creation write, with no atomic guard, a remote unauthenticated attacker who can reach an instance in its pre-onboarding state can create an administrator account for themselves — and concurrent requests can create multiple admin accounts in a single race.
Affected component
- Endpoint:
POST /api/users/onboarding/finish - Route registration:
api/user/routes.go:49→authorizer.AllowAnonymous(http.MethodPost, "/api/users/onboarding/finish") - Handler:
api/user/onboarding_finish_handler.go
Technical details
The route is explicitly allowed without authentication:
// api/user/routes.go:48-49
authorizer.AllowAnonymous(http.MethodGet, "/api/users/onboarding/status")
authorizer.AllowAnonymous(http.MethodPost, "/api/users/onboarding/finish")
The handler reads the onboarding state, returns 403 if already finished, and otherwise creates a user with every permission set to ReadWrite:
// api/user/onboarding_finish_handler.go
func (h onboardingFinishHandler) handle(ctx *gin.Context) {
alreadyFinished, err := h.commands.OnboardingCompleted(ctx.Request.Context()) // (1) CHECK
if err != nil { panic(err) }
if alreadyFinished {
ctx.Status(http.StatusForbidden)
return
}
requestPayload := &userRequestDTO{}
if err = ctx.BindJSON(requestPayload); err != nil { panic(err) }
domainModel := converter.Wrap(ctx.Request.Context(), toDomain, requestPayload)
domainModel.ID = uuid.New()
domainModel.Enabled = true
domainModel.Permissions = user.Permissions{ // full admin
Hosts: user.ReadWriteAccessLevel,
Streams: user.ReadWriteAccessLevel,
Certificates: user.ReadWriteAccessLevel,
Integrations: user.ReadWriteAccessLevel,
AccessLists: user.ReadWriteAccessLevel,
Settings: user.ReadWriteAccessLevel,
Users: user.ReadWriteAccessLevel,
NginxServer: user.ReadWriteAccessLevel,
Caches: user.ReadWriteAccessLevel,
// ...all remaining permissions ReadWrite/ReadOnly
}
if err = h.commands.Save(ctx.Request.Context(), domainModel, nil); err != nil { // (2) ACT
panic(err)
}
// ...authenticates and returns a JWT for the new admin
}
The gap between (1) OnboardingCompleted() and (2) Save() is not protected by a lock, transaction, or unique constraint. Two or more requests can each pass the alreadyFinished == false check before any of them commits, so every racing request proceeds to create an admin user and receive a valid admin JWT.
Preconditions (stated honestly)
This is exploitable when the instance is in a pre-onboarding state:
- Fresh deployment — the time window between the service coming online and the legitimate operator completing onboarding. During this window any unauthenticated party who can reach the instance can register the first/an additional admin. The race lets an attacker slip an admin account in alongside the operator's, so the operator's onboarding appears to succeed normally while the attacker silently holds admin.
- State reset — if onboarding state can return to "not completed" (e.g. all users removed), the endpoint reopens and becomes a repeatable unauthenticated admin-creation primitive.
The single-request path is a setup-window exposure; the race is what turns "first legitimate admin" into "attacker also gets admin," and what allows multiple admin accounts to be minted from one burst.
Proof of concept
Against an instance that has not yet completed onboarding:
# Fire concurrent onboarding-finish requests; multiple admin accounts are created,
# each returning a valid admin JWT,…
- Record
GHSA-pxcx-fv34-x9p5- CVSS 3.1
- 8.1 High
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H - Weakness
- CWE-362
- Updated
- 2026-11-02
OSVUBUNTU-CVE-2026-61628
8.1
nginx ignition is a user interface for the nginx web server. Prior to version 2.41.1, POST /api/users/onboarding/finish is registered as anonymous (unauthenticated) and creates a user with full ReadWrite admin permissions. Because the handler uses a check-then-act (TOCTOU) pattern between the "onboarding already completed?" check and the user-creation write, with no atomic guard, a remote unauthenticated attacker who can reach an instance in its pre-onboarding state can create an administrator account for themselves — and concurrent requests can create multiple admin accounts in a single race. Version 2.41.1 patches the issue.
- Record
UBUNTU-CVE-2026-61628- CVSS 3.1
- 8.1 High
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H - Updated
- 2026-11-02
OSVGO-2026-6540 No score
nginx ignition has Unauthenticated Admin Account Creation via Onboarding Race Condition in github.com/lucasdillmann/nginx-ignition
nginx ignition has Unauthenticated Admin Account Creation via Onboarding Race Condition in github.com/lucasdillmann/nginx-ignition.
NOTE: The source advisory for this report contains additional versions that could not be automatically mapped to standard Go module versions.
(If this is causing false-positive reports from vulnerability scanners, please suggest an edit to the report.)
The additional affected modules and versions are: github.com/lucasdillmann/nginx-ignition before v0.0.0-20260621194639-0586b4e55ab.
- Record
GO-2026-6540- Updated
- 2026-11-02
Affected products
Affected packages
| Package | Affected | Fixed |
|---|---|---|
github.com/lucasdillmann/nginx-ignitionGo |
before 0.0.0-20260621194639-0586b4e55ab | 0.0.0-20260621194639-0586b4e55ab |
github.com/lucasdillmann/nginx-ignitionGo |
All versions | None known |
Public exploits
Links only. Every CVE stores no exploit code.
| Source | Link | Date |
|---|---|---|
| PoC in GitHub | abraxas/CVE-2026-61628 | 2026-09-22 |
History
| Recorded | Changed | Sources |
|---|---|---|
| affected | ||
| first indexed | CVE List, EUVD, GitHub Advisories, NVD, OSV, PoC in GitHub |
Dates are when Every CVE recorded each change. Upstream dates may differ.
In short
CVE-2026-61628 is a high vulnerability (CVSS 8.1) in Lucasdillmann Nginx-ignition, published September 21, 2026. Public exploit code exists. EPSS puts the chance of exploitation in the next 30 days at 0.43%, the 37th percentile. Fixed in github.com/lucasdillmann/nginx-ignition 0.0.0-20260621194639-0586b4e55ab.
References
github.com/lucasdillmann/nginx-ignition/security/advisories/GHSA-pxcx-fv34-x9p5
github.com/lucasdillmann/nginx-ignition/commit/0586b4e55ab780676d3553a2592979dfa2fb0183
nvd.nist.gov/vuln/detail/CVE-2026-61628
github.com/lucasdillmann/nginx-ignition/pull/131
github.com/lucasdillmann/nginx-ignition/releases/tag/2.41.1
github.com/advisories/GHSA-pxcx-fv34-x9p5
Left out here: the rest of 2 source descriptions. The JSON record has them.