
Proof-of-concept and lab reproduction for CVE-2026-81294, an unauthenticated privilege escalation in the WordPress Authorizer plugin via unverified OAuth2 email matching.
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · CVE-2026-81294
Authorizer 3.15.1 - Paul Ryan
I am @abraxas_null. Loopback lab. The client is CVE-2026-81294-Abraxas-Labs.py.
Unverified email is enough. 3.15.1 maps GitHub emails[] to entry.email without checking entry.verified. Generic OAuth2 has the same hole. HTTP is GET /wp-login.php?external=oauth2, not admin-ajax. If that email matches an admin, Authorizer sets the cookie. 3.15.2 filters empty entry.verified for GitHub and adds oauth2_require_verified_email for generic.
| CVE | CVE-2026-81294 · CVE.org |
| CWE | CWE-266 |
| CVSS | Critical: 9.8 CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H |
| Product | WordPress - Authorizer |
| Affected | all versions through 3.15.1 (inclusive) |
| Patched | 3.15.2 and later |
| Auth | none |
| License | GNU Affero GPL v3.0 |
| Lab | 127.0.0.1 only |
Register an OAuth identity whose unverified email is the site admin's. Complete the login redirect. You are that admin. The lab uses a loopback mock and a display name witness.
Patchstack named unverified GitHub emails. I read the GitHub /emails map, then ran the same missing check on generic OAuth2 against a loopback mock.
GET /wp-login.php?external=oauth2 with a cookie jar. Follow 302s. GET /?auth_lab=1. Witness POCWitness81294.
Wrong turns: POST action=oauth2 at admin-ajax.php (login HTML, no cookie); dropping PHPSESSID between authorize and callback; token URL not reachable from PHP; oauth2_email_not_verified on 3.15.2; empty_username when the email did not map.
Port 8088. Authorizer 3.15.1. oauth2=1 generic mock. Admin email [email protected], display_name POCWitness81294.
Target only 127.0.0.1:8088 (or the loopback you bound).
cd lab
docker compose up --force-recreate
python3 ../CVE-2026-81294-Abraxas-Labs.py
Witness: GET /?auth_lab=1 after OAuth is POCWitness81294. Login page HTML without that string is not it.
Ways to lose without learning anything:
oauth2_email_not_verifiedempty_usernameUpdate Authorizer to 3.15.2 or newer. Re-run CVE-2026-81294-Abraxas-Labs.py against the patched build: POCWitness81294 must not appear.
Plugin directory: authorizer
Trac browser: plugins.trac.wordpress.org/authorizer
SVN tags: plugins.svn.wordpress.org/authorizer
Abraxas Labs: abraxaslabs.tech · github.com/abraxas · @abraxas_null
GNU Affero GPL v3.0. See LICENSE.
The client talks to loopback. Using it against systems you do not own is not authorized by Abraxas Labs. No warranty.