
Proof-of-concept and technical write-up for CVE-2026-73312, an OAuth2 refresh token replay vulnerability in XenForo before 2.3.13. Includes a Python script to test for the issue.
XenForo before 2.3.13 can leave an OAuth2 refresh token reusable when its parent access token has expired.
XenForo intentionally lets a refresh token outlive its short-lived access token. During rotation it creates the replacement token family, then asks the parent access-token revoker to consume the old family. That revoker returns early when the access token is expired, before revoking the related refresh token.
The original refresh token can consequently be submitted again, producing another independent token family with the same user and scopes. The attacker must already possess a valid refresh token (and the client secret for a confidential client). The issue extends a compromised credential's useful lifetime; it is not a login bypass or scope escalation by itself.
I reproduced the issue on XenForo 2.3.12 (build 2031270) after allowing the parent access token to expire. XenForo 2.3.13 contains the fix.
python poc.py https://xenforo.example CLIENT_ID REFRESH_TOKEN --verify-me
The script submits one authorized test token twice and prints only hashes and status. A replay rejection exits with status 0; a confirmed vulnerable result exits with status 1 so automation does not mistake the vulnerable condition for success.
Discovered by Marco Paciaroni (BomboBombone).