A new wave of malicious npm packages is targeting developers who work with cloud and serverless infrastructure.
The threat, known as the Shai-Hulud payload carrying the Hades malware family, has now expanded its reach to the Leo/RStreams ecosystem, a set of libraries widely used for AWS-native event streaming and data pipelines.
Security teams are raising the alarm as the attack quietly steals sensitive developer credentials the moment a package is installed.
What makes this campaign especially dangerous is how deep it digs. When a developer installs one of the affected packages, the payload begins collecting credentials stored across files, environment variables, shell history, GitHub CLI tokens, cloud access keys, and CI/CD pipeline secrets.
It works silently in the background and sends everything it finds to attacker-controlled GitHub repositories.
The scale of exposure is hard to ignore. The affected packages recorded roughly 45,000 downloads in a single month, meaning thousands of developers may have already been affected without knowing it.
Analysts at JFrog Security Research identified the new wave and published their findings in a report shared with Cyber Security News (CSN).
Researcher Yair Benamou noted this is not a completely new threat but another turn of the same campaign, with the same credential theft machinery but fresh targets and updated markers.
The Leo/RStreams libraries sit at the center of cloud-native development workflows. They wrap AWS services like Kinesis, S3, Lambda, and DynamoDB, meaning any developer installing these tools is likely working in an environment rich with cloud credentials and deployment tokens.
This positioning means that a single compromised install can expose far more than just one developer’s workstation. This latest wave confirms that the Shai-Hulud operation is still active and still growing.
Rather than building new malware from scratch, the attackers are recycling a proven payload and pointing it at new, trusted package families. Defenders who rely only on old campaign names or outdated signatures are still very likely to miss it entirely.
Shai-Hulud Payload Steals GitHub, npm, Cloud, CI/CD, and SSH Credentials
The malicious packages use a clever delivery trick that helps them slip past basic security scanners. Instead of placing harmful code inside the standard npm install scripts that most tools check, the attacker hides execution inside a file called binding.gyp.

