- Socket found that strutil-core 1.0.1, a Ruby gem, ran a credential-stealing worm at install time and wrote itself into AI coding tool settings.
- The worm's monitor deletes a home directory when a stolen GitHub token is revoked, so the usual first response can cause damage.
- Teams should check lockfiles, remove the persistence first, then revoke and rotate credentials from a clean device.
We judge software by what it does when we use it. This Ruby package did its work before anyone used it. Socket's Threat Research Team analysed strutil-core version 1.0.1 and found a worm that runs during installation. It steals credentials, writes itself into the settings of AI coding tools, and can delete files if a stolen token is revoked.
The lesson here is that the install step is the attack surface. Review effort usually goes to what code does at run time. This gem shows that the install step deserves the same attention.
What Socket found
The RubyGems account jamnajiea published a clean strutil-core 1.0.0 on November 1, 2026. Less than two hours later it pushed the malicious 1.0.1. Socket says its AI Scanner flagged the release 70 seconds after publication. The public window was short: roughly five hours passed between the malicious upload and RubyGems pulling both versions.
The scope is narrow. Socket found no public projects that depend on the gem. It reports no confirmed victims and no confirmed downstream packages infected by it. Socket also says most of its analysis is static, meaning it comes from reading the code. A sandbox run by Bitbison confirmed only the install-time execution and the credential reads.
How it runs without being used
The gem claims to offer string helpers. It also declares a native extension, a piece of code RubyGems runs during installation to prepare a build. Here that script contains no build logic. On Linux and macOS it downloads the Bun JavaScript runtime and runs a 5.48 MB bundled payload. It then writes a build file that does nothing, so the install finishes without errors.
No application has to load the gem. Running gem install, or bundle install against a file that resolves to the gem, is enough.
Your AI tools become the hiding place
The payload reads credential files and environment variables. Bitbison's sandbox recorded reads from 51 credential stores. They included cloud, package registry, container and Kubernetes files. They also included .claude/.credentials.json and .codex/auth.json, which belong to AI coding tools.
Then it writes itself into those tools. Socket reports that it adds an MCP server entry named workspace-tools to configurations it finds. MCP is the standard that lets AI assistants call outside tools. Other configurations gain SessionStart hooks, which run commands when a session opens.
With stolen Git credentials, it commits the same files into repositories. These include CLAUDE.md and AGENTS.md. Socket says the generated AGENTS.md instructs coding agents to launch a setup script before they run anything else. Whether the worm restarts when someone opens that repository in an AI tool or VS Code depends on the tool's workspace trust and approval settings.
This worm treats files written to guide AI assistants as a place to persist. Those files are plain text that people tend to read as documentation. A reviewer skimming a pull request may not read a markdown file as something that runs. That last point is our interpretation, not Socket's finding.
The response playbook is the trap
If the worm obtains a GitHub token, it installs a monitor called net-health-checker. Every 45 seconds the monitor checks the token. A 401 or 403 response runs a stored handler. Socket says the handler wipes the home directory once the token stops working.
Revoking a token is what a responder would do first. Socket's guidance reverses the order. Isolate the host. Stop and remove net-health-checker and a second persistence service, pkg-runtime. Only then revoke the token.
That second service checks public GitHub commits every hour for a marker. It runs scripts from URLs signed with the attacker's key. Socket notes that the signature covers the URL, not the downloaded script, so whoever controls the content at that address controls what runs. Removing the gem alone leaves the infection in place, because the payload lives outside the gem directory.
Old code, new route
The RubyGems injector is not new. Socket compared it with a deobfuscated June 2026 copy of the Miasma payload, which was published for defensive research. Socket counted 36 non-empty lines in the gem's installer. Thirty-three of them match that June template exactly, so the new build changed very little of the injection routine.
Socket judges the gem to be a newer build of the testmetest worm, which descends from the public Shai-Hulud toolkit. It adds a caution. Because that toolkit's code has been openly available since May 2026, finding the same code in two places does not prove one operator is behind both. Shared code is weak evidence of authorship.
What to ask your team
Ask whether any machine or CI runner installed strutil-core 1.0.1. Check lockfiles, CI caches and container images for the gem. If a system did install it, Socket's advice is to regard that system, and every credential it could reach, as compromised. Rotate them from a clean device.
Ask who owns the incident order. Write down that persistence comes off before tokens are revoked. Ask whether gems you maintain gained an unexpected patch release or a new extension entry. Ask who reviews changes to AGENTS.md, CLAUDE.md and MCP settings, and whether your AI tools prompt before running them.
A package is code you run. With native extensions, it can run before you have decided to trust it.
Produced by the WebPulse Newsroom with AI assistance from the original reporting credited below, and checked against that source by our editorial review. How we use AI.
Original reporting: Socket.





