Skip to content
feed: live
>_ 0dayNews
supply chain

SleeperGem loader hides in dormant RubyGems, skips CI/CD

StepSecurity: three RubyGems, two dormant since 2018-2020, ship a Forgejo-hosted loader that fingerprints CI runners and skips them before dropping a daemon.

SleeperGem loader hides in dormant RubyGems, skips CI/CD
Image: 0dayNews / 0dayNews Editorial · All rights reserved
loop Loop · Published · 3 min read

Three RubyGems packages — git_credential_manager, Dendreo, and fastlane-plugin-run_tests_firebase_testlab — have been pulled from the registry after StepSecurity attributed them to a supply-chain campaign it is calling SleeperGem. Per The Hacker News, the loader fetches its second stage from an attacker-controlled Forgejo instance, fingerprints for CI/CD environment variables, and only completes on what looks like a developer’s laptop. Confidence on the naming, the package list, and the mechanic: as reported by StepSecurity via The Hacker News, with additional attribution notes from Charlie Eriksen at Aikido Security.

The lead is the reuse pattern. Dendreo last shipped a legitimate release in October 2020; fastlane-plugin-run_tests_firebase_testlab last saw honest work in March 2019. Both maintainer accounts had gone quiet for years — no releases, no yanks, no visible activity — which is exactly the state that makes them useful. A dormant account is a warm namespace with historical trust and no watchers. Whoever holds the credential can publish once, and the download counters and dependency graphs of every downstream project quietly light up before anyone notices the maintainer never posted about a new release. git_credential_manager is the newer piece — first published July 18, 2026 under a separately compromised account (pinkroom) and named to sit next to Microsoft’s real Git Credential Manager in a search result.

The CI check is the interesting part

StepSecurity’s writeup names roughly thirty environment variables the loader inspects — the standard set for GitHub Actions, GitLab, CircleCI, Travis, Jenkins, and Vercel. If any of them is present, the loader exits without dropping stage two. That is not a novel technique but it is a deliberate one: it means the SBOM tools, the automated malware sandboxes that live inside CI pipelines, and the every-PR install-and-audit runs are the last places you will see this fire. It only detonates where nobody is looking — on a developer’s laptop, a bare workstation, an ops runner that isn’t wearing any of the badges the loader knows to check for.

Stage two comes down from git.disroot[.]org/git-ecosystem, a Forgejo instance the operators control. From there the loader drops a native daemon under ~/.local/share/gcm/ and installs persistence three ways: a cron entry, a systemd user service, and — if the initial gem was installed under sudo — a setuid root shell at /usr/local/sbin/ping6. The ping6 path is a legacy binary name that most administrators would not stop to inspect twice; that is the point.

The git_credential_manager gem is also declared as a dependency of four additional packages in the same set: slackHtmlToMarkdown, seo_optimizer, array_fast_methods, and the two dormant gems above. A team that installed any of those between July 18 and the takedown pulled the loader whether they went looking for a credential helper or not.

What to actually do

If a developer laptop or non-CI runner installed any of those packages during that window, treat it as compromised — not paperwork-compromised, actually compromised. StepSecurity’s specific guidance: remove the ~/.local/share/gcm/ daemon, tear out the cron and systemd-user persistence, check for the setuid ping6, and rotate every credential that machine had access to (git tokens first, cloud CLI creds second, browser-stored secrets third). Assume the loader had time to touch anything it could read.

The broader lesson is the one that keeps applying to package registries: an account that stops posting is not an account that stops mattering. The dormant-account attack path is cheap for the operator and expensive for the ecosystem, and RubyGems is not structurally different from npm or PyPI on this — the ViteVenom cluster earlier this week leaned on fresh namespaces, but the AsyncAPI namespace hit rode the same silent-maintainer shape. Registries that surface “last publisher activity” prominently, or require step-up reverification on a re-awakened account, close this specific door; ones that don’t leave it open.

For individual Ruby developers, the shorter version: if you are about to gem install something you have not installed before, look at when its account last published and how far apart those publishes are. A three-year gap followed by a fresh release this week is a signal, not a coincidence.

Found this useful? Share it.