3x-ui/internal/web/controller
Sanaei c8a3a2d723
fix(security): require a 2FA code to replace the stored TOTP secret
The confirmation gate in updateSetting only covered the true -> false
transition, so a settings save that kept twoFactorEnable=true while
carrying a non-blank twoFactorToken silently rebound the authenticator.
preserveRedactedSecrets restores the stored secret only when the
submitted one is blank, so a non-blank value went straight through
without any branch asking for a code.

Not reachable pre-auth or cross-site (CSRFMiddleware rejects unsafe
methods without the session token), but it matters after a session
hijack or with an admin API token, which sets api_authed and
short-circuits the CSRF check: the attacker gains persistence and locks
the legitimate operator out of their own authenticator.

Now a code is required whenever 2FA is currently on and the submitted
secret differs from the stored one. Enabling from off is untouched, as
no code exists yet to verify, and a blank secret still means
"unchanged", so the panel's normal save path is unaffected.

Reported by @n0ctal (GHSA-xqqw-jqqv-99h6).
2026-08-19 19:54:15 +02:00
..
api.go feat(api): scoped, optionally expiring API tokens (#6201) 2026-08-15 15:31:49 +02:00
api_auth_test.go feat(api): scoped, optionally expiring API tokens (#6201) 2026-08-15 15:31:49 +02:00
base.go
client.go feat(sub): add per-client subscription HWID limits (#5802) 2026-08-15 16:50:20 +02:00
dist.go feat(web): add network-only PWA installability (#6190) 2026-08-18 15:33:20 +02:00
dist_test.go feat(web): add network-only PWA installability (#6190) 2026-08-18 15:33:20 +02:00
geodata_test.go feat(xray): browse geosite/geoip categories from routing rules (#6165) 2026-08-15 17:12:59 +02:00
group.go fix(groups): report changed bulk moves without restarting xray (#6199) 2026-08-14 19:50:06 +02:00
host.go feat(hosts): bulk-add multiple hosts to multiple inbounds (#5677) 2026-07-08 23:35:20 +02:00
host_test.go feat(hosts): bulk-add multiple hosts to multiple inbounds (#5677) 2026-07-08 23:35:20 +02:00
inbound.go feat(inbounds): add a narrow endpoint for subscription sort order (#6179) 2026-08-15 21:48:24 +02:00
index.go fix dead code, typo, and minor bugs in main.go, process.go and index.go (#6167) 2026-07-31 18:27:46 +02:00
login_limiter.go Repo-wide self-correcting audit: 54 verified bug fixes (#5970) 2026-07-17 00:33:06 +02:00
login_limiter_test.go chore: refresh dependencies, fix Linux tool tasks, modernize Go idioms 2026-07-25 16:08:09 +02:00
node.go fix(nodes): apply a rotated master mTLS certificate without restarting the panel (#6194) 2026-08-15 16:03:42 +02:00
node_credentials_writeonly_test.go fix(nodes): report probe heartbeat persistence failures (#6207) 2026-08-13 12:34:37 +02:00
panel_update_test.go fix: make all self-managed file downloads/installs atomic, with real completion status (#5711) 2026-07-02 18:19:33 +02:00
pwa.go feat(web): add network-only PWA installability (#6190) 2026-08-18 15:33:20 +02:00
pwa_test.go feat(web): add network-only PWA installability (#6190) 2026-08-18 15:33:20 +02:00
server.go fix(reality): make the REALITY target check usable on a private network (#6242) 2026-08-18 13:47:59 +02:00
setting.go fix(security): require a 2FA code to replace the stored TOTP secret 2026-08-19 19:54:15 +02:00
setting_test.go fix(security): require a 2FA code to replace the stored TOTP secret 2026-08-19 19:54:15 +02:00
spa.go refactor(frontend): replace axios with the native Fetch API 2026-07-08 01:09:18 +02:00
spa_test.go fix(web): serve panel SPA routes from NoRoute (#5536) 2026-06-24 21:19:12 +02:00
util.go fix(sub): honor trustedProxyCIDRs before forwarded URLs (#6135) 2026-07-29 21:01:59 +02:00
util_test.go
websocket.go
xray_setting.go feat(xray): browse geosite/geoip categories from routing rules (#6165) 2026-08-15 17:12:59 +02:00
xray_setting_warp_test.go fix(warp): surface update-clock persistence failures (#6209) 2026-08-13 12:31:05 +02:00