Back to Blog

SleeperGem: Compromised git_credential_manager, Dendreo, and fastlane RubyGems Drop a Persistent Backdoor

Malicious versions of git_credential_manager, Dendreo, and a fastlane plugin were published to RubyGems. They fetch a second stage from a Forgejo command and control host, skip CI to target developer machines, and install a persistent daemon. StepSecurity ran them under Harden-Runner to capture the full kill chain.
Varun Sharma
View LinkedIn

July 19, 2026

Share on X
Share on X
Share on LinkedIn
Share on Facebook
Follow our RSS feed
SleeperGem RubyGems supply chain attack
Table of Contents

Between July 18 and July 19, 2026, malicious versions of three RubyGems packages were published to RubyGems.org in a coordinated supply chain attack that researchers named SleeperGem. The compromised gems are git_credential_manager, which impersonates the official Microsoft Git Credential Manager, along with Dendreo and fastlane-plugin-run_tests_firebase_testlab. Each malicious release is a loader. It fetches a second stage from an attacker controlled Forgejo host, checks whether it is running in a build system and skips if it is, and on a developer machine it drops a native daemon and installs persistence.

The releases were published straight to the registry with no matching commit or tag in the source projects. Two of the gems had been dormant for years before suddenly shipping new versions. StepSecurity ran every compromised version inside Harden-Runner in audit mode to capture the full kill chain, and this post walks through exactly what we observed.

Action required: If any of these gems were installed or required on a developer machine, treat that machine and every secret reachable from it as compromised. Remove the dropped daemon at ~/.local/share/gcm/, remove the systemd and cron persistence, check for a setuid shell at /usr/local/sbin/ping6, and rotate all credentials.

The compromised packages

We confirmed the malicious versions by comparing the RubyGems publish timeline against each project's GitHub release tags.

PackageAffected VersionsWhy flagged
git_credential_manager2.8.0, 2.8.1, 2.8.2, 2.8.3Impersonates the official Microsoft Git Credential Manager.
Dendreo1.1.3, 1.1.4Pushed on July 18 after the gem sat dormant since 2020.
fastlane-plugin-run_tests_firebase_testlab0.3.2Published July 19 with no matching GitHub tag; upstream tags stop at v0.3.1.

Two patterns made the malicious releases easy to spot. First, gems that had not shipped a release in years suddenly published new versions minutes apart. Second, a version appeared on RubyGems with no corresponding tag in the source repository, which means it never came from the real project.

RubyGems version history for the Dendreo gem showing versions 1.1.3 and 1.1.4 both published on July 18 2026, following version 1.1.2 from October 2020

Dendreo published two new versions on the same day after nearly six years of dormancy.

RubyGems version history for the fastlane-plugin-run_tests_firebase_testlab gem showing version 0.3.2 published July 19 2026 after 0.3.1 from March 2019

The fastlane plugin got a new 0.3.2 release years after 0.3.1, and it has no matching GitHub tag.

How the Attack Works

It hides from build systems

Before doing anything, the malware checks for around thirty environment variables that continuous integration platforms set, including GITHUB_ACTIONS, GITLAB_CI, and CIRCLECI. If it finds any of them, it exits and does nothing. This is deliberate. The attackers want to run on developer laptops, not on ephemeral CI runners where there is little of value and a high chance of detection. It also means a normal pipeline install shows no malicious behavior at all. To observe the real behavior, we stripped the CI environment variables before triggering the code, so the malware believed it was on a developer machine.

The gem is a loader

The gem contains very little malicious logic of its own. For git_credential_manager version 2.8.2 and later, the code runs the moment the library is required, not only at install time. On require, the gem spawns a child Ruby process that runs its bundled install script. That child downloads two files from the attacker command and control host: a shell script named deploy.sh and a native binary that carries the same name as the tool the gem impersonates.

The download uses Ruby's built in HTTP client with certificate verification switched off, and it sets the User-Agent header to the single word Git so the traffic blends in with normal Git activity. The command and control host is a public Forgejo instance, and the attacker registered a username that looks like an official ecosystem account to appear legitimate.

Harden-Runner process events showing the require call under a stripped environment spawning a child Ruby process that runs the gem bin/install script, which then runs deploy.sh

