Skip to content

Back to the catalog

Miasma & Hades Worms
socket.devwriteup

Miasma & Hades Worms

Socket's Threat Research team documents a new wave of 23 malicious PyPI artifacts (bioinformatics packages like embiggen/ensmallen/gpsea/pyphetools, typosquats like rsquests/tlask/rlask, and an MCP-themed langchain-core-mcp package) tied to the ongoing Mini Shai-Hulud/Miasma/Hades supply chain campaign. Unlike earlier .pth-hook wheels that bundled an obfuscated _index.js JavaScript stealer run via Bun, the bioinformatics cluster hides execution inside trojanized .abi3.so native extensions triggered at import time, while langchain-core-mcp ships only a .pth loader that scans sys.path for an external _index.js payload — a loader/payload split designed to evade detection rules. The payload also opens with a fake prompt-injection comment block meant to derail LLM-based static analysis tools before reaching the actual obfuscated stealer code that harvests GitHub, npm, PyPI, cloud, Kubernetes, SSH, and Docker credentials.

TL;DR New Mini Shai-Hulud/Miasma/Hades PyPI wave hides its Bun/JS stealer inside trojanized native extensions and a sys.path-scanning loader, with a fake prompt-injection header meant to fool LLM-based scanners.
Document

What it is

The newer wave in the Hades branch of the Mini Shai-Hulud / Miasma PyPI campaign: 23 new package-version artifacts, bringing Socket's tracker to 471 artifacts (411 npm across 106 packages, 60 PyPI across 37 packages). The summary already names the clusters and the three-branch delivery split; what it omits is the concrete version numbers, IOCs, and hunting artifacts an engineer needs to check an environment.

Preconditions / Affected

  • langchain-core-mcp@1.4.2 and @1.4.3 (py3-none-any-whl) — the loader-only variant. Installs langchain_core-setup.pth; the wheel does not ship _index.js.
  • Bioinformatics real packages, malicious versions: embiggen, ensmallen, gpsea, phenopacket-store-toolkit, ppkt2synergy, pyphetools.
  • Typosquats/bait: rsquests, tlask, rlask, plus MCP-themed packages.
  • Highest risk in CI/CD build/release runners, where an exposed publishing token lets the actor ship more packages.

How it works

Details the summary doesn't carry:

  • The .pth loader scans every sys.path entry for _index.js — first directly, then one directory below each entry — rather than relying on .pth execution context (which is unreliable in CPython because __file__ may not point at the .pth file). This decouples loader from payload across wheels.
  • Execution is gated by a run-once marker at os.path.join(tempfile.gettempdir(), ".bun_ran"); if absent, it downloads Bun (v1.3.13 referenced), runs the payload, then creates the marker.
  • The .abi3.so branch executes _index.js at import time via dlopen() module init — invisible to source-only Python review.
  • The _index.js anti-analysis header is a JS block comment (skipped at runtime) with fake system instructions to derail LLM-first triage; real code follows as try{eval(...)} over a char-code array with ROT substitution. Socket notes this is not a bypass against YARA, entropy, AST, or behavioral rules.

What to do

Socket's stated guidance: check for affected versions, preserve forensic artifacts before uninstalling, and rotate any exposed tokens. In Python environments hunt for:

  • executable .pth files, unexpected _index.js, Bun download logic, newly added .abi3.so extensions
  • specific native extensions: ensmallen_haswell.abi3.so, ensmallen_core2.abi3.so; any .abi3.so paired with _index.js

Hunting strings / host indicators:

  • thebeautifulmarchoftime, thebeautifulsnadsoftime — fallback C2 discovery strings
  • /tmp/.sshu-setup.js — SSH propagation path
  • Payload discovery / exec signatures: os.path.join(d,"_index.js"), _s.run([_b,"run",_j],check=False)
  • Upload User-Agent Bun/1.3.14 (not malicious alone, notable in context)
  • File hashes: langchain_core_mcp-1.4.2-py3-none-any.whl SHA256 6d332f814f15f19758d65026bbfd0a8c49671b319ec77b8fa1b27fc48afff7d9; langchain_core-setup.pth SHA256 6506d31707a39949f89534bf9705bcf889f1ecae3dbc6f4ff88d67a8be3d01b2

In CI/CD, inspect runners for /var/run/docker.sock abuse, poisoned /etc/hosts, unexpected privileged containers, and workflow changes. Notably, the malware targets StepSecurity defenses: harden-runner, and blocks agent.stepsecurity.io, api.stepsecurity.io, app.stepsecurity.io.

Caveats

Socket offers three unresolved readings of the payload-less langchain-core-mcp wheel: a fixed reliability bug from the earlier loader, an accidental incomplete publish, or deliberate paired-package staging — but treats the behavior as malicious regardless. Full payload breakdown (GitHub dead-drop, Docker/SSH propagation) is deferred to the prior Hades PyPI report.

Organisations named here

  • Shai-Hulud

Technologies named here

  • embiggen
  • Bun
  • Socket Threat Research campaign tracker
  • ensmallen
  • gpsea
  • Harden-Runner
  • YARA rules
  • phenopacket-store-toolkit
  • ppkt2synergy
  • pyphetools
  • rsquests
  • tlask
  • rlask
  • langchain-core-mcp
  • PyPI
  • Python
  • LangChain
  • Docker
  • StepSecurity

Techniques named here

  • .pth startup-hook execution
  • Native extension import-time execution
  • Loader/payload split via sys.path search
  • Run-once marker file
  • LLM-scanner anti-analysis / prompt injection
  • Credential and secret theft
  • Docker socket abuse
  • SSH propagation
  • Fallback C2 discovery
  • Security tool blocking

Threat actors named here

  • Mini Shai-Hulud
  • Miasma
  • Hades