The last 72 hours have been the noisiest patch window I have lived through in a while. cPanel and WHM were quietly being rooted as a zero-day for two months before the public advisory dropped on April 28. The next day, a nine-year-old Linux kernel logic bug went public with a 732-byte Python exploit that gives any local user root on essentially every major distribution. Hours later, the same TeamPCP crew that hit LiteLLM in March came back with a fresh credential-stealer worm, this time poisoning the official intercom-client npm package and the popular lightning PyPI release.
Three independent incidents, all critical, all dropping inside the same 72 hour window. If you manage hosting, Linux fleets, or any developer pipeline that touches npm or PyPI, you have work to do this week. This post is the consolidated picture: what each incident is, what to patch, and what to hunt for.
What broke and when
| Date (UTC) | Event |
|---|---|
| Feb 23 | Earliest in-the-wild exploitation of CVE-2026-41940 observed by KnownHost. The cPanel auth bypass was being used as a 0-day for two months before disclosure |
| Apr 28 | cPanel public advisory and emergency patches release. Major hosts (Namecheap, hosting.com, KnownHost, HostPapa, InMotion) block ports 2083, 2087, 2095, and 2096 at the edge |
| Apr 29 | ”Copy Fail” / CVE-2026-31431 publicly disclosed by Theori and Xint via oss-security. PoC and detailed writeup go live the same day |
| Apr 29 | [email protected] published to npm by TeamPCP with a Bun-based credential stealer. SAP-CAP packages compromised in the same window |
| Apr 30 | lightning 2.6.2 and 2.6.3 published to PyPI from a hijacked maintainer account. Socket flags both versions roughly 18 minutes after publish |
| Apr 30 | PyPI quarantines lightning. npm pulls [email protected]. Distributions begin shipping patched Linux kernels (USN, RHSA, SUSE-SU, DSA) |
cPanel CVE-2026-41940: silently exploited for two months
This one is the worst story of the three because the exploitation predates the advisory by approximately two months. Researcher Sina Kheirkhah at watchTowr Labs reported a critical authentication bypass to WebPros around mid-April. WebPros initially dismissed the report. Then KnownHost publicly confirmed they had been seeing exploitation in their telemetry “at least for the last 30 days, if not longer”, with the earliest verified compromise dating to February 23, 2026.
The root cause is a CRLF injection (literal \r\n bytes) in cPanel’s session-saving logic, specifically inside Cpanel::Session::Modify::saveSession. An unauthenticated attacker:
- Triggers a failed login to create a pre-auth session file on disk.
- Sends a follow-up request with an
Authorization: Basicheader containing raw\r\n. - The session module writes the unsanitised header into the on-disk session file, line by line.
- The injected lines forge keys like
user=root,hasroot=1,tfa_verified=1, andsuccessful_internal_auth_with_timestamp. - A separate cookie-segment trick bypasses the encryption check on the
whostmgrsessioncookie.
The result is pre-auth root on WHM. On a shared hosting box that means every tenant’s data, mail, databases, and customer sites are also fully exposed.
Affected: every supported cPanel and WHM build older than the patched releases below, plus WP Squared v136.1.7. Shodan counts roughly 1.5 million internet-exposed cPanel instances, managing somewhere around 70 million domains.
Fixed builds (from the cPanel advisory):
- 110.0.x:
11.110.0.97 - 118.0.x:
11.118.0.63 - 126.0.x:
11.126.0.54 - 132.0.x:
11.132.0.29 - 134.0.x:
11.134.0.20 - 136.0.x:
11.136.0.5
Linux “Copy Fail” CVE-2026-31431: nine years dormant, 732 bytes to root
While cPanel admins were finishing emergency patches, Theori (Taeyang Lee) and the Xint Code Research Team coordinated public disclosure of a Linux kernel logic bug they nicknamed Copy Fail. The bug was introduced in 2017 by an in-place AEAD optimisation (commit 72548b093ee3) and sat there silently for nine years before being reported in March 2026.
What makes Copy Fail “brutal” is the exploit profile, not the CVSS score (7.8 high, but local). The published proof of concept is a 732 byte Python script using only the standard library on Python 3.10 or later. There is no race condition, no kernel offset leak, no ROP, no payload to compile. The same script reaches root on every distribution shipped since 2017, including Ubuntu 24.04 LTS, Amazon Linux 2023, RHEL 10.1, SUSE 16, Rocky Linux 9.7, and Debian stable.
The attack chains the kernel’s algif_aead socket interface (the AF_ALG family for userspace crypto) with the authencesn AEAD template. The authencesn template reserves four bytes past its output buffer as a scratch pad and never restores them. With a carefully crafted splice() call, an unprivileged user gets a deterministic 4-byte write into any page-cache-backed page: pick /usr/bin/su, patch its setuid binary in cache, run it, get a root shell.
The container escape twist. The page cache is shared across every namespace on a node. If a compromised container can run the exploit, the corrupted setuid binary is visible to the host and to peer containers in shared image layers. That makes Copy Fail a viable Kubernetes container escape primitive on multi-tenant clusters. OVHcloud and Sysdig both flagged this angle for managed Kubernetes, and a Kubernetes-specific PoC is already on GitHub.
Affected kernels: 4.14 through 7.0-rc, all 6.18.x below 6.18.22, all 6.19.x below 6.19.12.
Patched builds:
- Mainline
7.0(commita664bf3d) - Stable
6.19.12(commitce42ee42) - Stable
6.18.22(commitfafe0fa2) - Distribution USN, RHSA, SUSE-SU, and DSA updates rolling since April 29
- CloudLinux KernelCare livepatch available with no reboot
If you cannot reboot immediately, blacklist the algif_aead module:
echo "install algif_aead /bin/false" > /etc/modprobe.d/disable-algif-aead.conf
rmmod algif_aead 2>/dev/null
On RHEL or Rocky 9.7 the module is built in, so the kernel cmdline mitigation is the only pre-patch option:
sudo grubby --update-kernel=ALL --args="initcall_blacklist=algif_aead_init"
# reboot required
For containers, push a seccomp profile that blocks socket(AF_ALG, ...) until host nodes are running patched kernels.
Mini Shai-Hulud strikes again: intercom-client and lightning
The third story is a sequel. The TeamPCP threat actor we wrote about for the LiteLLM compromise in March never went away. They have been chaining together compromises ever since (Telnyx, Xinference, Bitwarden CLI, Aqua Trivy), and on April 29 and 30 they shipped what Aikido, Wiz, and Socket are now calling the “Mini Shai-Hulud” worm campaign. Two packages stand out for the impact on MSP-managed environments:
[email protected]on npm, the official Intercom Node SDK, with roughly 337,000 weekly downloads.lightning 2.6.2andlightning 2.6.3on PyPI, the PyTorch Lightning training framework, which Socket describes as having hundreds of thousands of downloads per day.
The same window also produced poisoned SAP-CAP packages (@cap-js/[email protected], @cap-js/[email protected], @cap-js/[email protected], [email protected]). Different ecosystems, identical payload pattern.
The shared payload
Every malicious package in this campaign ships the same multi-stage credential stealer.
graph TD INSTALL["Install or import malicious package<br/><small>npm install intercom-client OR import lightning</small>"] --> DROPPER["Stage 1: Dropper<br/><small>setup.mjs or _runtime/start.py runs from preinstall hook or import-time code</small>"] DROPPER --> BUN["Stage 2: Bun JS runtime fetched<br/><small>Platform-specific Bun binary downloaded from GitHub Releases</small>"] BUN --> EXEC["Stage 3: Obfuscated stealer executes<br/><small>execution.js or router_runtime.js, around 11 MB obfuscated</small>"] EXEC --> HARVEST["Credential harvest<br/><small>SSH keys, GitHub PATs, npm tokens, AWS, Azure, GCP, Kubernetes, IMDS, env vars, crypto wallets</small>"] HARVEST --> CRYPTO["AES-256-GCM encryption<br/><small>Session key wrapped with embedded RSA-4096 public key</small>"] CRYPTO --> EXFIL["Exfiltration via GitHub<br/><small>New public repo on the victim account, Dune-themed name, Mini Shai-Hulud signature description</small>"] HARVEST --> WORM["Worm propagation<br/><small>Inject preinstall hook into every locally cached npm package the stolen token can publish, bump patch version, republish</small>"] style INSTALL fill:#92400e,stroke:#78350f,color:#fef3c7 style DROPPER fill:#991b1b,stroke:#7f1d1d,color:#fef2f2 style BUN fill:#991b1b,stroke:#7f1d1d,color:#fef2f2 style EXEC fill:#991b1b,stroke:#7f1d1d,color:#fef2f2 style HARVEST fill:#991b1b,stroke:#7f1d1d,color:#fef2f2 style CRYPTO fill:#991b1b,stroke:#7f1d1d,color:#fef2f2 style EXFIL fill:#5b21b6,stroke:#4c1d95,color:#ede9fe style WORM fill:#5b21b6,stroke:#4c1d95,color:#ede9fe
A few details worth calling out:
- Bun is the canary. The dropper fetches the Bun JavaScript runtime, drops the binary on disk, and uses it to execute the obfuscated stealer. If
bunshows up in process telemetry on a host that does not normally run it, especially in the parent chain ofnpm installorpip install, that is the campaign. - GitHub itself is the C2. There is no traditional command-and-control domain. Stolen credentials are committed to a brand new public repository created on the victim’s own GitHub account. Names follow a Dune theme. The repo description is the literal string
A Mini Shai-Hulud has Appeared. A search for that exact string across an org is enough to catch active compromises. - The worm. If the stealer recovers npm publish credentials, it walks the developer’s locally cached packages, injects a
preinstallhook into each, bumps patch versions, and republishes. One developer’s stolen token can mushroom into a dozen secondary package compromises. Researchers reported more than 1,100 victim repositories carrying the signature description by April 30.
What we know about each package
[email protected]. Published April 29. Last known good version is 7.0.3. Pin and override accordingly. Intercom posted an incident notice on intercomstatus.com advising customers to rotate any credentials reachable from systems that installed the malicious version. To be unambiguous: Intercom the SaaS was not compromised. The npm SDK was. The right risk framing for clients is “our build host pulled a poisoned dependency”, not “Intercom got breached”.
lightning 2.6.2 and 2.6.3. Published April 30 from the compromised pl-ghost GitHub maintainer account. Last known good version is 2.6.1 (January 30, 2026). Socket caught both versions within 18 minutes. PyPI quarantined the project later the same day. The malicious code was injected into __init__.py, so the stealer fires on import lightning, not just on install. Any data science, MLOps, or AI workload that imported the package between publish and quarantine should be treated as a credential breach.
Socket’s writeup published the file hashes for router_runtime.js, the obfuscated payload:
- SHA256:
5f5852b5f604369945118937b058e49064612ac69826e0adadca39a357dfb5b1 - SHA1:
f1b3e7b3eec3294c4d6b5f87854a52471f03997f - MD5:
40d0f21b64ec8fb3a7a1959897252e09
Indicators of compromise
If you are feeding the values below into a SIEM, strip the defang brackets ([.]) and restore regular dots.
cPanel CVE-2026-41940
No public attacker IPs, domains, or file hashes were released as of April 30. Detection is filesystem and string based.
| Type | Indicator |
|---|---|
| Inspection paths | /var/cpanel/sessions/raw/, /var/cpanel/sessions/cache/, /var/cpanel/sessions/preauth/ |
| Strong exploitation signal | token_denied co-occurring with cp_security_token in any session file under those paths |
| Forged session keys | user=root, hasroot=1, tfa_verified=1, successful_internal_auth_with_timestamp appearing inside pre-auth sessions |
| Network signature | Inbound requests to 2083, 2087, 2095, or 2096 with raw \r\n in Authorization: Basic headers |
| Detection tooling | cPanel’s ioc_checksessions_files.sh, watchTowr’s PoC and detector, Searchlight Cyber’s high-fidelity check |
Linux Copy Fail CVE-2026-31431
There is no malware here, just an exploit primitive, so detection is patch-based first and behavioural second.
| Type | Indicator |
|---|---|
| Affected versions | Kernel 4.14 through 7.0-rc, all 6.18.x below 6.18.22, all 6.19.x below 6.19.12 |
| Suspicious behaviour | Non-root processes opening AF_ALG sockets and using splice() against the kernel crypto interface |
| Public PoC repos | theori-io/copy-fail-CVE-2026-31431, tgies/copy-fail-c, Percivalll/Copy-Fail-CVE-2026-31431-Kubernetes-PoC, rootsecdev/cve_2026_31431 |
| Mitigation knob | Module blacklist for algif_aead, or initcall_blacklist=algif_aead_init on built-in module distros |
Mini Shai-Hulud (intercom-client, lightning, SAP-CAP)
| Type | Indicator |
|---|---|
| Malicious package versions | [email protected] (npm), lightning==2.6.2 and lightning==2.6.3 (PyPI), @cap-js/[email protected], @cap-js/[email protected], @cap-js/[email protected], [email protected] |
| Planted file paths | setup.mjs, execution.js, _runtime/start.py, _runtime/router_runtime.js, .claude/router_runtime.js, .claude/setup.mjs, .vscode/setup.mjs, .github/workflows/format-check.yml |
| Process signal | bun binary spawned from an npm install, pip install, or Python interpreter context |
| Cloud metadata abuse | Outbound requests to 169.254.169[.]254 (AWS IMDS), 169.254.170[.]2 (AWS ECS), Azure and GCP metadata endpoints from Python or Bun processes |
| GitHub exfil signature | New public repo on a developer’s GitHub account, random Dune-themed name, repo description literally A Mini Shai-Hulud has Appeared, files at results/results-<timestamp>-<n>.json |
| Commit signature | Spoofed author [email protected], commit messages containing OhNoWhatsGoingOnWithGitHub:<base64> |
| Compromised maintainer | github[.]com/pl-ghost (PyPI lightning source) |
| router_runtime.js hashes | SHA256 5f5852b5f604369945118937b058e49064612ac69826e0adadca39a357dfb5b1, SHA1 f1b3e7b3eec3294c4d6b5f87854a52471f03997f, MD5 40d0f21b64ec8fb3a7a1959897252e09 |
What to hunt for
Patch in priority order
The three incidents do not share infrastructure but they do share urgency. If you are choosing what to roll first across a managed estate:
- Multi-tenant Kubernetes nodes. Copy Fail’s container escape primitive is the largest blast radius of the week. EKS, GKE, AKS, MKS, and any self-hosted clusters with shared image layers should be on a same-day patch SLA.
- Internet-exposed cPanel and WHM hosts. Patch to the build for your branch, restart
cpsrvd, and assume-breach for any pre-April-28 box. While you patch, block 2083, 2087, 2095, and 2096 at the perimeter. - Shared dev hosts, jump boxes, CI runners, and sFTP gateways running vulnerable kernels. Anywhere multiple human users or untrusted code can run, Copy Fail is local privilege escalation to root with no friction.
- Audit npm and PyPI lockfiles in every pipeline that ran since April 29. Any host that resolved
[email protected]orlightning2.6.2 or 2.6.3 is a credential-breach incident, not a clean-the-package incident.
Hunt across the fleet
For cPanel hosts:
# Run cPanel's official IoC script
/usr/local/cpanel/scripts/ioc_checksessions_files.sh
# Look for forged keys in session files
grep -RIE "hasroot=1|tfa_verified=1|user=root" /var/cpanel/sessions/ 2>/dev/null
# Check for token_denied + cp_security_token co-occurrence
grep -RIl "token_denied" /var/cpanel/sessions/ 2>/dev/null \
| xargs -r grep -l "cp_security_token" 2>/dev/nullFor Linux fleets, confirm kernel state and module status:
# Current kernel
uname -r
# Is algif_aead loaded as a module, or built in?
lsmod | grep algif_aead
grep -i algif_aead /boot/config-$(uname -r)For developer workstations and CI runners that may have pulled the compromised packages:
# Search for planted dropper files
find / -type f \
\( -name "router_runtime.js" -o -name "setup.mjs" -o -name "execution.js" \) \
2>/dev/null
# Search every managed GitHub org for the exfil-repo signature
gh search repos "A Mini Shai-Hulud has Appeared" --owner <your-org>
# Look for bun in process history (sysmon, auditd, or your EDR)
# Parent of interest: npm, node, pnpm, yarn, python, pip, uv
# Child of interest: bunRotate and harden
- For Mini Shai-Hulud exposure: rotate Intercom Access Tokens for any workspace whose backend ran the compromised SDK, plus GitHub PATs, npm tokens, AWS, Azure, and GCP keys, and any SSH keys reachable from affected build hosts. Reimage rather than clean. The Bun binary persists on disk and the worm may have re-poisoned local package caches.
- For cPanel exposure: rotate root, every WHM user password, and every API token after patching. Audit cron,
authorized_keys, custom hooks, and/usr/local/cpanel/for unfamiliar Perl modules or webshells. For shared-hosting tenants, treat their data as exposed and notify accordingly. - For Copy Fail exposure: the bug itself does not phone home. The risk is what an attacker who already has a foothold can do with it. If you find evidence of
algif_aeadabuse in audit logs, treat the host as compromised and rotate any credentials accessible from it. - Long-term hygiene: pin GitHub Actions to commit SHAs (the lesson the LiteLLM and Trivy chain taught us in March), enforce
npm ci --ignore-scriptsandpip install --require-hashesin production builds, and put a Socket or Snyk gate on dependency updates.
Why this matters for MSPs
- Patch fatigue is itself a security risk. Three independent severe issues in 72 hours stretch even a well-resourced team. Prioritise by blast radius (multi-tenant first), and accept that you will be applying mitigations and patches in parallel rather than in sequence.
- “Patched” does not mean “clean”. cPanel’s CRLF bug was exploited as a 0-day for two months before the patch. Anyone who patched on April 28 without running an IoC sweep is still potentially holding a rooted box. The same logic applies to any future story like this: assume compromise spans the time between bug introduction and your patch.
- Supply-chain compromise is the new normal in npm and PyPI. TeamPCP has now run high-profile attacks on LiteLLM (March), Telnyx (March), Bitwarden CLI (April), and now Intercom and PyTorch Lightning (April). The cadence is accelerating. Lockfile hygiene, install-script discipline, and continuous credential rotation are no longer optional.
- Container security needs more than image scanning. Copy Fail demonstrates that a clean container image running on an unpatched host kernel is still a container escape. Node-level kernel patching matters as much as image hygiene, and seccomp profiles that deny exotic syscalls (like
AF_ALGsocket creation) are cheap insurance.
Closing thought
Three independent severe issues in one news cycle would have been a fluke five years ago. In 2026 it is starting to look like a pattern, and I expect more of it before the year is out. The teams that come out ahead are the ones with disciplined inventories, automated rotation, and a habit of treating “we patched it” as the start of incident response, not the end.
Related reading
LiteLLM Supply Chain Attack: What MSPs Need to Know
Analysis of the TeamPCP supply chain attack on LiteLLM via compromised Trivy GitHub Actions, covering the 3-layer payload, IOCs, and defensive actions for MSPs.
Axios npm Supply Chain Attack: What You Need to Know
Analysis of the axios npm supply chain attack that dropped a cross-platform RAT via maintainer account compromise, with IOCs and defensive steps.
Nightmare-Eclipse: Public PoC Meets Real Intrusion
Huntress caught the Nightmare-Eclipse toolkit (BlueHammer, RedSun, UnDefend, BeigeBurrow) in a live intrusion. Here are the IOCs and what we learned.