The Hook That Runs Before You Type
We need to talk about how Python starts up. Or more specifically, how threat actors have figured out that you do not even need to run a compromised package's import statements to get completely owned. If you are tuning detection rules for a standard Security Operations Center, this is the kind of engineering problem that breaks your logic. Most automated detectors monitor import statements. They watch for patterns like import urllib or import os inside suspicious files. The Hades campaign, however, throws that strategy straight out the window. It targets Python's site customization features, specifically abusing *-setup.pth files.
A .pth file is supposed to be a basic path config file. It tells the Python interpreter where to look for modules. But Python's site module has a high-risk capability: if a line inside a .pth file starts with import, the interpreter executes it as raw code during initialization. When a developer runs a standard pip install on a compromised package, the package manager writes a malicious .pth file to the site-packages directory. The next time any Python script runs on that machine, things go south. Python boots up, reads the .pth file, and executes the payload. No explicit import malicious_package is required. It runs before a single line of the user's script executes. In the logging telemetry, you just see python3 spawning. You do not see a manual entry point. According to reports published by The Hacker News, this stealthy initialization is exactly how the loader achieves automatic code execution on user systems. If you want to detect this, you have to query your Endpoint Detection and Response logs for the creation of .pth files containing importing keywords.
The Bun Runtime Bypass
Most Python supply chain campaigns drop their payloads directly into the Python code. It is simpler. But it is also highly visible to static code scanners. The writers of the Mini Shai-Hulud malware family decided to do something far more annoying. They wrote a tiny Python loader that downloads and executes the Bun JavaScript runtime. Specifically, version 1.3.14.
They chose Bun for a reason. It is fast, self-contained, and runs as an architecture-specific binary. During the execution sequence, the initial script checks for a flag file at /tmp/.bun_ran. If it is not there, it fetches the Bun binary directly from GitHub. It extracts the binary to a temporary folder and calls a companion script named _index.js. From a network security monitoring standpoint, this is a real problem. Bun acts as a proxy bypass. It does not rely on Python's network libraries. So if you are looking at flow data expecting Python to call out to weird IPs, you will find nothing. Instead, you see a random binary in /tmp/ making raw, encrypted websocket calls. Security scanners tuned for PyPI packages only analyze Python files. They do not watch for the startup of a third-party Javascript runtime running executable modules on the side. Evasion by design.
Two Clusters of Toxicity
The Hades campaign did not just throw darts at the map. They targeted specific developer profiles in two distinct clusters. In total, they poisoned 19 packages across 37 malicious wheel files on PyPI.
The first cluster focuses on bioinformatics and graph machine learning libraries. We are talking about packages like ensmallen, embiggen, and gpsea. These packages are popular among academic and enterprise researchers. These developers run intense workloads with elevated privileges. The entry point here was of course different: they used obfuscated __init__.py entry points. The second cluster targets general utilities like bramin, cmd2func, and coolbox. This group relied on the *-setup.pth hook we talked about. By splitting their targets, they achieved two goals. They compromised research platforms while also digging into general developer workstations. As documented by Dark Reading, this dual targeting mechanism is what makes the campaign's footprint so wide.
Harvesting the Keys to the Kingdom
When _index.js gets running, it bootstraps 16 modular, encrypted payloads. They are gzip-compressed and AES-256-GCM encrypted. They exist to grab credentials across 14 distinct categories. And they target everything.
For cloud access, they search for AWS, GCP, and Azure tokens, alongside Kubernetes secrets. For source control, they extract GitHub personal access tokens, Actions tokens, and GitLab credentials. Publishing credentials for registries like PyPI, npm, and RubyGems are scraped. If a package publisher gets compromised, the attackers can immediately push trojanized updates to their existing packages. This creates a chain reaction. They also sweep local secrets: SSH keys, Docker config files, .env files, and shell histories. Even AI tools aren't safe. Config files for Claude, OpenAI, Gemini, and GitHub Copilot are actively targeted. CI/CD tokens for JFrog and CircleCI vanish too. If it is a secret, Hades wants it. Detection engineers need to monitor registry token directories for unexpected access by non-standard binaries.
AI Prompt Injection in Malware
This is where the Mini Shai-Hulud lineage gets weird. We have seen prompt injection in web applications, but this is the first documented case of a supply chain attack using it to bypass security scanners.
Inside the obfuscated _index.js payload, the attackers embedded a block of plain-text English. The text is specifically formatted to target LLM-based code scanners in development pipelines. It reads like a prompt: instructions telling the reading AI that the script is a benign, standard diagnostic tool. It commands the model to ignore any suspicious functions or external network requests. It is a cheap trick, but it shows where threat actors are heading. They know enterprises are using LLM agents to review code changes. If a developer runs an LLM-based security tool before committing, this prompt injection tries to trick the AI into returning a clean bill of health. We can't rely on smart assistants to check our dependencies. We need hard, rule-based detection and behavioral monitoring.
Command and Control via GitHub
Hades operators do not stand up a classic C2 infrastructure that a simple firewall rule can block. They use GitHub. In fact, they use three separate communication channels built entirely on top of public GitHub repositories.
First, they use a token dead-drop. The malware pushes encrypted commits containing stolen credentials into public repositories. These commits are marked with the keyword DontRevokeOrItGoesBoom. Second, they run a signed JS evaluation loop. The malware queries GitHub for repository commits tagged with the phrase TheBeautifulSnadsOfTime. These commits contain base64-encoded JavaScript payloads signed with RSA-PSS. The local loader verifies the signature before executing the code. Third, a background service called updater.py polls GitHub repos for commits labeled firedalazer. These commits contain fresh URLs to download updated payloads. This entire command and control network is disguised as normal developer traffic. It's HTTPS to github.com. Unless you are looking at the specific API request parameters, it looks completely benign in your traffic logs.
The Worm that Spreads Internally
Mini Shai-Hulud isn't just a credential stealer; it has worm-like self-propagation capabilities. Once it infects a developer workstation, it immediately searches the local directories.
First, it parses ~/.ssh/known_hosts and helper configuration files. It uses these hosts to copy and execute the loader onto remote systems via SSH and SCP. Second, it abuses OIDC trust relationships. If it compromises a CI/CD environment that holds OIDC authentication details, it can bypass traditional credential security. It uses that trust to upload trojanized versions of code back to PyPI. Third, it engages in repository backdooring. It injects itself into local GitHub repositories. When other team members clone those repos or when security tools open the folders, the malware fires up. This is a highly aggressive distribution method. It treats the developer network as a bridge to other targets.
The Threats that Block Response
Incident response teams face an ugly surprise when dealing with this malware. The threat actors built a defensive deterrent directly into the loader's toolkit: a persistence daemon called gh-token-monitor.
If a security team detects the compromise and revokes the stolen GitHub tokens, the monitor daemon notices the sudden 401 Unauthorized errors in its polling logs. Instead of quietly quitting, it triggers a destructive routine that executes rm -rf ~/ on the system. It wipes the developer's home directory. This is a wiper deterrent. It is a hostile, retaliatory defense mechanism. It punishes detection and intervention efforts, presenting an active threat to incident teams attempting to remediate the system. It forces responders to isolate systems completely from the network before rotating any access keys. Alert details from Rescana's advisory outline these containment challenges clearly.
Tracking the Worm's Evolution
We can trace this current campaign back to the original Shai-Hulud campaigns first spotted in September 2025. Then came the Miasma campaigns. Now, we have the Hades campaign of June 2026.
Each iteration shows the developers learning from our detections. The original Shai-Hulud relied on simpler execution hooks, as seen in the previous Shai-Hulud campaign. Then Miasma introduced the Bun runtime packaging. Hades refined this with cross-platform memory scraping and wiper defenses. A previous incident involving npm packages distributed the Miasma malware, showing that the group is not afraid to jump ecosystems. In fact, we have already documented similar behaviors in the Miasma Worm Campaign. If we look at the Red Hat npm Compromise, we see the same signature file structures. The current Hades loader runs memory scraping scripts across operating systems. It parses /proc/{pid}/maps on Linux, calls Mach kernel VM APIs on macOS, and compiles custom C# assemblies on Windows to read from process memory. Their primary target is the GitHub Actions Runner.Worker process. We are dealing with an adversary that understands developer workloads inside out.