PST-008: The single sign-on handshake can be started by a cross-site GET (SOCIALACCOUNT_LOGIN_ON_GET) #737
Labels
No labels
accessibility
authentication
breaking change
bug
documentation
enhancement
interface
internationalisation
observability
performance
security
tier
1
tier
2
tier
3
tier/4
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
Postulo/postulo#737
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Found in the security audit of 2026-10-10 (
SECURITY-AUDIT-2026-10-10.md), run againstmainatc30851bfrom 8 to 10 October 2026, as PST-008. 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.
src/postulo/config/settings/base.py(331-334; 331-333; 333)Who can do it, and what they need. A hostile page the victim visits while signed in to Postulo (for
process=connect) or while signed out (forprocess=login). For account linking to benefit the attacker, the operator's identity provider must itself be vulnerable to login CSRF or must auto-approve with a session the attacker controls; otherwise the flow links the victim's own identity, which is harmless. …How it works.
<img src="https://postulo.example/accounts/sso/oidc/login/?process=connect">or a link.requests.Session()(socialaccount/adapter.py:344-347), not throughpostulo.plugins.http.client(); scratch test showed an unauthenticated GET to/accounts/sso/oidc/login/immediately attempting an outbound HTTPS request.Impact. Account linking by a cross-site GET when the IdP is weak; unauthenticated callers can make the server issue one outbound request per hit to the configured IdP (destination is operator-configured, so not SSRF, but it bypasses the project's guarded client and its destination policy).
Evidence.
Verification (verdict: confirmed; severity after verification: Low). Keep low, close to informational. The real precondition for account linking is an IdP-side login-CSRF or auto-approve weakness, which is an operator-chosen trust item. The outbound-fetch amplification exists with or without LOGIN_ON_GET, needs no extra precondition beyond an extra GET and POST, and is a DoS-class concern the threat model puts out of scope. Treat 'allauth's HTTP session bypasses the guarded client' as informational. The path is operator-configured and the IdP is trusted. The guard would break LAN identity providers. Remediation options: keep the setting and document the trade-off, or switch to POST and add the IdP origin to form-action when SSO is configured. Rate-limiting the unauthenticated entry is optional. Merge with #90.
Suggested remediation. Set SOCIALACCOUNT_LOGIN_ON_GET back to allauth's default (False) and make the SSO button a POST form; the CSP concern can be met by listing the IdP's authorize origin in
form-action(or by answering the POST with a 303 to the IdP, whichform-action 'self'permits in Firefox/Safari and which Chrome also allows for the initial POST target being self when the redirect is followed from a non-form navigation) rather than by opening the flow to GET. Document that the IdP must enforce its own login-CSRF protection. Consider caching the discovery document or routing allauth's HTTP through the guarded client.Also covered by this issue.
src/postulo/config/settings/base.py(331-333); Low). Classic login-CSRF through the provider; low here because the instance has one operator-chosen IdP and allauth's state parameter still binds the callback to the session that started it. Accounts dimension overlap; recorded because it is a settings default.src/postulo/config/settings/base.py(331-333); Informational). Hardening gap acknowledged in allauth's own documentation; the project chose GET because form-action 'self' in the CSP blocks the redirect of a POSTed form. No concrete account compromise was found.src/postulo/config/settings/base.py(333); Informational). Minor: drive-by initiation of SSO; no account linking without the victim completing the provider step.Fixed in
d4251b1c6on main.