# SleeperGem: dormant RubyGems maintainer accounts taken over to plant a backdoor

> On 2026-07-18 → 07-19 an actor reactivated two long-dormant RubyGems maintainer accounts (Dendreo, dormant since 2020; fastlane-plugin-run_tests_firebase_testlab, dormant since 2019) and published a brand-new `git_credential_manager` gem impersonating Microsoft's Git Credential Manager. Seven malicious releases across three gems fetch a second-stage binary from `git.disroot.org/git-ecosystem/*` (Forgejo), skip execution if any of ~30 CI env vars are present, and drop a persistent native daemon on developer laptops.

- Published: 2026-07-18
- Last updated: 2026-07-19
- Severity: high
- Kind: Compromise - A legitimate, already-used package, maintainer account, CI pipeline, or release tag was hijacked and a malicious version was published under a name people already depend on.
- Ecosystems: RubyGems
- Scope: 3 packages, 7 compromised versions
- Tags: maintainer-takeover, account-takeover, dormant-domain, credential-theft, ci-cd-compromise
- Also known as: SleeperGem
- Detected by: Aikido, StepSecurity
- Incident ID: rubygems-2026-07-18-sleepergem-dormant-maintainer-takeover

## Affected packages (3)

Only the exact versions listed were named by the source advisories. Other versions are not implicated.

