← Back to all articles

3 exploits in 72 hours. I fear this is just the beginning.

Three critical incidents in under 72 hours: cPanel auth bypass exploited as 0-day, Linux Copy Fail kernel root, and Mini Shai-Hulud's npm and PyPI return.

Updated 15 min read
Three critical security incidents within 72 hours: cPanel CVE-2026-41940 authentication bypass, Linux Copy Fail kernel zero-day, and the Mini Shai-Hulud npm and PyPI supply chain campaign.

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 23Earliest 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 28cPanel 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 30lightning 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 30PyPI 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:

  1. Triggers a failed login to create a pre-auth session file on disk.
  2. Sends a follow-up request with an Authorization: Basic header containing raw \r\n.
  3. The session module writes the unsanitised header into the on-disk session file, line by line.
  4. The injected lines forge keys like user=root, hasroot=1, tfa_verified=1, and successful_internal_auth_with_timestamp.
  5. A separate cookie-segment trick bypasses the encryption check on the whostmgrsession cookie.

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 (commit a664bf3d)
  • Stable 6.19.12 (commit ce42ee42)
  • Stable 6.18.22 (commit fafe0fa2)
  • 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.2 and lightning 2.6.3 on 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 bun shows up in process telemetry on a host that does not normally run it, especially in the parent chain of npm install or pip 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 preinstall hook 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.

TypeIndicator
Inspection paths/var/cpanel/sessions/raw/, /var/cpanel/sessions/cache/, /var/cpanel/sessions/preauth/
Strong exploitation signaltoken_denied co-occurring with cp_security_token in any session file under those paths
Forged session keysuser=root, hasroot=1, tfa_verified=1, successful_internal_auth_with_timestamp appearing inside pre-auth sessions
Network signatureInbound requests to 2083, 2087, 2095, or 2096 with raw \r\n in Authorization: Basic headers
Detection toolingcPanel’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.

TypeIndicator
Affected versionsKernel 4.14 through 7.0-rc, all 6.18.x below 6.18.22, all 6.19.x below 6.19.12
Suspicious behaviourNon-root processes opening AF_ALG sockets and using splice() against the kernel crypto interface
Public PoC repostheori-io/copy-fail-CVE-2026-31431, tgies/copy-fail-c, Percivalll/Copy-Fail-CVE-2026-31431-Kubernetes-PoC, rootsecdev/cve_2026_31431
Mitigation knobModule blacklist for algif_aead, or initcall_blacklist=algif_aead_init on built-in module distros

Mini Shai-Hulud (intercom-client, lightning, SAP-CAP)

TypeIndicator
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 pathssetup.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 signalbun binary spawned from an npm install, pip install, or Python interpreter context
Cloud metadata abuseOutbound 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 signatureNew 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 signatureSpoofed author [email protected], commit messages containing OhNoWhatsGoingOnWithGitHub:<base64>
Compromised maintainergithub[.]com/pl-ghost (PyPI lightning source)
router_runtime.js hashesSHA256 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:

  1. 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.
  2. 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.
  3. 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.
  4. Audit npm and PyPI lockfiles in every pipeline that ran since April 29. Any host that resolved [email protected] or lightning 2.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/null

For 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: bun

Rotate 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_aead abuse 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-scripts and pip install --require-hashes in 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_ALG socket 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.

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.

Search articles
esc to close