PST-012: Accounts with no password or second factor pass reauthentication automatically, so a hijacked SSO-only session can delete the account #741

Closed
opened 2026-10-10 10:55:51 +00:00 by tiagoagueda · 1 comment
Owner

Found in the security audit of 2026-10-10 (SECURITY-AUDIT-2026-10-10.md), run against main at c30851b from 8 to 10 October 2026, as PST-012. Severity: Low.

The text below is the audit's entry, unchanged apart from links to the other issues it names. The finding was produced by automated review and checked by a second automated pass; re-check it before acting on it.


  • Severity: Low
  • Category: reauthentication
  • Location: src/postulo/accounts/views.py (495-507)
  • Found by: authentication and sessions

Who can do it, and what they need. Someone holding an unattended or stolen session of an account created through single sign-on that never set a password or a passkey.

How it works.

  1. allauth's did_recently_authenticate returns True whenever get_reauthentication_flows(user) is empty, i.e. no usable password and no MFA.
  2. DeleteAccountView's reauthentication_required therefore never challenges such a session; the only remaining check is typing the account's own address, which is shown on the same settings pages.
  3. The same holds for allauth's MFA set-up views, so the session can enrol an authenticator the real owner does not hold.

Impact. Narrow: needs a live session of an SSO-only account; the deletion is at least loud (everything is removed) and the MFA enrolment is visible under Settings → Account.

Evidence.

views.py:506 `@method_decorator(reauthentication_required)`; allauth/account/internal/flows/reauthentication.py:76-83 `if not get_reauthentication_flows(request.user): ... return True`.

Verification (verdict: confirmed; severity after verification: Low; first-pass claim: Informational). Attacker: someone holding a live session of a passwordless, MFA-less account (typically SSO-only), such as an unattended unlocked machine. Gain: delete the account with only the visible address typed, set a password or enrol an authenticator for persistence, and, if the account is an administrator's, download or delete backups (all users' data) with no proof. Remediation: for accounts with no reauthentication flow, require something Postulo can check itself (for example a mailed code or a fresh SSO round-trip) before delete, MFA enrolment, set-password and backup download, and correct the DeleteAccountView docstring. Cited lines views.py:495-507 and allauth reauthentication.py:76-83 are correct.

Suggested remediation. For accounts with no local reauthentication method, require a fresh provider round trip (allauth's reauthenticate via socialaccount) or an emailed code before destructive settings; or nudge SSO-only accounts to add a passkey.

Found in the security audit of 2026-10-10 (`SECURITY-AUDIT-2026-10-10.md`), run against `main` at `c30851b` from 8 to 10 October 2026, as **PST-012**. Severity: **Low**. The text below is the audit's entry, unchanged apart from links to the other issues it names. The finding was produced by automated review and checked by a second automated pass; re-check it before acting on it. --- - **Severity:** Low - **Category:** reauthentication - **Location:** `src/postulo/accounts/views.py` (495-507) - **Found by:** authentication and sessions **Who can do it, and what they need.** Someone holding an unattended or stolen session of an account created through single sign-on that never set a password or a passkey. **How it works.** 1. allauth's did_recently_authenticate returns True whenever get_reauthentication_flows(user) is empty, i.e. no usable password and no MFA. 2. DeleteAccountView's reauthentication_required therefore never challenges such a session; the only remaining check is typing the account's own address, which is shown on the same settings pages. 3. The same holds for allauth's MFA set-up views, so the session can enrol an authenticator the real owner does not hold. **Impact.** Narrow: needs a live session of an SSO-only account; the deletion is at least loud (everything is removed) and the MFA enrolment is visible under Settings → Account. **Evidence.** ```text views.py:506 `@method_decorator(reauthentication_required)`; allauth/account/internal/flows/reauthentication.py:76-83 `if not get_reauthentication_flows(request.user): ... return True`. ``` **Verification** (verdict: confirmed; severity after verification: Low; first-pass claim: Informational). Attacker: someone holding a live session of a passwordless, MFA-less account (typically SSO-only), such as an unattended unlocked machine. Gain: delete the account with only the visible address typed, set a password or enrol an authenticator for persistence, and, if the account is an administrator's, download or delete backups (all users' data) with no proof. Remediation: for accounts with no reauthentication flow, require something Postulo can check itself (for example a mailed code or a fresh SSO round-trip) before delete, MFA enrolment, set-password and backup download, and correct the DeleteAccountView docstring. Cited lines views.py:495-507 and allauth reauthentication.py:76-83 are correct. **Suggested remediation.** For accounts with no local reauthentication method, require a fresh provider round trip (allauth's reauthenticate via socialaccount) or an emailed code before destructive settings; or nudge SSO-only accounts to add a passkey.
tiagoagueda added this to the 0.6.0 milestone 2026-10-10 10:57:24 +00:00
Author
Owner

Fixed in 85b38f408 on main.

Fixed in 85b38f408 on main.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
Postulo/postulo#741
No description provided.