Sep 21, 2026·6 min read·66 visits
Unauthenticated remote attackers can create unauthorized administrative accounts on fresh Nginx Ignition installations by exploiting a race condition in the initial setup API.
Nginx Ignition prior to version 2.41.1 contains a Time-of-Check to Time-of-Use (TOCTOU) race condition in its unauthenticated onboarding API endpoint. This flaw allows remote, unauthenticated attackers to register an administrative account by sending concurrent HTTP requests during the initial system configuration phase, bypassing the check meant to restrict onboarding to a single initial administrator.
CVE-2026-61628 is a critical security flaw identified in Nginx Ignition, an open-source administration panel and user interface developed by Lucas Dillmann for managing the NGINX web server. The flaw is located in the application's initial setup API endpoint /api/users/onboarding/finish, which is designed to configure the initial administrator account on clean installations.
This endpoint is unauthenticated by design to allow the initial deployment configuration. However, the API handler fails to perform atomic checks when evaluating if the system has already been configured. The underlying weakness is classified as a Time-of-Check to Time-of-Use (TOCTOU) race condition, mapped to CWE-362.
If the application is deployed in a multi-threaded or concurrent processing environment, the vulnerability exposes a severe initial access vector. An attacker can exploit this condition to bypass setup barriers and register their own administrative accounts alongside the legitimate administrator.
The root cause of CVE-2026-61628 lies in the separation of the validation check and the insertion operations in the onboarding handler logic. In affected versions prior to 2.41.1, the handler inside api/user/onboarding_finish_handler.go uses a non-atomic two-phase execution flow.
During the check phase, the handler queries the database using OnboardingCompleted(ctx) to determine if any accounts are already present. If the database returns zero users, the application assumes setup is incomplete. In the subsequent write phase, the handler hashes the password, constructs the administrative domain object, and calls the repository's Save() function to write the new user record.
Because Nginx Ignition's Go backend processes concurrent HTTP requests inside separate goroutines, multiple requests can execute the check phase simultaneously. If multiple requests reach the check phase before any single write is committed, they all read a count of zero users. As a result, all concurrent threads proceed to the write phase and successfully write their database records without generating a unique constraint conflict or transactional rollback.
The original handler performed the check and database insert sequentially without wrapping the operations in an exclusive database lock or unified transaction. The security patch submitted in Pull Request #131 addresses this by deprecating the two-step execution and delegating validation to FinishOnboarding.
// api/user/onboarding_finish_handler.go (PATCHED)
if err = h.commands.FinishOnboarding(ctx.Request.Context(), domainModel); err != nil {
if errors.Is(err, user.ErrOnboardingAlreadyCompleted) {
ctx.Status(http.StatusForbidden)
return
}
panic(err)
}The FinishOnboarding command calls the repository method TryCreateInitialUser, which begins a transaction and implements explicit, dialect-specific table locks. This architecture blocks concurrent check attempts.
// database/user/repository.go (PATCHED)
func (r *repository) TryCreateInitialUser(ctx context.Context, u *user.User) (bool, error) {
transaction, err := r.database.Begin()
if err != nil {
return false, err
}
defer transaction.Rollback()
if err = lockUserTable(ctx, transaction); err != nil {
return false, err
}
exists, err := transaction.NewSelect().Model((*userModel)(nil)).Exists(ctx)
if err != nil {
return false, err
}
if exists {
return false, nil
}
model := toModel(u)
_, err = transaction.NewInsert().Model(&model).Exec(ctx)
if err != nil {
return false, err
}
return true, transaction.Commit()
}The locking function lockUserTable dynamically maps locks to the target database engine. For PostgreSQL, it executes LOCK TABLE "user" IN EXCLUSIVE MODE, forcing consecutive transactions to block and queue. For SQLite, it triggers ROLLBACK; BEGIN IMMEDIATE; to enforce exclusive read-write locks at the database connection layer. This resolves the TOCTOU gap comprehensively across both supported databases.
Exploitation of CVE-2026-61628 depends on temporal precision and system state. The target must be a fresh installation that has not yet completed its onboarding process, or an instance where the user database has been purged. Once onboarding is complete, the API path is blocked and the race window is permanently closed.
To exploit the flaw, the attacker generates multiple parallel connection threads and targets the /api/users/onboarding/finish endpoint with HTTP POST requests. These requests contain JSON payloads containing the desired attacker-controlled administrator credentials and authorization parameters.
If the threads execute concurrently within the processing window, both requests execute successfully. When the database transaction commits, two distinct users are registered with administrative privileges. The attacker can then navigate to the standard web administration interface and authenticate as a administrator.
A successful attack results in full administrative control over the Nginx Ignition console and the managed NGINX environment. Attackers obtain administrative permissions (ReadWrite), which authorize full reading and writing capabilities across all server settings.
With this access level, attackers can alter proxy hosts, modify routing files, and access downstream network systems. The configuration console also manages sensitive data, such as private SSL/TLS certificates and system logs. Attackers can export active cryptographic keys or configure malicious proxy rules to capture passing client credentials.
This vulnerability has been assigned a CVSS v3.1 base score of 8.1. The attack requires no prior authentication and demands no victim interaction. Although the complexity is high due to the strict timing window, the impact on confidentiality, integrity, and availability is critical.
To address CVE-2026-61628, administrators must update Nginx Ignition to version 2.41.1 or higher. This update introduces the necessary table locking and immediate transaction controls to prevent parallel setup routines.
If an upgrade cannot be applied immediately, administrators should implement network-level access controls to limit access to the onboarding endpoint. Restricting communication to the setup handler to trusted IPs prevents external access during configuration.
# Example NGINX configuration to restrict onboarding access
location /api/users/onboarding/finish {
allow 192.168.1.50; # Administrator Workstation
deny all;
proxy_pass http://localhost:8080;
}Security teams should also audit active database tables to identify potential indicator files. Running a query against the user table to check for multiple accounts with identical or near-identical creation timestamps is a reliable method to identify exploitation attempts.
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H| Product | Affected Versions | Fixed Version |
|---|---|---|
nginx-ignition lucasdillmann | < 2.41.1 | 2.41.1 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-362 |
| Attack Vector | Network |
| CVSS v3.1 | 8.1 |
| Exploit Status | poc |
| KEV Status | Not Listed |
| Impact | Administrative Access |
The software performs multiple concurrent operations on a shared resource, but does not properly synchronize these operations, creating a race condition.
CVE-2026-12411 is a broken access control vulnerability in the DevLXD interface of Canonical LXD versions 6.6 through 6.8. The flaw resides in the devLXDInstancePatchHandler component, which fails to verify storage volume ownership when an instance attaches a new disk device via the /dev/lxd guest socket. When the security.devlxd.management.volumes configuration option is enabled, an untrusted guest or DevLXD identity can issue a crafted HTTP PATCH request referencing another tenant's custom storage volume. The LXD host daemon subsequently mounts the target volume into the requesting guest, permitting unauthorized cross-tenant read and write operations.
CVE-2026-105769 (GHSA-5q7h-w9jf-cx97, GO-2026-6225) is an origin validation error and credential exfiltration vulnerability affecting Kaniko prior to version 1.25.20. The flaw stems from an unanchored regular expression in the integrated Azure Container Registry (ACR) credential helper (github.com/chrismellard/docker-credential-acr-env). When Kaniko processes a Dockerfile containing an image reference hosted on a lookalike domain containing an ACR suffix as a substring (e.g., x.azurecr.io.attacker.com), the credential helper acquires a Microsoft Entra ID access token for Azure Resource Manager and transmits it via HTTP POST to the attacker-controlled host.
CVE-2026-62300 is an uncontrolled resource consumption vulnerability (CWE-400) affecting the daemon mode of filecoin-pin in versions up to and including 1.1.0. The daemon implements the IPFS Pinning Service API to store content on Filecoin's Proof of Data Possession (PDP) service. Due to the absence of rate limits, concurrency caps, execution timeouts, and Directed Acyclic Graph (DAG) traversal limits, an authenticated user—or an unauthenticated user when authentication is disabled—can exhaust system resources via crafted POST /pins requests.
CVE-2026-61536 is a high-severity Remote Code Execution (RCE) vulnerability in the masci/banks Python library prior to version 2.4.3. The flaw exists within the CompletionExtension component, which parses JSON-serialized Tool definitions directly from rendered Jinja template bodies inside {% completion %} blocks. When handling tool calls returned by an LLM, the library dynamically resolves the target callable using importlib.import_module() and getattr() based on an unvalidated import_path string. An attacker who can supply or modify prompt templates can inject a malicious Tool JSON object pointing to arbitrary Python functions (such as os.system), bypassing the Jinja SandboxedEnvironment introduced in version 2.4.2 and achieving arbitrary code execution when the LLM invokes the tool.
Payload CMS contains a missing authorization vulnerability (CWE-862) in its client-side upload instructions endpoint and the `@payloadcms/storage-vercel-blob` storage adapter. Two distinct logic defects allow authenticated users lacking collection-level `create` or `update` permissions to generate signed upload tokens and upload arbitrary files directly to external cloud storage.
CVE-2026-55098 (GHSA-93cm-2v4m-c56c) is an authorization bypass and sensitive information disclosure vulnerability in Basekick-Labs Arc prior to version 26.06.2. The flaw stems from an incomplete remediation of CVE-2026-47735, which failed to restrict the full suite of DuckDB table-valued filesystem I/O functions and quoted-identifier invocations. Because Arc's query parser ignores function calls during table reference extraction, authenticated users with minimal or empty permissions can invoke functions like parquet_scan(), glob(), and read_blob() to read, enumerate, and extract telemetry data across all tenant databases residing within the shared local storage root.