What Is CVE-2026-41940?
CVE-2026-41940 is a critical pre-authentication remote authentication bypass affecting cPanel & WHM and WP Squared — the control panel software that quietly powers an estimated 70 million domains and 94% of the web hosting control panel market.
The root cause is a CRLF injection flaw in the way cPanel’s service daemon (cpsrvd) reads and writes session files. An unauthenticated attacker can inject two characters — a carriage return (\r) and a line feed (\n) — into a login request header, manipulate the resulting session file on disk, and promote themselves to a fully authenticated root session. No password. No 2FA. No user interaction. No credentials at all.
The vulnerability was publicly disclosed on April 28, 2026, by security firm watchTowr. Its CVSS score is 9.8 out of 10. CISA added it to the Known Exploited Vulnerabilities (KEV) catalog on May 1, 2026, and the Shadowserver Foundation has confirmed at least 44,000 servers already compromised — with ransomware and state-sponsored espionage campaigns both observed in the wild.
Why This Vulnerability Is Unusually Dangerous
Most authentication bypasses are severe. CVE-2026-41940 is in a different category for three compounding reasons:
1. The attack surface is enormous. cPanel controls 94% of the web hosting control panel market. Roughly 1.5 million cPanel instances are directly exposed to the public internet. A single vulnerable server typically hosts hundreds or thousands of websites, databases, mailboxes, and DNS zones. Compromising one server means compromising everything on it.
2. Exploitation predates the patch by two months. KnownHost confirmed in-the-wild exploitation began as early as February 23, 2026 — roughly eight weeks before cPanel issued a fix. The vulnerability was used as a zero-day during that entire window, with multiple threat groups running automated mass-exploitation campaigns within 24 hours of public disclosure.
3. 2FA does not help. The exploit injects tfa_verified=1 directly into the session file before any authentication code runs. Both the password gate and the two-factor authentication gate are bypassed entirely. Enabling 2FA on your cPanel instance does not protect an unpatched server.
The Affected Versions and Patch Status
CVE-2026-41940 affects all currently supported versions of cPanel & WHM released after version 11.40, and WP Squared (a managed WordPress hosting platform built on cPanel).
Vulnerable versions (all builds prior to the patched releases below):
| Branch | First Patched Version |
|---|---|
| 11.110.x | 11.110.0.97 |
| 11.118.x | 11.118.0.63 |
| 11.126.x | 11.126.0.54 |
| 11.132.x | 11.132.0.29 |
| 11.134.x | 11.134.0.20 |
| 11.136.x | 11.136.0.5 |
| WP Squared | 136.1.7 |
Affected interfaces and ports:
| Interface | Ports |
|---|---|
| cPanel (user-facing) | TCP 2082 (HTTP), TCP 2083 (HTTPS) |
| WHM (host-facing admin) | TCP 2086 (HTTP), TCP 2087 (HTTPS) |
| Webmail | TCP 2095 (HTTP), TCP 2096 (HTTPS) |
cPanel’s TIER system means that different hosts run different release tracks. An organization on the STABLE tier might be running 11.126.x while one on the CURRENT tier might be on 11.136.x. Both are affected until patched to the corresponding fixed build. Administrators can verify the installed version by running /usr/local/cpanel/cpanel -V on the server.
How to Patch
Option 1 — Update via WHM (Recommended)
If your WHM interface is accessible:
- Log in to WHM
- Navigate to Home → cPanel → Upgrade to Latest Version
- Apply the update and verify the installed version matches the patched build for your branch
Option 2 — Update via Command Line
SSH into your server as root and run:
For organizations that manage their own cPanel installations, the update process is straightforward:
/usr/local/cpanel/scripts/upcp
/scripts/upcp --force
After the update, verify your version:
/usr/local/cpanel/cpanel -V
Compare the output against the patched version table above. If auto-updates are disabled on your server, re-enable them after patching:
/usr/local/cpanel/bin/whmapi1 set_tweaksetting key=cpanel_autoupdate_enabled value=1
Note: For organizations using managed hosting, the responsibility falls on the provider. The exposure window between April 28 (disclosure) and whenever a provider’s rolling patch deployment reaches a specific server is exactly the period during which internet-exposed instances were vulnerable.
Servers with auto-update disabled or pinned to a specific build will not patch automatically. Manual verification is required.
What cPanel Is, and Why This Matters
For anyone not familiar with the hosting world: cPanel is the dominant web hosting control panel. It provides the graphical interface that lets shared hosting customers manage their websites, email accounts, databases, and DNS records. WHM (Web Host Manager) sits above it and gives hosting providers themselves root-level control over the entire server — provisioning accounts, adjusting resource limits, managing SSL certificates across tenants.
The key word in that last sentence is root-level. WHM operates with full administrative access to the underlying Linux server. When a hosting provider installs cPanel, they are putting a web application with a direct line to UID 0 on their infrastructure. When that web application has an authentication bypass, the attacker doesn’t just get access to a single website — they get access to the server, every customer account on it, every database, every email inbox, and every file hosted there.
That is the scope of what CVE-2026-41940 enables, and it is why the immediate response from major hosting providers was to block the cPanel management ports (2082, 2083, 2086, 2087) at their perimeter firewalls while patches were prepared. The exposure window between public disclosure and widespread patching is exactly the kind of moment attackers have been waiting for.
The Vulnerability at a Glance
At its core, CVE-2026-41940 is a CRLF injection vulnerability in cPanel’s HTTP Basic authentication handler. CRLF refers to the carriage return (\r) and line feed (\n) characters — the standard line separator in HTTP headers. When these characters appear in data that gets written to a file without being sanitized, an attacker can inject new lines into that file. If the file later gets re-parsed line by line, those injected lines are treated as legitimate records.
In cPanel’s case, the data being written is the user’s password. The file being written to is a pre-authentication session file on disk. And the re-parsing happens automatically as part of a specific internal code path that cPanel triggers when a session’s security token doesn’t match. The result is that an attacker who is not logged in can craft a password string containing embedded newlines and session field definitions, submit it to the server, and then trigger a specific request sequence that causes cPanel to promote their unauthenticated session into a fully authenticated root session.
The session ends up containing user=root, hasroot=1, tfa_verified=1, an attacker-chosen security token, and a recent authentication timestamp. From cPanel’s perspective, this session looks indistinguishable from a legitimate root login that completed successfully moments ago.
Understanding the Technical Root Cause
To understand why this works, you need to understand how cPanel manages sessions internally. When a user logs in, cPanel creates a session file on disk under /var/cpanel/sessions/raw/. This file is a simple key=value text format, one record per line. Alongside the raw file, cPanel also maintains a JSON cache of the session. Most requests load from the JSON cache for performance. But under certain conditions — specifically when a session is regenerated — cPanel re-parses the raw file to rebuild the cache.
The vulnerability lives in a function called saveSession() inside the Cpanel::Session module. This function is responsible for writing session data to the raw file on disk. The problem is that saveSession() does not call filter_sessiondata(), the sanitization routine that strips carriage returns and newlines from session data before writing. Other session-handling functions — Cpanel::Session::create() and Cpanel::Session::Modify::save() — do call the sanitizer. But saveSession() doesn’t, and the HTTP Basic auth handler uses saveSession() directly.
When a user sends HTTP Basic auth credentials, cPanel decodes the base64-encoded Authorization header, extracts the password field, and calls saveSession() to write it to the raw session file. Because the password is written verbatim — without sanitization — any CRLF characters embedded in the password become literal newlines in the session file.
The second half of the vulnerability is how those injected lines get promoted into actual session state. The mechanism is triggered by do_token_denied(), a cPanel internal handler that fires when an incoming request carries a security token that doesn’t match the current session’s token. When this happens, cPanel calls Cpanel::Session::Modify::new($session, nocache => 1). The nocache => 1 flag is the critical part: it instructs cPanel to bypass the JSON cache and re-read the raw session file directly, line by line. Every line in that file — including the attacker’s injected lines — gets parsed as a key=value pair. Then Cpanel::Session::Modify::save() rewrites the JSON cache from that parsed data, promoting all the injected values to top-level session entries.
# The vulnerable code path (simplified):
sub saveSession {
my ($session, $session_ref) = @_;
# ...
# No call to filter_sessiondata() here -- the raw password
# with embedded \r\n is written verbatim to the session file
# ... write key=value lines to /var/cpanel/sessions/raw/
}
# The regeneration trigger:
Cpanel::Session::Modify::new($session, nocache => 1); # re-reads raw file
Cpanel::Session::Modify::save(); # writes JSON cache
# with injected keys
The fix is straightforward: the patched build adds a call to filter_sessiondata($session_ref) inside saveSession() itself, so sanitization happens at the write boundary regardless of which calling path reaches it. The vulnerability existed because sanitization was the caller’s responsibility, and one caller — the HTTP Basic auth handler — didn’t fulfill it.
The Exploit Chain Step by Step
The full attack takes four HTTP requests, and understanding each one shows just how deliberately crafted this exploit is.
Step 1: Create a pre-authentication session. The attacker sends a POST to /login/?login_only=1 with user=root&pass=wrong. This is a normal, failed login attempt. cPanel creates a pre-authentication session file and returns a session cookie — specifically, a whostmgrsession cookie — in the response. The cookie value contains a random session ID followed by a %2c separator and an obfuscation suffix.
Step 2: Inject the malicious payload via HTTP Basic auth. The attacker re-sends a GET request to /?attempt=1, reusing the session cookie from step 1 but without the obfuscation suffix after the %2c delimiter. This request carries an Authorization: Basic header whose base64-decoded value is:
root:x\r\nhasroot=1\r\ntfa_verified=1\r\nuser=root\r\ncp_security_token=/cpsess9999999999\r\nsuccessful_internal_auth_with_timestamp=\r\n
When cPanel processes this, it extracts the password field (everything after the colon) and writes it to the session file via saveSession(). The embedded \r\n sequences are written as actual newlines, creating a multi-line session file where the attacker’s fields appear as separate key=value records below the legitimate session data.
Step 3: Trigger the session regeneration. The attacker requests a protected URL using the security token they injected — something like GET /cpsess9999999999/scripts2/listaccts. At this point, cPanel’s cache still has the unmodified session (before the attacker’s injection was written). The URL-bound security token /cpsess9999999999 doesn’t match the cached session’s token, so do_token_denied() fires. This calls Cpanel::Session::Modify::new($session, nocache => 1), which re-parses the now-corrupted raw session file. Every injected line becomes a top-level session entry. Modify::save() writes the poisoned data back to the JSON cache.
Step 4: Use the promoted root session. The attacker sends any request under the cpsess9999999999 token prefix — for example, GET /cpsess9999999999/json-api/version?api.version=1. The request passes cPanel’s URL-token CSRF check (the token matches the injected one), the recent successful_internal_auth_with_timestamp suppresses the password challenge, tfa_verified=1 bypasses the 2FA gate, and user=root with hasroot=1 establishes identity. cPanel executes the handler as root. The JSON response returns the cPanel build version — an unambiguous proof-of-concept that the session is running with full administrative access.
There is one minor reliability wrinkle: when Modify::save() serializes the session hash back to JSON, Perl’s key iteration order is randomized. Occasionally, the original unset cp_security_token overwrites the injected value, breaking the chain. A handful of retries across the four-request sequence makes the exploit reliably reproducible in practice.
Why Two-Factor Authentication Does Not Help Here
One of the more striking aspects of this vulnerability is that 2FA provides no protection whatsoever. In a normal cPanel login flow, after password verification succeeds, the user is presented with a TOTP or backup code challenge. The session is only marked tfa_verified=1 after the correct code is submitted.
In the exploit chain, the attacker never touches the authentication code path at all. They skip it entirely by injecting tfa_verified=1 directly into the session file. By the time cPanel’s request handler evaluates whether 2FA has been verified, it simply reads the session field — which the attacker has already set to true — and proceeds. The 2FA mechanism assumes the session data it’s reading was set by a legitimate authentication flow. That assumption is what the attack invalidates.
This has a practical implication for defenders: organizations that believed 2FA protected their cPanel instances from remote takeover were wrong. The protection evaporated the moment this vulnerability existed.
What an Attacker Can Do with Root Access to WHM
It’s worth being explicit about what full root WHM access actually means in a shared hosting context, because “root access to the server” can feel abstract.
An attacker with this level of access can read every file on the server — that includes every customer website’s source code, every database, every email stored in mail directories, and every SSL private key. They can create new privileged user accounts that persist after patching. They can install SSH keys in root’s authorized_keys, enabling persistent backdoor access over SSH that has nothing to do with cPanel authentication. They can install kernel rootkits that survive reboots. They can modify every customer website to serve malware or phishing pages. They can extract database credentials from configuration files and pivot into backend systems. On a shared hosting server with hundreds of tenant accounts, the blast radius of a single exploitation event is enormous.
Perhaps more importantly for enterprise security teams: many customer websites on shared hosting have integrations with corporate systems — CRM connections, API keys stored in configuration files, OAuth tokens. A compromised hosting server is not just a website problem. It is potentially a credential and access problem for every connected system.
Forensics: What to Look For
Because this attack operates through file manipulation rather than a traditional auth bypass, detection requires knowing where to look.
The most direct forensic signal is in /var/cpanel/sessions/raw/. A legitimate pre-authentication session file will never contain user=root, hasroot=1, tfa_verified=1, successful_internal_auth_with_timestamp, or multiple pass= lines. Any of these in a session that was never legitimately upgraded to an authenticated state is a strong indicator of exploitation. Multiple pass= lines in a single session file are effectively proof — that pattern can only be produced by the CRLF injection chain.
If session files are not being forwarded to an external SIEM (most deployments don’t), the access logs offer two useful signals. First, look for a 401 response on POST /login/?login_only=1 followed within seconds by a GET / carrying an Authorization: Basic header from the same source IP and session cookie. An Authorization header on a request to / rather than /login is anomalous and not produced by any legitimate cPanel client. Second, look for cpsess tokens in URL paths that don’t match tokens issued by cPanel’s own Set-Cookie headers. Legitimate cpsess values are 16 hexadecimal digits generated by cpsrvd; an injected value will typically be something like /cpsess9999999999 — a distinctive pattern.
For Splunk deployments, correlation queries can join the 401 events on /login/ with subsequent Authorization-header requests sharing the same session cookie, or flag cpsess tokens that appear first in a URL path rather than in a Set-Cookie header.
The Structural Problem This Exposes
There is a broader issue here that CVE-2026-41940 makes hard to ignore. cPanel controls approximately 94% of the web hosting control panel market. That means a single vulnerability in a single product simultaneously affects millions of servers and the hundreds of millions of websites hosted on them. The organizations whose sites live on those servers have no way to patch the vulnerability themselves. They are entirely dependent on their hosting provider’s response timeline.
The initial response from major hosting providers — blocking the cPanel management ports at the network perimeter — bought time but didn’t solve the problem. It also introduced its own operational friction: legitimate administrators who need to manage their servers remotely suddenly found themselves blocked. Providers with strong network security posture and fast patch deployment pipelines minimized the exposure window. Providers without those capabilities left their customers exposed for longer.
This is the structural reality of critical infrastructure monocultures. A single critical vulnerability becomes an industry-wide incident. The diversity that normally provides resilience — different hosting providers, different server configurations, different software stacks — all converges at a single point: the cPanel authentication handler. When that point fails, everything downstream of it fails simultaneously.
Detecting Compromise
Because the exploit works by writing crafted entries into pre-auth session files, detection focuses on artifacts left in the session directory.
1. Check Session Files for Injected Entries
cPanel has published a detection script. To manually inspect, check for session files in /var/cpanel/sessions/raw/ that contain these injected fields without a corresponding legitimate login:
grep -rl "hasroot=1" /var/cpanel/sessions/raw/
grep -rl "tfa_verified=1" /var/cpanel/sessions/raw/
grep -rl "successful_internal_auth_with_timestamp" /var/cpanel/sessions/raw/
Session files containing these values without a matching legitimate authentication event are exploitation artifacts.
2. Review Access Logs on cPanel Ports
Look for unusual HTTP requests to the cPanel login endpoint, particularly:
- Requests with
Authorization: Basicheaders containing encoded\r\nsequences - Requests with malformed or truncated
whostmgrsessioncookies - Root-level WHM access from unexpected IP addresses
grep -E "(2082|2083|2086|2087)" /var/log/cpanel-access_log | grep "POST.*login"
3. Check for Ransomware Indicators
If exploitation predates your patch date (i.e., your server was unpatched between February 23 and April 28, 2026), scan for .sorry extension files and unexpected processes:
find / -name "*.sorry" 2>/dev/null
4. Use the Nuclei Detection Template
Hadrian has published a Nuclei template that exercises the full exploitation chain and validates whether a target is vulnerable without false positives:
nuclei -u https://target:2087 -t cve-2026-41940-native.yaml
A confirmed-vulnerable target returns the extracted cPanel version string. Patched targets return no output.
Remediation Checklist
If you manage your own cPanel installation:
Run upcp to update to the patched build and verify the version with /usr/local/cpanel/cpanel -V. Restrict management port access (2082, 2083, 2086, 2087, 2095, 2096) to known administrative IP ranges via firewall rules — these ports should never be directly internet-accessible in a production environment. Inspect /var/cpanel/sessions/raw/ for the indicators described above. Audit WHM for unexpected administrative accounts, SSH keys in root’s authorized_keys, and unexpected cron jobs.
If your website is hosted on shared hosting:
Contact your hosting provider directly and ask for confirmation of the patch status of the server your account lives on. Ask whether they detected any exploitation activity during the exposure window (April 28–29, 2026). If your provider cannot confirm patch status or is evasive about exploitation, treat the server as potentially compromised.
If you discover evidence of compromise:
Do not attempt to remediate a root-compromised server in-place. Rebuild from a clean, patched image. Rotate all administrative credentials, replace all SSH keys, and rotate any API keys or database credentials that were stored on the server. Assume all data on the server has been exposed, and notify affected customers accordingly. Conduct a broader investigation for lateral movement — compromised SSH keys, exfiltrated database credentials, and OAuth tokens may have already been used against connected systems.
Summary and Action Checklist
CVE-2026-41940 is a good example of how a small, localized coding mistake — one function that doesn’t call a sanitizer that other functions do call — can produce consequences that extend far beyond what any single line of code should be capable of. The CRLF injection itself is not a new class of vulnerability. The technique of injecting key=value records into a file that gets re-parsed later is well understood. What makes this instance consequential is not its novelty but its location: directly in the authentication layer of software that controls 94% of the shared hosting market.
The patch is a single filter_sessiondata() call added to saveSession(). The exposure it closes affects millions of servers globally. That asymmetry — one missing function call, industry-wide impact — is the story that CVE-2026-41940 tells. And it is a story worth taking seriously before the next chapter is written.
| Priority | Action |
|---|---|
| 🔴 Immediate | Patch cPanel & WHM to the patched version for your branch |
| 🔴 Immediate | Verify auto-updates are enabled (/scripts/upcp --force to patch now) |
| 🔴 Immediate | Inspect /var/cpanel/sessions/raw/ for exploitation artifacts |
| 🟠 If unpatched | Restrict WHM port (2087) to trusted IPs via firewall immediately |
| 🟠 If unpatched | Block public access to ports 2082, 2083, 2086, 2087, 2095, 2096 |
| 🟡 Post-patch | Rotate all cPanel and WHM passwords and API tokens |
| 🟡 Post-patch | Review root access logs for unauthorized sessions since Feb 23, 2026 |
| 🟡 Post-patch | Scan for .sorry ransomware indicators if server was unpatched |
| 🟡 Ongoing | Place WHM behind a jump server or VPN — never expose directly |
| 🟡 Ongoing | Enable cPanel access logging and alert on root-level WHM logins |
Frequently Asked Questions
Q: What is CVE-2026-41940? A: A CVSS 9.8 pre-authentication remote authentication bypass in cPanel & WHM and WP Squared. A CRLF injection flaw in the session handler lets an unauthenticated attacker inject arbitrary fields — including user=root and hasroot=1 — into a pre-auth session file, granting full root access without a password.
Q: How many servers are affected? A: Approximately 1.5 million cPanel instances are directly internet-exposed. cPanel manages roughly 70 million domains, so a single compromised server can expose hundreds or thousands of downstream websites.
Q: Was it exploited before the patch? A: Yes. Exploitation began around February 23, 2026 — two months before the April 28 patch. The Shadowserver Foundation confirmed at least 44,000 servers already compromised.
Q: Does 2FA protect against this? A: No. The exploit injects tfa_verified=1 directly into the session file, bypassing both the password and 2FA gates without ever executing authentication code.
Q: How do I check if my server was compromised? A: Inspect /var/cpanel/sessions/raw/ for session files containing hasroot=1, tfa_verified=1, or successful_internal_auth_with_timestamp without a corresponding legitimate login. Run cPanel’s published detection script and review WHM access logs from February 23 onward.