
High fidelity scanner for CVE-2026-41940 (cPanel & WHM authentication bypass)
A high-fidelity scanner for the cPanel/WHM authentication bypass tracked as CVE-2026-41940. It identifies vulnerable hosts without producing the false-negatives common to public proofs-of-concept and detections, and without triggering the account lockout and root-IP-allowlist mechanisms that interfere with naive scanning.
The tool also bundles a separate, opt-in exploit chain for a same-family
CalDAV path-traversal bug on cpdavd (ports 2079 plain / 2080 TLS) —
CVE-2026-29205 —
that lets a remote attacker read arbitrary files as root
once a small SMTP-driven setup step succeeds. cPanel 11.134.0.26 fixes the
underlying RAII lifetime bug so the read now runs as the unprivileged account
owner; the traversal itself still reaches cpdavd but cannot escalate beyond
what that account can already read. The CalDAV chain is gated behind
--exploit and is off by default because it sends real emails and reads
files from confirmed targets — see the
Exploit mode (active) section.
Most public detections for CVE-2026-41940 share three problems. This scanner addresses each of them.
You can read our blog post on this detection technique here: https://slcyber.io/research-center/high-fidelity-check-for-the-cpanel-authentication-bypass-cve-2026-41940/
cPanel's per-vhost Apache configuration installs a ProxyPass that forwards
/___proxy_subdomain_whm to 127.0.0.1:2086 and /___proxy_subdomain_cpanel
to 127.0.0.1:2080 regardless of the request's Host header. The
RewriteCond only constrains the rewrite that maps the management subdomain
onto the proxy path; the ProxyPass itself is unconditional. Hitting these
paths on any vhost served by a cPanel-managed Apache reaches the same vulnerable
backend as the management ports.
Scanners that only probe ports 2082/2083/2086/2087 will report a host as not vulnerable when those ports are firewalled, even though the bug is fully reachable through 443. This scanner probes 2087, 2083, and the two proxy paths on 443 by default.
cPanel ships cphulkd, which locks accounts out after a small number of failed
password attempts, and authorized_whm_root_ips, which restricts root logins
to a configured list of source addresses. A scanner that exploits the bypass by
trying to inject a session for root will:
This scanner avoids both issues on the WHM side by injecting expired=1 into
the session payload under a randomly generated username. The session injection
is verified by visiting the resulting cpsessXXXX URL and matching
msg_code:[expired_session] in the response body, which is only present when
the injection succeeded. No real account is targeted, so no real account can be
locked out, and the root allowlist is irrelevant because no root login is
attempted.
The cPanel daemon (cpaneld, ports 2083 and the /___proxy_subdomain_cpanel
path) requires the supplied username to correspond to an existing cPanel
account on disk (-f /var/cpanel/users/$user). A username of root will never
satisfy this check because root is a system user, not a cPanel user. Detections
that try only root produce false negatives on this surface. This scanner uses
a configurable wordlist of common cPanel usernames against the cPanel surface
and falls back to the random-username path on the WHM surface, which has no
such restriction.
For each target the scanner performs the following steps per surface:
GET /login and read the Set-Cookie header for either
whostmgrsession (WHM) or cpsession (cPanel). The cookie contains a
comma-separated session-name component.GET / with an Authorization: Basic header whose decoded value is
<user>:\xff\nexpired=1. The trailing \nexpired=1 is the session-injection
payload. The session cookie from step 1 is replayed unmodified.Location header from the response and extract the cpsessXXXX
token.GET /<cpsessXXXX>/ with the original cookie and look for
msg_code:[expired_session] in the body. Its presence proves the session
injection succeeded and the host is vulnerable.On WHM (port 2087 and the /___proxy_subdomain_whm path on 443) the username
is a random u followed by ten hex characters. On cPanel (port 2083 and the
/___proxy_subdomain_cpanel path on 443) the scanner walks its username
wordlist and stops at the first match.
By default the scanner probes 2087, 2083, and 443 in that order and stops as soon as any surface confirms vulnerability.
--exploit)CVE-2026-29205 — cPanel/WHM WP2 Security Update, May 13 2026. Fixed in cPanel 11.134.0.26. The advisory tracks the same
cpdavdprivilege-drop regression this exploit chain abuses.
Full write-up of the bug and the exploitation chain: https://slcyber.io/research-center/new-age-of-collisions-reading-arbitrary-files-pre-auth-as-root-in-cpanel-cve-2026-29205
cpdavd on ports 2079 (plain HTTP) and 2080 (TLS) trusts the
<principal>/<collection>/... path it builds when serving CalDAV/CardDAV
resources. By crafting a request whose path component encodes .. segments
and pointing it at a maildir folder whose on-disk name also encodes traversal
(x-attachment-1-y), cpdavd can be coerced into reading any file on disk
as root, regardless of ownership or permissions — including /etc/shadow,
/etc/passwd, and the per-user mail spools.
The defense-in-depth that was supposed to drop privileges to the account
owner before the read silently failed: the Cpanel::AccessIds::ReducedPrivileges
object was constructed in void context, so its destructor restored root
privileges before the read ran. cPanel 11.134.0.26 binds the object to a
my $privs lexical so it lives through the -f / stat / open / read
chain; on patched hosts the read therefore runs as the unprivileged account
owner instead of root.
The vulnerable folder must exist on disk before the read works. cPanel
auto-creates a folder named .x-attachment-1-y for the recipient
<user>+x-attachment-1-y@<domain> the first time an email lands at that
sub-address. The chain is therefore:
info, admin,
webmaster).<prefix>+x-attachment-1-y@<domain> to each candidate. Accepted
RCPT TO responses are tracked.GET against cpdavd
on ports 2080 (TLS) and 2079 (plain), under both the /calendar/ and
/addressbook/ collection prefixes.A success returns the file's bytes; the finding records the email used, the collection, the byte count, and the first 200 bytes as a preview.