Malicious RubyGems strutil-core 1.0.1 installs Miasma/testmetest worm that steals developer and AI tool credentials
strutil-core 1.0.1, a malicious gem on RubyGems, runs a 5.48 MB credential-stealing worm during gem install or bundle install, and no application has to load it. The package is a new build of the testmetest worm from the Miasma family, which grew out of the publicly released Shai-Hulud toolkit. The account jamnajiea published a clean 1.0.0 on November 1, 2026 and pushed 1.0.1 less than two hours later; RubyGems removed both versions about five hours after the malicious release, and Socket's AI Scanner had flagged the payload 70 seconds after publication (socket.dev). Socket found no public dependents and has confirmed no victims, so real-world impact is unknown. Criticity is high rather than critical because there is no confirmed exploitation or victim, but any host that installed 1.0.1 must be treated as compromised, and revoking a stolen GitHub token can trigger a wiper.
Detalhes técnicos
- Install-time execution: the native extension script
extconf.rbcontains no build logic. On Linux and macOS it downloads the Bun runtime (version 1.2.18) and runs the bundledindex.js, then writes a Makefile with empty targets so the installation finishes cleanly (socket.dev). - Injector origin: the installer is byte-identical to the output of the payload's own RubyGems injection module, and 33 of its 36 non-empty lines match a deobfuscated June 2026 Miasma payload. The injector only edits gemspec metadata, which explains why the library still declares VERSION 1.0.0 inside the 1.0.1 release (socket.dev).
- Credential theft: the payload targets cloud, CI, package registry, SSH, wallet and AI coding tool secrets. Bitbison's sandbox logged reads from 51 credential stores, including
.claude/.credentials.jsonand.codex/auth.json(gbhackers.com, socket.dev). Results are encrypted with AES-256-GCM and posted topaleasbest[.]top, with GitHub and GitLab fallbacks (socket.dev). - CI runners: inside GitHub Actions the payload reads runner worker memory through
/proc, a technique also seen in the March 2025 tj-actions/changed-files compromise. It tries to tamper with StepSecurity Harden-Runner, but StepSecurity states those attempts do not succeed (socket.dev). - Persistence and backdoor: a Python backdoor,
sync.py, is registered as the systemd user servicepkg-runtime(or a LaunchAgent on macOS). Every hour it checks public GitHub commits for the markermsync-3f7aand executes only scripts whose URLs carry a valid RSA-PSS signature from the operator (socket.dev). - AI tool poisoning: the worm adds a
workspace-toolsMCP server and SessionStart hooks to local AI tool configurations. With stolen Git credentials it commitsCLAUDE.md,AGENTS.md,.cursor/mcp.jsonand.vscode/tasks.jsoninto repositories. The generated AGENTS.md instructs agents to run a setup script first, so opening an affected repository can re-run the worm depending on workspace trust and approval settings (gbhackers.com, socket.dev). - Wiper: when a stolen GitHub token is accepted, the
net-health-checkermonitor checks it every 45 seconds. A 401 or 403 response deletes the home directory, so revoking the token first can destroy data (gbhackers.com, socket.dev). - Propagation: the code contains republishing routines for RubyGems, npm and PyPI and spreading code for JFrog Artifactory, GitHub, GitLab and SSH. Socket confirmed the routines exist but saw no successful downstream publication (socket.dev).
- Relationship to testmetest: the gem shares
sync.py, the command markers and the wiper logic with testmetest, which SafeDep documented in October, but uses a new C2 domain, a RubyGems delivery path and a different encryption scheme. Because the Shai-Hulud source has been public since May 2026, shared code does not prove a single operator (socket.dev). The same domain appears in the PyPI packagepystr-codec(versions 0.1.0 to 0.1.2), which Kamil Mańkowski documented as MAL-2026-18432 (gbhackers.com, osv.dev).
Remediação
- Isolate any host where strutil-core 1.0.1 was installed.
- Remove the
net-health-checkerandpkg-runtimepersistence before revoking any token, because revocation starts the wipe logic (socket.dev). - Rotate credentials from a clean device, then rebuild the machine. Uninstalling the gem does not remove the infection, since the payload persists outside the gem directory (gbhackers.com).
- Check repositories for the committed files listed above and review local AI tool configurations for the
workspace-toolsMCP entry and SessionStart hooks.
Linha do tempo
-
Malicious RubyGems strutil-core 1.0.1 installs Miasma/testmetest worm that steals developer and AI tool credentials
ler a análise desta fonte ocultar
strutil-core 1.0.1, a malicious gem on RubyGems, runs a 5.48 MB credential-stealing worm during
gem installorbundle install, and no application has to load it. The package is a new build of the testmetest worm from the Miasma family, which grew out of the publicly released Shai-Hulud toolkit. The accountjamnajieapublished a clean 1.0.0 on November 1, 2026 and pushed 1.0.1 less than two hours later; RubyGems removed both versions about five hours after the malicious release, and Socket's AI Scanner had flagged the payload 70 seconds after publication (socket.dev). Socket found no public dependents and has confirmed no victims, so real-world impact is unknown. Criticity is high rather than critical because there is no confirmed exploitation or victim, but any host that installed 1.0.1 must be treated as compromised, and revoking a stolen GitHub token can trigger a wiper.Technical Details
- Install-time execution: the native extension script
extconf.rbcontains no build logic. On Linux and macOS it downloads the Bun runtime (version 1.2.18) and runs the bundledindex.js, then writes a Makefile with empty targets so the installation finishes cleanly (socket.dev). - Injector origin: the installer is byte-identical to the output of the payload's own RubyGems injection module, and 33 of its 36 non-empty lines match a deobfuscated June 2026 Miasma payload. The injector only edits gemspec metadata, which explains why the library still declares VERSION 1.0.0 inside the 1.0.1 release (socket.dev).
- Credential theft: the payload targets cloud, CI, package registry, SSH, wallet and AI coding tool secrets. Bitbison's sandbox logged reads from 51 credential stores, including
.claude/.credentials.jsonand.codex/auth.json(gbhackers.com, socket.dev). Results are encrypted with AES-256-GCM and posted topaleasbest[.]top, with GitHub and GitLab fallbacks (socket.dev). - CI runners: inside GitHub Actions the payload reads runner worker memory through
/proc, a technique also seen in the March 2025 tj-actions/changed-files compromise. It tries to tamper with StepSecurity Harden-Runner, but StepSecurity states those attempts do not succeed (socket.dev). - Persistence and backdoor: a Python backdoor,
sync.py, is registered as the systemd user servicepkg-runtime(or a LaunchAgent on macOS). Every hour it checks public GitHub commits for the markermsync-3f7aand executes only scripts whose URLs carry a valid RSA-PSS signature from the operator (socket.dev). - AI tool poisoning: the worm adds a
workspace-toolsMCP server and SessionStart hooks to local AI tool configurations. With stolen Git credentials it commitsCLAUDE.md,AGENTS.md,.cursor/mcp.jsonand.vscode/tasks.jsoninto repositories. The generated AGENTS.md instructs agents to run a setup script first, so opening an affected repository can re-run the worm depending on workspace trust and approval settings (gbhackers.com, socket.dev). - Wiper: when a stolen GitHub token is accepted, the
net-health-checkermonitor checks it every 45 seconds. A 401 or 403 response deletes the home directory, so revoking the token first can destroy data (gbhackers.com, socket.dev). - Propagation: the code contains republishing routines for RubyGems, npm and PyPI and spreading code for JFrog Artifactory, GitHub, GitLab and SSH. Socket confirmed the routines exist but saw no successful downstream publication (socket.dev).
- Relationship to testmetest: the gem shares
sync.py, the command markers and the wiper logic with testmetest, which SafeDep documented in October, but uses a new C2 domain, a RubyGems delivery path and a different encryption scheme. Because the Shai-Hulud source has been public since May 2026, shared code does not prove a single operator (socket.dev). The same domain appears in the PyPI packagepystr-codec(versions 0.1.0 to 0.1.2), which Kamil Mańkowski documented as MAL-2026-18432 (gbhackers.com, osv.dev).
Remediation
- Isolate any host where strutil-core 1.0.1 was installed.
- Remove the
net-health-checkerandpkg-runtimepersistence before revoking any token, because revocation starts the wipe logic (socket.dev). - Rotate credentials from a clean device, then rebuild the machine. Uninstalling the gem does not remove the infection, since the payload persists outside the gem directory (gbhackers.com).
- Check repositories for the committed files listed above and review local AI tool configurations for the
workspace-toolsMCP entry and SessionStart hooks.
- Install-time execution: the native extension script