CVE-2026-84313
## Summary Endpoints that bind a TOTP secret (`POST /api/otp_enroll`) or register a WebAuthn passkey (`POST /api/finish_passkey_register`) for the *current* user require only a valid JWT. There is no current-password re-prompt and the routes are explicitly registered **outside** the `RequireSecureSession()` group. With only a stolen JWT, an attacker can attach their own second factor to the victim's account, surviving any subsequent password rotation and locking the legitimate user out. ## Details `api/user/router.go:34-39` — note the routes registered *before* the secure-session group: ```go r.GET("/otp_secret", GenerateTOTP) r.POST("/otp_enroll", EnrollTOTP) // ← outside RequireSecureSession r.GET("/begin_passkey_register", BeginPasskeyRegistration) r.POST("/finish_passkey_register", FinishPasskeyRegistration) // ← outside RequireSecureSession o := r.Group("", middleware.RequireSecureSession()) { o.GET("/otp_reset", ResetOTP) // reset *is* protected — inconsistent ... } ``` `EnrollTOTP` (`api/user/otp.go:45-102`) only refuses if `cUser.EnabledOTP()` is already `true`; for any victim who has never enabled TOTP it accepts an attacker-supplied `Secret` and `Passcode` pair (the validator only checks that the passcode is a valid TOTP for the supplied secret — i.e., the attacker proves they know the secret they are submitting): ```go if cUser.EnabledOTP() { ... abort ... } var twoFA struct { Secret string `json:"secret" binding:"required"` Passcode string `json:"passcode" binding:"required"` } if !cosy.BindAndValid(c, &twoFA) { return } if ok := totp.Validate(twoFA.Passcode, twoFA.Secret); !ok { ... abort ... } ciphertext, _ := crypto.AesEncrypt([]byte(twoFA.Secret)) u.Where(u.ID.Eq(cUser.ID)).Update(u.OTPSecret, ciphertext) ``` `FinishPasskeyRegistration` (`api/user/passkey.go`) is structurally identical and additionally has *no* "already enrolled" guard — an attacker can register multiple passkeys to
Properties
- severity
- high
- summary
- Nginx UI: TOTP / passkey enrolment requires no re-authentication, enabling persistent account takeover
- cvss_score
- 8.8
- retrieved_at
- 2026-10-15T22:56:51+00:00
- ghsa_published
- 2026-10-15T20:11:32Z
- source_url
- https://github.com/advisories/GHSA-gfrc-g87h-7h5w
- ghsa_updated
- 2026-10-15T20:11:33Z
- ghsa_id
- GHSA-gfrc-g87h-7h5w
- last_source
- GitHub Advisory Database
- cve_id
- CVE-2026-84313
- cvss_vector
- CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H
- signal_observed_at
- 2026-10-15T22:56:51+00:00
- is_ghsa_only
- false
Related Entities (5)
VULNERABLE_TO (1)
AFFECTS (1)
HAS_WEAKNESS (2)
REPORTED_BY (1)
Explore deeper with Ninja Signal's threat intelligence graph