| Package | Ecosystem | Compromised versions |
|---|---|---|
| [Dendreo](https://dependencywatch.io/package/rubygems/Dendreo) | RubyGems | 1.1.3, 1.1.4 |
| [fastlane-plugin-run_tests_firebase_testlab](https://dependencywatch.io/package/rubygems/fastlane-plugin-run_tests_firebase_testlab) | RubyGems | 0.3.2 |
| [git_credential_manager](https://dependencywatch.io/package/rubygems/git_credential_manager) | RubyGems | 2.8.0, 2.8.1, 2.8.2, 2.8.3 |

## What happened

On 2026-07-18 → 07-19 an actor reactivated two long-dormant RubyGems maintainer accounts and published a brand-new impersonator gem in a 24-hour window that Aikido named **SleeperGem** - the first known at-scale RubyGems dormant-maintainer takeover of the shape that has hit npm and PyPI repeatedly since 2024. Three gems were compromised across seven releases; every release has been yanked from `rubygems.org` and every affected version is listed in the packages map below.

## The three compromised gems

| Gem | Malicious versions | Publish (UTC) | Dormancy before compromise | Yanked? |
|---|---|---|---|---|
| `git_credential_manager` | `2.8.0`, `2.8.1` | 2026-07-18 | N/A (brand-new gem) | Yes |
| `git_credential_manager` | `2.8.2`, `2.8.3` | 2026-07-19 (17 min apart) | N/A | Yes |
| `Dendreo` | `1.1.3`, `1.1.4` | 2026-07-18 | ~6 years (last release 2020-10-24) | Yes |
| `fastlane-plugin-run_tests_firebase_testlab` | `0.3.2` | 2026-07-19 | ~7 years (last release 2019-03-04) | Yes |

### `git_credential_manager` - the impersonator

A brand-new gem published under a fresh account, named to impersonate Microsoft's [git-ecosystem/git-credential-manager](https://github.com/git-ecosystem/git-credential-manager) CLI. The real Microsoft tool is distributed as a native binary through Homebrew / apt / a Microsoft installer and has never been shipped as a Ruby gem - so the mere existence of a RubyGems package by that name is itself the deception. Version numbers `2.8.x` were chosen to sit slightly ahead of the real project's 2.6.x release train, giving the fake plausible "latest" placement in `gem search` results.

The operator shipped four versions in rapid succession. The first two (`2.8.0`, `2.8.1` on 2026-07-18) contained a downloader-only installer. After an eight-hour pause (presumably an overnight break in the operator's time zone), `2.8.2` and `2.8.3` landed on 2026-07-19 seventeen minutes apart - `2.8.2` wired the installer into the gem's Ruby load path (so `require "git_credential_manager"` fires the chain, not just `gem install`), and `2.8.3` uncommented the single line that actually executes the downloaded binary. This staged-uncomment pattern suggests the operator was watching install telemetry in real time and iterating quickly to activate the payload once install volume looked convincing.

### `Dendreo` - the dormant-account takeover

`Dendreo` had shipped `1.0.1` → `1.1.2` between 2017-10-14 and 2020-10-24, then went silent for **~6 years**. On 2026-07-18 the account pushed `1.1.3` and `1.1.4` back-to-back on the same day. Both were yanked; `1.1.0` from the historical release train was also yanked as part of the cleanup, so the current known-good version on RubyGems is `1.1.2` (2020-10-24).

### `fastlane-plugin-run_tests_firebase_testlab` - dormant + no upstream Git tag

This fastlane plugin last shipped `0.3.1` on 2019-03-04 and went silent for **~7 years**. On 2026-07-19 a `0.3.2` release appeared on RubyGems. Two independent takeover tells confirm the compromise:

1. **Dormancy gap**: seven years with no publish, then a single release out of the blue.
2. **No matching Git tag** in the upstream source repository. Legitimate fastlane plugins are always tagged in Git as part of the release workflow, so a RubyGems release with no corresponding Git tag never came from the real project.

## Install-time payload chain

1. `gem install` / `bundle install` triggers the gem's installer hook (or, for `git_credential_manager` `2.8.2+`, the load-path require).
2. The installer runs a **`skip_install` check** - it scans the process environment for **~30 CI-platform environment variables** (`GITHUB_ACTIONS`, `GITLAB_CI`, `CIRCLECI`, `TRAVIS`, `JENKINS_URL`, `VERCEL`, `BUILDKITE`, `DRONE`, `TEAMCITY_VERSION`, etc.) and returns immediately if any are set. This is a deliberate choice to fly under automated malware scanners (Socket / Aikido / OpenSSF Package Analysis all run in CI-shaped environments) while still landing on human developer laptops.
3. On a laptop (no CI vars), the installer fetches a native binary from `https://git.disroot.org/git-ecosystem/*` - a public Forgejo instance where anyone can register. The **`git-ecosystem`** username on that instance was registered by the attacker specifically to visually mimic the real [github.com/git-ecosystem](https://github.com/git-ecosystem) organization on GitHub that publishes the Microsoft Git Credential Manager. SSL verification is disabled on the download call.
4. The binary is executed via `system()` (Linux/macOS) or PowerShell (Windows) and, per StepSecurity's analysis, establishes persistence and beacons to attacker infrastructure.

## Why "SleeperGem"

Aikido coined the name to capture the core novelty: the compromise vector is not a fresh account or a typosquat, but **real, ordinary accounts that had simply gone dormant and looked harmless enough to hijack without anyone noticing**. The pattern is well-established on npm ([node-ipc 2026-05-14](https://dependencywatch.io/incident/npm-2026-05-14-node-ipc-dormant-takeover), [dbmux 2026-06-09](https://dependencywatch.io/incident/npm-2026-06-09-dbmux-maintainer-takeover)) and on PyPI, but RubyGems had until now been largely spared - SleeperGem marks the first time the same playbook has been executed at scale against Ruby maintainers.

## Registry state (2026-07-19)

All seven malicious releases have been yanked from `rubygems.org` - the versions are no longer resolvable via `bundle install` against the public registry. However, gems that were pulled into a lockfile between 2026-07-18 and the yank window will remain pinned to the malicious versions on any host where the Gemfile.lock was frozen. Internal RubyGems mirrors (Bundler-Inc, Artifactory RubyGems, Gemfury) that cached the tarballs during the publish window will continue to serve them after the public yank - any lockfile hit against the versions in the packages map below must be treated as active malware regardless of what `rubygems.org` currently returns.

## Impact

- Any developer laptop that ran `gem install` or `bundle install` and resolved one of the seven malicious releases below during 2026-07-18 → 07-19 should be treated as fully compromised - the payload deliberately skips CI/build servers and targets interactive developer machines, so exposure surface is workstations that actively ran `bundle install` in that window
- **Attack shape (SleeperGem - Aikido, 2026-07-19)**: two previously dormant RubyGems maintainer accounts were reactivated within hours of each other to push the same malicious dependency into gems people already trusted - the first known RubyGems dormant-maintainer takeover of the scale npm and PyPI have dealt with for over a year. Combined with the brand-new `git_credential_manager` gem impersonating Microsoft's official Git Credential Manager CLI, three gems were compromised in a 24-hour window
- **Compromised account 1 - Dendreo (dormant since 2020-10-24)**: two malicious versions `1.1.3` and `1.1.4` pushed on 2026-07-18 after **~6 years of dormancy**. Both yanked; the account had previously shipped `1.0.1` → `1.1.2` between 2017 and 2020
- **Compromised account 2 - fastlane-plugin-run_tests_firebase_testlab (dormant since 2019-03-04)**: malicious `0.3.2` released on 2026-07-19 after **~7 years of dormancy**. Yanked. Has no matching Git tag in the upstream source repository - the smoking gun that the release never came from the real project
- **Brand-new impersonator gem - git_credential_manager (never previously existed)**: four malicious releases in rapid succession - `2.8.0` and `2.8.1` on 2026-07-18, then `2.8.2` and `2.8.3` on 2026-07-19 seventeen minutes apart. The `2.8.x` version alignment mimics the real [git-ecosystem/git-credential-manager](https://github.com/git-ecosystem/git-credential-manager) release train (the Microsoft-maintained CLI is at 2.6.x in mid-2026); the naming and versioning is designed to be picked up by anyone searching for the Microsoft tool via `gem install`
- **git_credential_manager escalation chain**: `2.8.0` and `2.8.1` shipped a downloader-only installer. After an eight-hour gap (presumably the operator's sleep window), `2.8.2` wired the downloader directly into the gem's Ruby load path so **merely `require "git_credential_manager"` triggers the whole chain** - no explicit installer invocation needed. The line that actually invokes the downloaded binary was commented out in `2.8.2` and uncommented seventeen minutes later in `2.8.3` - an unusually fast operator-visible iteration cycle that suggests the actor was watching install telemetry in real time
- **Second-stage delivery - `git.disroot.org` Forgejo abuse**: the installer fetches a native binary from `https://git.disroot.org/git-ecosystem/*` (a public Forgejo instance where anyone can register). The `git-ecosystem` username on that instance was **registered by the attacker** to visually mimic the real [github.com/git-ecosystem](https://github.com/git-ecosystem) organization that publishes the Microsoft Git Credential Manager - a namespace-collision technique that also works because the Forgejo instance federates to `git.disroot.org` and appears as a legitimate-looking URL. SSL verification is disabled on the download call, so any TLS-inspecting proxy that would have flagged the certificate mismatch is bypassed
- **CI evasion - `skip_install` check on ~30 environment variables**: the installer scans the environment for any of a curated list of ~30 CI-platform env vars (`GITHUB_ACTIONS`, `GITLAB_CI`, `CIRCLECI`, `TRAVIS`, `JENKINS_URL`, `VERCEL`, `BUILDKITE`, etc.) and does nothing if any are present. This is a deliberate choice to fly under the radar of automated malware scanners (Socket / Aikido / OpenSSF Package Analysis all run in ephemeral CI-shaped environments) while still landing on human developer laptops where an initial infection can pivot to source-code access, SSH keys, browser credentials, and cloud CLI tokens
- **Persistent daemon**: on a developer laptop (no CI env vars present) the installer downloads a native binary and executes it via `system()` on Linux/macOS or PowerShell on Windows. StepSecurity's analysis confirms the binary establishes persistence and beacons back to attacker infrastructure - the exact C2 shape has not been publicly disclosed as of 2026-07-19

## What to do

1. Grep every `Gemfile.lock` for the exact gem-name + version pairs in the packages map below. Any match on a developer laptop (not a CI runner - the malware deliberately skipped CI) is a full compromise: re-image the laptop, rotate every credential the developer had touched (git tokens, cloud CLI, SSH keys, browser-saved passwords, IDE Copilot/AI provider tokens, RubyGems API keys)
2. **If you had `git_credential_manager` in a `Gemfile.lock`**: this gem never had a legitimate parent - it was created solely to impersonate the [github.com/git-ecosystem/git-credential-manager](https://github.com/git-ecosystem/git-credential-manager) CLI, which is distributed as a native binary (not a gem) and is normally installed via Homebrew, apt, or the Microsoft installer. There is no legitimate reason to have `git_credential_manager` as a gem dependency - the presence of it in a lockfile is by itself a supply-chain incident
3. **If you had `Dendreo` in a Gemfile.lock at 1.1.3 or 1.1.4**: downgrade to `1.1.2` (2020-10-24 - the last known-good release before the maintainer went dormant) or replace with an alternative. Contact the original maintainer through a channel other than the compromised RubyGems account to confirm any future release
4. **If you had `fastlane-plugin-run_tests_firebase_testlab` at 0.3.2**: pin back to `0.3.1` (2019-03-04) or migrate off the plugin - Firebase Test Lab is now typically driven directly via `gcloud firebase test` rather than through this dormant fastlane plugin
5. Audit outbound traffic from developer laptops for HTTPS calls to `git.disroot.org` from a Ruby / gem installer process - legitimate Ruby developer workflows almost never hit that Forgejo instance, so any hit during the 2026-07-18 → 07-19 window (or later, if the operator republishes) is a strong SleeperGem indicator. The download call disables SSL verification, so any TLS-inspecting proxy will have seen the cleartext HTTP-CONNECT to `git.disroot.org:443` even if it could not decrypt the response
6. Search EDR / process telemetry for `ruby` or `bundler` invoking `system()` / `sh -c` / `powershell.exe` during a `gem install` or `bundle install` operation, with a payload that fetches a binary from a non-`rubygems.org` host. This is the SleeperGem-family install-time behaviour signature
7. For RubyGems-security defenders: this is the first at-scale dormant-maintainer takeover of RubyGems. Consider requiring 2FA and forced-reset on any RubyGems account that has been inactive for >1 year, and treat any new release from a >5-year-dormant account as suspicious by default. Any gem published from a dormant account without a matching Git tag in the upstream repo is a strong takeover signal

## References

- [SleeperGem: RubyGems supply chain attack targets dormant maintainer accounts](https://www.aikido.dev/blog/sleepergem-rubygems-supply-chain-attack) - Aikido
- [SleeperGem: Compromised git_credential_manager, Dendreo, and fastlane RubyGems Drop a Persistent Backdoor](https://www.stepsecurity.io/blog/sleepergem-compromised-rubygems-drop-persistent-backdoor) - StepSecurity
- [git_credential_manager on RubyGems (yanked versions listing)](https://rubygems.org/gems/git_credential_manager/versions) - RubyGems
- [Dendreo on RubyGems (yanked versions listing)](https://rubygems.org/gems/Dendreo/versions) - RubyGems
- [fastlane-plugin-run_tests_firebase_testlab on RubyGems (yanked versions listing)](https://rubygems.org/gems/fastlane-plugin-run_tests_firebase_testlab/versions) - RubyGems
- [git-ecosystem/git-credential-manager - the real Microsoft-maintained CLI the impersonator gem mimics](https://github.com/git-ecosystem/git-credential-manager) - GitHub

---

Canonical page: https://dependencywatch.io/incident/rubygems-2026-07-18-sleepergem-dormant-maintainer-takeover
Markdown version: https://dependencywatch.io/incident/rubygems-2026-07-18-sleepergem-dormant-maintainer-takeover.md
Site index for agents: https://dependencywatch.io/llms.txt
DependencyWatch.io is operated by Precursor Security (https://precursorsecurity.com).