The loader chain captured by Harden-Runner. The require call spawns a child Ruby install process, which runs the downloaded deploy.sh.

Version 2.8.2 stages, version 2.8.3 detonates

Comparing versions side by side revealed that the attackers were iterating. In version 2.8.2 the line that launches the downloaded script is commented out, so that version only downloads the payload and stops. It stages the attack without pulling the trigger. Version 2.8.3 removes that safety and runs the full chain.

Persistence and privilege escalation

On version 2.8.3, the install script copies the downloaded binary into a hidden directory in the user home folder, marks it executable, and launches it as a background daemon. It then installs persistence twice, once as a systemd user service and once as a cron entry, both under the innocuous service name git-credential-manager, so the daemon restarts even if one method is removed. Finally it probes the sudo and wheel groups. If the user can run sudo without a password, the script re-runs itself as root, and when it runs as root it plants a setuid root copy of the system shell at a path chosen to mimic a networking utility. On our runner the user did not have passwordless sudo, so this branch checked the group and stopped, but the code path is present and active.

Harden-Runner process events showing deploy.sh running id, dirname, uname, mkdir, and copying the downloaded git-credential-manager binary into the hidden gcm directory

deploy.sh copies the downloaded binary into a hidden directory in the user home folder.

Harden-Runner process events showing chmod on the dropped binary, launching it as a daemon, installing systemd and cron persistence, and running getent on the wheel and sudo groups

The daemon launches, installs systemd and cron persistence, and probes the sudo and wheel groups for a path to root.

Runtime Validation with StepSecurity Harden-Runner

StepSecurity ran the compromised gems in a controlled GitHub Actions environment with Harden-Runner in audit mode. This captured the complete kill chain: network connections, the process tree, and file activity, across install-time and runtime jobs for every version.

GitHub Actions run summary for the Install SleeperGem Compromised RubyGems workflow showing all install-time and runtime detonation jobs completed successfully

The detonation harness. Each gem version runs in its own install-time and runtime job, all fronted by Harden-Runner.

Network events: command and control contact confirmed

Alongside the expected registry traffic, the runtime job's ruby process reached out to the attacker's Forgejo host. That single off-baseline destination is the whole external footprint of the loader on a runner.

Harden-Runner network events list for the runtime job showing outbound calls to github.com, release-assets.githubusercontent.com, index.rubygems.org, and git.disroot.org

The runtime job's outbound calls. Alongside normal registry traffic, the ruby process reaches git.disroot.org, the attacker's command and control host.

Harden-Runner API call detail showing two GET requests to git.disroot.org for deploy.sh and the git-credential-manager binary

The two requests to the command and control host are GETs that download deploy.sh and the git-credential-manager binary.

Process tree: the full kill chain

Harden-Runner's process monitoring recorded every process spawned after the require call. These are the real recorded steps, in order:

ruby <gem_path>/git_credential_manager-2.8.3/bin/install
sh -c /bin/sh '<gem_path>/git_credential_manager-2.8.3/package/deploy.sh' 2>&1 >/dev/null
cp <gem_path>/.../package/git-credential-manager $HOME/.local/share/gcm/git-credential-manager
chmod +x $HOME/.local/share/gcm/git-credential-manager
$HOME/.local/share/gcm/git-credential-manager --daemon
$HOME/.local/share/gcm/git-credential-manager install --method=systemd --service-name=git-credential-manager
systemctl --user daemon-reload
$HOME/.local/share/gcm/git-credential-manager install --method=cron --service-name=git-credential-manager
getent group sudo

This is the value of runtime monitoring. A static scan of the gem source shows suspicious code, but the process tree shows the attack executing, step by step, in order. It also shows where the credential theft lives. The gem itself never touches credentials. The harvesting and exfiltration live inside the native daemon that the loader drops and starts. In our runs the only external destination Harden-Runner recorded was the Forgejo host that served the payload, and characterizing the daemon's own network behavior is a separate analysis of that binary. It is worth noting that the fastlane plugin gem reached the same command and control host, which confirms these packages share infrastructure and are one coordinated campaign rather than three unrelated incidents.

Indicators of Compromise

Malicious gem versions:

  • git_credential_manager 2.8.0, 2.8.1, 2.8.2, 2.8.3
  • Dendreo 1.1.3, 1.1.4
  • fastlane-plugin-run_tests_firebase_testlab 0.3.2