When npm finds a package with this file and no explicit install script, it automatically runs node-gyp, which processes shell commands embedded inside that file. This gives the attacker a way to run code during installation while staying off the radar.
Once running, the payload collects credentials from a wide range of sources on the developer’s machine. It targets GitHub tokens, npm and PyPI publishing credentials, AWS access keys, JFrog and Artifactory tokens, and SSH keys.
Any stolen data is packaged into encrypted files and exfiltrated by creating repositories under a stolen GitHub token and committing the results there, a technique known as a GitHub dead drop.
Persistence and Lateral Movement Tactics
The payload does not stop at stealing credentials during installation. It plants several persistence hooks to keep running long after the initial install.
It sets itself up as a systemd service on Linux or a LaunchAgent on macOS, while also hooking into AI development tools by modifying configuration files for tools like Cursor, Copilot, and Gemini.
SSH keys found on the compromised machine are used to attempt lateral movement into other systems the developer has access to. The payload also injects itself into GitHub Actions workflows to dump pipeline secrets.
A single infected install on one machine could ripple outward into team repositories, cloud accounts, and production pipelines.
JFrog recommends isolating affected machines and CI runners before rotating any credentials. All persistence artifacts, including the monitor service, AI-tool hooks, and suspicious workflow files, must be removed first.
After cleanup, all GitHub, npm, cloud, SSH, Docker, and package registry credentials should be rotated. GitHub and npm accounts should also be audited for unexpected repositories, package releases, or suspicious workflow changes.
Indicators of Compromise (IoCs):-
Malicious npm Package Versions
| Type | Indicator | Description |
|---|---|---|
| npm Package | leo-auth v4.0.6 | Hijacked Leo/RStreams package (XRAY-1009715) |
| npm Package | leo-aws v2.0.4 | Hijacked Leo/RStreams package (XRAY-1009716) |
| npm Package | leo-cache v1.0.2 | Hijacked Leo/RStreams package (XRAY-1009726) |
| npm Package | leo-cdk-lib v0.0.2 | Hijacked Leo/RStreams package (XRAY-1009721) |
| npm Package | leo-cli v3.0.3 | Hijacked Leo/RStreams package (XRAY-1009724) |
| npm Package | leo-config v1.1.1 | Hijacked Leo/RStreams package (XRAY-1009720) |
| npm Package | leo-connector-elasticsearch v2.0.6 | Hijacked Leo/RStreams package (XRAY-1009713) |
| npm Package | leo-connector-mongo v3.0.8 | Hijacked Leo/RStreams package (XRAY-1009714) |
| npm Package | leo-connector-mysql v3.0.3 | Hijacked Leo/RStreams package (XRAY-1009729) |
| npm Package | leo-connector-oracle v2.0.1 | Hijacked Leo/RStreams package (XRAY-1009718) |
| npm Package | leo-connector-redshift v3.0.6 | Hijacked Leo/RStreams package (XRAY-1009725) |
| npm Package | leo-cron v2.0.2 | Hijacked Leo/RStreams package (XRAY-1009723) |
| npm Package | leo-logger v1.0.8 | Hijacked Leo/RStreams package (XRAY-1009727) |
| npm Package | leo-sdk v6.0.19 | Hijacked Leo/RStreams package (XRAY-1009717) |
| npm Package | leo-streams v2.0.1 | Hijacked Leo/RStreams package (XRAY-1009728) |
| npm Package | rstreams-metrics v2.0.2 | Hijacked Leo/RStreams package (XRAY-1009731) |
| npm Package | rstreams-shard-util v1.0.1 | Hijacked Leo/RStreams package (XRAY-1009732) |
| npm Package | serverless-convention v2.0.4 | Hijacked Leo/RStreams package (XRAY-1009719) |
| npm Package | serverless-leo v3.0.14 | Hijacked Leo/RStreams package (XRAY-1009730) |
| npm Package | solo-nav v1.0.1 | Hijacked Leo/RStreams package (XRAY-1009722) |
Network and Service Indicators
| Type | Indicator | Description |
|---|---|---|
| URL | hxxps[:]//api[.]anthropic[.]com/v1/api | Anthropic API camouflage used for payload communication |
| URL | hxxps[:]//api[.]github[.]com | GitHub API used for dead-drop exfiltration |
| URL | hxxps[:]//api[.]github[.]com/search/commits?q=firedalazher | GitHub commit search endpoint used in campaign tracking |
| URL | hxxps[:]//github[.]com/oven-sh/bun/releases/download/bun-v1.3.13/ | Bun runtime download used by payload |
| URL | hxxps[:]//github[.]com/oven-sh/bun/releases/download/bun-v1.3.14/ | Bun runtime download used by payload |
Host and Persistence Indicators
| Type | Indicator | Description |
|---|---|---|
| File Path | /tmp/p*.js | Temporary payload script |
| File Path | /tmp/b-/bun | Bun runtime binary dropped in temp |
| File Path | /tmp/b-/b.zip | Bun runtime archive in temp |
| File Path | ~/.config/gh-token-monitor/ | Persistence config directory |
| File Path | ~/.config/gh-token-monitor/token | Stored token file for monitor service |
| File Path | ~/.config/gh-token-monitor/handler | Handler script for monitor service |
| File Path | ~/.local/bin/gh-token-monitor.sh | Monitor shell script |
| File Path | ~/.config/systemd/user/gh-token-monitor.service | Linux systemd persistence service |
| File Path | ~/Library/LaunchAgents/com.user.gh-token-monitor.plist | macOS LaunchAgent persistence |
| File Path | ~/.local/share/updater/update.py | Python updater persistence script |
| File Path | ~/.local/share/updater/update-monitor.service | Updater systemd service |
| File Path | ~/.config/index.js | Payload config index |
| File Name | ai_setup.sh | AI tool setup hook script |
| File Name | ai_init.js | AI tool initialization hook script |
| File Path | results/results-.json | Exfiltrated credential result files |
Repository and Workflow Indicators
| Type | Indicator | Description |
|---|---|---|
| Campaign Marker | Alright Lets See If This Works | Current wave public repository description marker |
| Token String | RevokeAndItGoesKaboom | Current token relay marker string |
| Token String | TheBeautifulSandsOfTime | Alternate campaign marker string |
| Token String | thebeautifulmarchofftime | Alternate campaign marker string |
| Env Variable | SEED_PAT | GitHub PAT used in gated seeder path |
| Env Variable | VARIABLE_STORE | Variable storage environment reference |
| File Name | format-results.txt | Credential formatting output file |
| AI Config | .cursor/rules/setup.mdc | Cursor AI rules hook |
| AI Config | .gemini/settings.json | Gemini AI settings hook |
| AI Config | .cursorrules | Cursor rules persistence file |
| AI Config | .windsurfrules | Windsurf rules persistence file |
| AI Config | .github/copilot-instructions.md | Copilot instructions persistence file |
| AI Config | mcp.json | MCP configuration hook |
| AI Config | .aider.conf.yml | Aider AI configuration hook |
Note: IP addresses and domains are intentionally defanged (e.g., [.]) to prevent accidental resolution or hyperlinking. Re-fang only within controlled threat intelligence platforms such as MISP, VirusTotal, or your SIEM.