XenForo 2.3.12 build 2031270 allowed the same OAuth2 authorization code to be redeemed more than once. Each successful exchange created a separate access token and refresh-token family.
Technical details
grantAuthorizationCode() loaded the code, checked isValid() and created the tokens. It then returned the response without deleting the code or marking it as used. Two simultaneous requests could also pass the validity check before either one finished.
Reproduction
- Complete an OAuth2 authorization flow and capture the token request.
- Send the request once and record the returned access and refresh tokens.
- Send the same request again with the same authorization code.
- Verify both access tokens at
/api/me.
Both exchanges returned HTTP 200. The responses contained different access tokens and different refresh tokens for the same user.
Impact
Anyone able to capture a complete valid token request could replay it until the authorization code expired. Client authentication and PKCE material remained required where applicable. Every replay created another refresh-token family.
XenForo 2.3.13 consumes the authorization code while issuing tokens, including for concurrent exchanges.
References
XenForo 2.3.12 build 2031270 allowed the same OAuth2 authorization code to be redeemed more than once. Each successful exchange created a separate access token and refresh-token family.
## Technical details
`grantAuthorizationCode()` loaded the code, checked `isValid()` and created the tokens. It then returned the response without deleting the code or marking it as used. Two simultaneous requests could also pass the validity check before either one finished.
## Reproduction
1. Complete an OAuth2 authorization flow and capture the token request.
2. Send the request once and record the returned access and refresh tokens.
3. Send the same request again with the same authorization code.
4. Verify both access tokens at `/api/me`.
Both exchanges returned HTTP 200. The responses contained different access tokens and different refresh tokens for the same user.
## Impact
Anyone able to capture a complete valid token request could replay it until the authorization code expired. Client authentication and PKCE material remained required where applicable. Every replay created another refresh-token family.
XenForo 2.3.13 consumes the authorization code while issuing tokens, including for concurrent exchanges.
## References
- [CVE-2026-73311](https://www.cve.org/CVERecord?id=CVE-2026-73311)
- [PoC](https://github.com/BomboBombone/CVE-2026-73311)
- [VulnCheck advisory](https://www.vulncheck.com/advisories/xenforo-oauth2-authorization-code-reuse)
- [XenForo 2.3.13 release](https://xenforo.com/community/threads/xenforo-2-3-13-and-add-ons-released-includes-security-fixes.239857/)