Command and control host:

  • git.disroot.org, under a path that impersonates an official Git ecosystem account

Files and artifacts to hunt for:

  • $HOME/.local/share/gcm/git-credential-manager, the dropped daemon
  • $HOME/.local/share/gcm/.env, the daemon config the script writes
  • A systemd user unit named git-credential-manager whose ExecStart points at the dropped daemon
  • A cron entry that runs the dropped daemon
  • A setuid root shell at /usr/local/sbin/ping6 with permissions 6777 when the malware runs as root

Behavioral indicators:

  • A Ruby process spawning a child Ruby install script when a gem is merely required
  • Outbound HTTPS to git.disroot.org with certificate verification disabled and a User-Agent of Git
  • A binary dropped under the user home directory and launched as a background daemon

Am I Affected?

CI/CD Pipelines

Check your Harden-Runner organization baseline for any outbound connection to the command and control host. If git.disroot.org appears in your baseline, a compromised gem was required in one of your workflow runs and contacted the command and control host.

Developer Machines

Because SleeperGem skips CI and targets developer laptops, developer machines are the primary exposure surface. StepSecurity Dev Machine Guard scans developer machines for malicious files using its suspicious files detection, so it can flag the SleeperGem artifacts across your fleet: the gem loader source that hardcodes the git.disroot.org command and control host, the deploy.sh installer that references the /usr/local/sbin/ping6 backdoor, and the persistence unit that runs the dropped daemon from ~/.local/share/gcm/. Review flagged machines in the Dev Machine Guard dashboard.

Code Repositories

Search your lockfiles for the compromised versions:

grep -RniE 'git_credential_manager \((2\.8\.[0-3])\)|Dendreo \(1\.1\.[34]\)|run_tests_firebase_testlab \(0\.3\.2\)' --include=Gemfile.lock .

Recovery Steps

  1. Uninstall the malicious gem and pin to a known good version: gem uninstall git_credential_manager -v 2.8.3, then remove it from your Gemfile.
  2. Stop and remove persistence: disable the systemd user service named git-credential-manager, remove the matching cron entry, and delete ~/.local/share/gcm/.
  3. Check for the backdoor: inspect /usr/local/sbin/ping6 and remove it if it is a setuid shell.
  4. Rotate credentials. Treat any secret present on the machine as compromised, including SSH keys, cloud provider credentials, tokens in environment files, and browser-stored secrets.
  5. Review network logs for outbound connections to git.disroot.org, which confirm the loader executed.
Cleaning up one compromised gem is step one. Finding every risky dependency and misconfiguration across your pipelines is the harder part. Request a free GitHub Actions security audit and get a report of your organization's exposure.

How StepSecurity Protects Against This

Detect anomalous traffic with Harden-Runner

Harden-Runner monitors every outbound connection from your GitHub Actions runners and flags any call that is not in your workflow's established baseline. In audit mode it is what surfaced this entire kill chain, from the download to the persistence, in the process events. git.disroot.org is a legitimate service with valid uses, so the goal is not to blocklist a single domain. In block mode you allow only the endpoints your workflow actually needs, and every other destination is denied by default. That is what stops a loader from reaching an unexpected host, even one that looks benign.

Not sure which of your workflows are exposed? Run any workflow through the free GitHub Actions Advisor to see its security posture in seconds, no signup required.

Detect the artifacts on developer machines with Dev Machine Guard

The real target of SleeperGem is the developer laptop, which is exactly where Dev Machine Guard operates. Its suspicious files detection scans developer machines against content based rules and flags the SleeperGem loader source, the deploy.sh installer with its /usr/local/sbin/ping6 backdoor, and the systemd or cron persistence that points at the dropped daemon. Because CI evasion means these gems will run quietly on laptops and never in a pipeline, fleet wide file detection is the control that catches them.

Acknowledgment

This supply chain attack was first reported and named by the research team at Aikido Security. See their write up for their analysis: SleeperGem RubyGems supply chain attack.

References

Check if these gems are in your environment

StepSecurity checks your repositories, CI/CD pipelines, and developer machines for compromised gems like the ones in the SleeperGem campaign.

Explore Related Posts