Skip to content

[security-sensitive] 2FA re-enrollment rotates the TOTP secret in place and keeps verified=1 (integrity/availability) #10700

Description

@baozhoutao

Surfaced by QA run #10663 (identity-auth.two-factor-verify-to-activate / -enrollment-reveal) at 79ebb37. Existence + mechanism only; full reproduction withheld pending maintainer review per the auth/authz disclosure carve-out — available in the QA session on request.

What

Calling POST /api/v1/auth/two-factor/enable while 2FA is already active rotates the stored TOTP secret in place on the same sys_two_factor row and leaves verified = 1 carried over from the prior enrollment. The replacement secret — which no code has ever confirmed — becomes immediately live at the sign-in challenge, while the previously verified secret goes dead. Not a privilege escalation (the call requires a live session and the account password, and such an actor could call /two-factor/disable anyway).

Impact

  • Integrity of the flag: verified no longer describes the secret actually stored — any code or audit trusting "this factor was user-confirmed" is wrong after a re-enroll.
  • Availability: a user who re-enrolls and mis-scans the QR is locked out instantly — the old authenticator is already dead and there is no confirmation step to catch it.

Mechanism (fix-oriented)

The enable path treats an already-enrolled account the same as a fresh one, overwriting the secret without resetting verified to false or requiring a re-verification before the new secret is honored at the challenge. Fix direction: on re-enroll, set verified = false and gate the new secret on a fresh verify (or reject enable when already enabled and route through a dedicated rotate flow).

Related

Same family: sys_user.generate_backup_codes silently re-provisions on an already-enabled account too (see the non-sensitive lockout card #10681).

QA-source: #10663 · identity-auth.two-factor-verify-to-activate · clause 2 / negative 1

Metadata

Metadata

Assignees

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions