Skip to content

TOTP code & recovery code can be replayed within validity window #3359

Description

@houko

Location

  • crates/librefang-kernel/src/approval.rs:789-809 (verify_totp_code_with_issuer)
  • crates/librefang-kernel/src/approval.rs:864 (verify_recovery_code)
  • crates/librefang-api/src/routes/system.rs:1765-1825 (/api/approvals/{id}/approve)

Threat model
An authenticated Admin (or anyone who phishes a single TOTP code via a malicious approval prompt) can use one 6-digit TOTP code to approve multiple distinct high-risk operations within the same 30-second window — verify_totp_code_with_issuer only calls totp.check_current(code) and returns true; there is no "consumed codes" set keyed on (secret, slot).

Worse, verify_recovery_code does a read-modify-write on vault_get/vault_set("totp_recovery_codes") with no lock; two concurrent POST /api/approvals/{id}/approve requests carrying the same recovery code both pass position(), both succeed, and both call vault_set("…", "[]") — the recovery code, which is supposed to be one-time, approves N requests in parallel.

Suggested fix
Add a Mutex<HashSet<(slot_index, code_hash)>> for TOTP replay tracking (evict entries older than step + skew), and serialize verify_recovery_code behind a per-vault async mutex so the read-modify-write is atomic.

Metadata

Metadata

Assignees

No one assigned

    Labels

    area/kernelCore kernel (scheduling, RBAC, workflows)area/securitySecurity systems and auditingbugSomething isn't workingdifficulty/mediumHalf day, some familiarity with the crateneeds-triageAuto-applied when the issue title/body matched no area label — needs maintainer reviewsecuritySecurity issuesseverity/criticalRemote-exploitable, data loss, or production-blocking

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions