Malicious RubyGem strutil-core 1.0.1 Delivers Credential-Stealing Worm

· Original article ↗

Summary

Socket analyzed malicious RubyGem strutil-core 1.0.1, whose install hook runs a worm that steals credentials, spreads across package registries and poisons AI coding tools. Sandbox and code analysis found no confirmed victims or downstream infections.

Key points

  • The malicious strutil-core 1.0.1 was published less than two hours after a clean 1.0.0; RubyGems removed both versions about five hours after the malicious release.
  • A sandbox confirmed install-time payload execution and credential-file reads. The article's other findings come from static code analysis; no victims or successful downstream package publications were confirmed.
  • The worm collects credentials from cloud, CI, package registry, SSH, and AI coding tools, then attempts exfiltration to hxxps://paleasbest[.]top/v1/api, with GitHub and GitLab fallbacks.
  • The payload includes package-republishing routines, CI runner memory scraping, and persistence through services and AI-tool or repository configuration changes.
  • A conditional wiper monitors a stolen GitHub token and can delete the user's home directory if the token returns HTTP 401 or 403; the monitor is not installed on every potentially infected host.
  • Socket links the build to testmetest and the Miasma family through shared components, while noting that shared code from the public Shai-Hulud toolkit does not establish a common operator.
  • The article advises isolating affected systems, removing persistence before revoking the relevant token, rotating reachable credentials from a clean device, and rebuilding the host.

Article Details

Attack Vectors
  • Installing [email protected] runs ext/strutil-core/extconf.rb, which downloads Bun and executes the bundled JavaScript payload without requiring an application to load the gem.
  • The payload collects credentials from files, environment variables, and GitHub Actions runner memory, then exfiltrates data to paleasbest[.]top with GitHub and GitLab fallbacks.
  • The worm contains routines to republish malicious packages to RubyGems, npm, and PyPI, and spreading code for JFrog Artifactory, GitHub, GitLab, and SSH; successful downstream publication from this gem was not confirmed.
  • A Python backdoor persists as a systemd user service or macOS LaunchAgent and executes scripts from URLs announced in appropriately signed GitHub commit messages.
  • The payload can poison AI coding tool and IDE configurations with MCP servers, hooks, and instruction files that may trigger execution when a repository is opened.
  • On the GitHub-token path, a monitor deletes the user's home directory if the stolen token returns HTTP 401 or 403.
Defensive Notes
  • If [email protected] was installed, isolate the host and remove net-health-checker and pkg-runtime, including their service units or LaunchAgents, before revoking the GitHub token stored at ~/.config/net-health-checker/token.
  • Rotate credentials reachable from an affected host or runner using a clean device, then rebuild the host; uninstalling the gem alone does not remove the persistent payload.
  • Check Gemfile.lock files, CI caches, and container images for strutil-core, and review maintained packages for unexpected patch releases or newly added ext/*/extconf.rb files and extensions entries.
  • Review repositories and home directories for unrecognized workspace-tools MCP entries, SessionStart hooks, .github/init.js, AGENTS.md, CLAUDE.md, and .vscode/tasks.json changes.
  • Hunt for the reported file hashes and persistence artifacts, Bun launched from /tmp/.b_<pid> by Ruby, sudo python3 reading /proc/<pid>/mem on CI runners, and egress to paleasbest[.]top.

Indicators of compromise

TypeIndicatorContext
DOMAINpaleasbest[.]topReported primary collection and exfiltration domain for the payload.
SHA256306c1deec402e8b4a6478e7f0fe02194bcd224d37d8fc6ba61ad1951e8abd7a9SHA-256 of the bundled JavaScript worm payload ext/strutil-core/index.js.
SHA2563b3f6e1bde0b28b015030a81a6d805b5b5306dc3f021e1102123971cfd83acc0SHA-256 of the malicious strutil-core-1.0.1.gem package.
SHA256c5264f3b9cf2f95c83a70b7dd7430aab8abc262b853dbbcd5386c3a8a9c74769SHA-256 of the malicious extconf.rb installer shipped with the package and identified as output of the worm's RubyGems injector.
SHA256c78daf27c42c3929758b24c2ef0baf65eea81b26b0fddfe8a5b748672d40d5f5SHA-256 of the Windows addon embedded in the malicious payload.
SHA256c7ef186aa59b67d9b198a14f6dc8aaee6dd86510ac7c37d28f65d310cd846411SHA-256 of the embedded sync.py backdoor installed for persistence and remote script execution.
SHA256e29a5319888319b51345ab8e3e009938ee5c2b9ae5d6bdd053f4f44c98f309d3SHA-256 of the embedded net-health-checker installer associated with the token-revocation-triggered wiper.
URLhxxps[:]//paleasbest[.]top/v1/apiReported collection endpoint receiving encrypted exfiltrated data; the article says it was not tested for liveness.

MITRE ATT&CK

T1003.007 · Proc FilesystemOn GitHub Actions runners, an embedded Python script reads /proc/<pid>/maps and /proc/<pid>/mem to extract secrets from the worker process.T1027 · Obfuscated Files or InformationThe bundle uses string obfuscation and includes gzip-compressed, AES-256-GCM-encrypted embedded components.T1059.004 · Unix ShellThe payload uses shell commands for actions including its token-triggered home-directory deletion.T1059.006 · PythonThe payload installs and runs sync.py, and pipes an embedded Python script to sudo on GitHub Actions runners.T1059.007 · JavaScriptThe gem installer runs the bundled JavaScript payload through Bun.T1105 · Ingress Tool TransferThe install hook downloads Bun, and the backdoor downloads and runs scripts from signed GitHub commit messages.T1195.002 · Compromise Software Supply ChainThe malicious RubyGems package executes its payload during installation; the worm also contains package-republishing routines.T1485 · Data DestructionThe net-health-checker monitor runs a stored deletion command against the user's home directory if the stolen GitHub token returns HTTP 401 or 403.T1528 · Steal Application Access TokenThe payload steals application access tokens, including GitHub and package-registry credentials, and uses stolen GitHub tokens for exfiltration.T1543.001 · Launch AgentThe payload registers pkg-runtime and net-health-checker as LaunchAgents on macOS.T1543.002 · Systemd ServiceThe payload installs the pkg-runtime and net-health-checker persistence services as systemd user services.T1548.003 · Sudo and Sudo CachingThe payload uses sudo to read runner process memory and starts a privileged container that adds passwordless sudo access.T1552.001 · Credentials In FilesCredential collectors read files such as .aws/credentials, .npmrc, .pypirc, .gem/credentials, and .docker/config.json.T1562.001 · Disable or Modify ToolsThe payload disables StepSecurity Harden-Runner by killing its container and manipulating runner network configuration.T1567.001 · Exfiltration to Code RepositoryWhen its primary endpoint fails, the payload can create a public GitHub repository or fall back to GitLab for exfiltration.

People

Malware

Vendors

Products

BunInstall-time execution: a native extension script, ext/strutil-core/extconf.rb, downloads the Bun JavaScript runtime and runs the bundled ext/strutil-core/index.js during gem install.GitHubCredential theft: the payload collects cloud, CI, package registry, SSH, AI coding tool and wallet credentials, then exfiltrates them to paleasbest[.]top with GitHub and GitLab fallbacks.GitHub ActionsGitHub Actions Runner MemoryGitLabCredential theft: the payload collects cloud, CI, package registry, SSH, AI coding tool and wallet credentials, then exfiltrates them to paleasbest[.]top with GitHub and GitLab fallbacks.Harden-Runnergrant passwordless sudo, so the read succeeds by default. The payload also disables StepSecurity Harden-Runner, an agent that monitors and filters network traffic on GitHub Actions runners. Through the DockerJFrog ArtifactorySelf-propagation: it contains republishing routines for RubyGems, npm and PyPI, plus JFrog Artifactory, GitHub, GitLab and SSH spreading code.npmSelf-propagation: it contains republishing routines for RubyGems, npm and PyPI, plus JFrog Artifactory, GitHub, GitLab and SSH spreading code.PyPISelf-propagation: it contains republishing routines for RubyGems, npm and PyPI, plus JFrog Artifactory, GitHub, GitLab and SSH spreading code.RubyGemsSocket’s Threat Research Team analyzed strutil-core version 1.0.1, a malicious RubyGems package that runs a 5.48 MB credential-stealing worm when it is installed. The RubyGems account jamnajiea published a clean 1.0.0

Related Articles