OTP security hardened
This commit is contained in:
+10
-6
@@ -137,13 +137,17 @@ These findings are prioritized below. Severity describes the potential security
|
||||
|
||||
### SA-009: TOTP enrollment has no recovery codes or reset workflow
|
||||
|
||||
**Severity:** Medium
|
||||
**Evidence:** `POST /api/user/otp/setup` returns the seed/provisioning URI and `POST /api/user/otp` requires a valid current OTP code to disable OTP.
|
||||
**Impact:** A user who loses the authenticator device or seed can be locked out. Administrators have no documented recovery path that does not weaken authentication. Database readers can also use the plaintext seed as a second factor.
|
||||
**Severity:** Medium, remediated in current worktree
|
||||
**Evidence before remediation:** `POST /api/user/otp/setup` returned the seed/provisioning URI and `POST /api/user/otp` required a valid current OTP code to disable OTP.
|
||||
**Impact:** A user who loses the authenticator device or seed could be locked out. Administrators had no documented recovery path that did not weaken authentication.
|
||||
|
||||
**Recommendation:** Generate one-time recovery codes during enrollment, display them once, hash them at rest, and invalidate each code on use. Require password reauthentication for disabling or replacing OTP. Add a controlled administrative recovery workflow with audit logging and notification. Avoid returning the seed after initial setup and never include it in profile responses.
|
||||
**Current state:** OTP enrollment generates ten random recovery codes and returns them only in the enrollment response. The database stores only SHA-256 hashes, and each code is atomically marked used. Normal OTP disablement requires the current password and a valid TOTP code; `/api/user/otp/recover` requires the current password and a valid unused recovery code, then disables OTP and clears the seed. Profile responses do not include the seed or recovery codes.
|
||||
|
||||
**Priority:** Medium.
|
||||
**Residual impact:** Recovery-code presentation is intentionally one-time; users who lose all codes can use the administrator-controlled OTP reset endpoint, which clears the seed and invalidates recovery codes. Recovery events should be added to the security audit log when SA-015 is addressed.
|
||||
|
||||
**Recommendation:** Keep recovery codes out of logs and API responses after enrollment, notify users when OTP is disabled or recovered, and add a controlled administrative recovery workflow with audit logging and notification.
|
||||
|
||||
**Priority:** Completed in code; operational recovery and audit logging remain.
|
||||
|
||||
### SA-010: Avatar validation trusts the client MIME type
|
||||
|
||||
@@ -247,7 +251,7 @@ Before production exposure:
|
||||
- [ ] Configure HTTPS, HSTS, CSP, Referrer-Policy, frame protections, `nosniff`, and trusted hosts.
|
||||
- [ ] Define a restrictive CORS policy or leave CORS disabled.
|
||||
- [ ] Add global request-size limits and hardened image decoding/re-encoding.
|
||||
- [ ] Add OTP recovery codes and a protected recovery workflow.
|
||||
- [x] Add OTP recovery codes and a protected recovery workflow.
|
||||
- [ ] Remove or implement refresh-token behavior.
|
||||
- [ ] Add security audit events and centralized redacted logging.
|
||||
- [ ] Rotate all credentials and set a unique high-entropy production secret.
|
||||
|
||||
Reference in New Issue
Block a user