GitHub Security Advisory: GHSA-mxqh-q9h6-v8pq
Package: github.com/0xJacky/nginx-ui (GO)
Severity: HIGH (CVSS 8.1)
CWE: CWE-284: Improper Access Control, CWE-306: Missing Authentication for Critical Function
Vulnerable versions: = 2.3.5
Patched in: unpatched

Summary: Nginx-UI: Unauthenticated first-boot instance claim via POST /api/install allows remote bootstrap takeover

Details:
## Summary

An unauthenticated bootstrap takeover exists in `nginx-ui` during the initial installation window exposed by `POST /api/install`.

When the instance is still uninitialized, `POST /api/install` is reachable without authentication and accepts attacker-controlled bootstrap data. The handler sets the application's JWT secret, the node secret, the certificate email, and the initial administrator username and password. This allows an attacker who can reach a fresh instance during the initial 10-minute setup window to claim the installation before the legitimate operator.

This is not a general post-install takeover. The exposure condition is narrower: the target must still be in its first-run state and still be within the initial setup window. In practice, this makes the issue most relevant during initial deployment, rebuilds, ephemeral test environments, LAN-accessible fresh installs, or temporarily exposed setup workflows.

The primary attack path is direct network access to a reachable fresh instance.[^cors]

This was reproduced over HTTP against live local instances started from `nginx-ui` `v2.3.5` using Docker image `uozi/nginx-ui@sha256:d73343e3009c9b558129a2be0cacd6c2c57ed8006a5871873b874b812e612e5a` (`org.opencontainers.image.version=2.3.5`, revision `1a9cd29a308278173aa0f16234cb78061dd2bd42`).

## Impact

This issue allows full unauthenticated takeover of a fresh `nginx-ui` instance during the initial installation window.

The practical exposure window is limited, but the impact inside that window is complete administrative takeover. An attacker does not need to guess defaults or exploit an authenticated feature; they become the first administrator and define the instance trust material themselves.

In live testing, the attacker was able to:

- confirm that the target was still uninitialized
- submit attacker-chosen bootstrap credentials
- lock the installation under attacker control
- immediately authenticate as the newly set administrator

Observed values during live reproduction included:

```text
INSTALL_BEFORE={"lock":false,"timeout":false}
INSTALL_POST={"message":"ok"}
INSTALL_AFTER={"lock":true,"timeout":false}
LOGIN_RESPONSE={"message":"ok","code":200,...,"short_token":"qIJAE3dQMm3afhaV"}
```

Because the bootstrap request also initializes the application's trust material, this is more severe than a simple default-admin issue. An attacker does not merely guess credentials; they define the initial administrator account and application secrets themselves.

## PoC

The following standalone PoC is sufficient to reproduce the issue without relying on any repository-local helper script. It requires only `bash`, `curl`, and `openssl`.

Standalone PoC:

```bash
#!/usr/bin/env bash
set -euo pipefail

base_url="http://127.0.0.1:9000"
email="poc2@nginxui.test"
username="pocverify2"
[CREDENTIAL_REDACTED]"

tmpdir="$(mktemp -d)"
trap 'rm -rf "$tmpdir"' EXIT

install_before="$(curl -fsS "${base_url}/api/install")"
printf 'INSTALL_BEFORE=