supply-chain security rubygems dependency-management malware

Dormant maintainer accounts are a supply-chain risk

SleeperGem shows how old, trusted package-maintainer accounts can become a quiet path from normal dependency updates to malware delivery.

boring.tools team

boring.tools team

The team behind boring.tools.

5 min read
Dormant maintainer accounts are a supply-chain risk

A package does not need to be new to be risky. Sometimes the most dangerous release comes from a project everyone stopped thinking about years ago.

That is the useful lesson from Aikido’s SleeperGem report, which describes a RubyGems supply-chain attack built around dormant maintainer accounts and trusted gems. The initial package, git_credential_manager, looked like a small utility. Under the surface, Aikido says it downloaded binaries from a public Forgejo instance, disabled TLS certificate verification, and executed the payload on developer machines.

The important part is not only that RubyGems was targeted. It is that old trust was reused. A maintainer account that had been quiet for years suddenly became a delivery path again.

What happened

Aikido reports that git_credential_manager published four versions in rapid succession. The package downloaded binaries from git.disroot[.]org/git-ecosystem/, a public Forgejo host where the attacker had registered a convincing-looking git-ecosystem username.

According to the report, the early version already behaved like a dropper: it built a URL to the hardcoded host, fetched a binary with certificate verification disabled, and handed the downloaded file to /bin/sh on Unix-like systems or PowerShell on Windows. A later release made the Unix execution quieter by piping output to /dev/null.

The most important change came next. Aikido says version 2.8.2 wired the installer into the gem’s load path, so merely requiring git_credential_manager could trigger the installation flow. Version 2.8.3 then made the payload live. That moved the risk from “someone ran this tool” to “application code loaded a dependency that now performs unexpected work.”

The campaign also tried to avoid CI environments. Aikido found logic that checked for roughly 30 environment variables associated with CI systems such as GitHub Actions, GitLab CI, CircleCI, Travis, Jenkins, and Vercel, then skipped installation if those variables were present. That points the attack toward developer workstations rather than disposable build runners.

Why dormant accounts change the risk model

Most dependency review focuses on obvious changes:

  • a new package enters the graph,
  • a maintainer publishes an unusual major version,
  • a package adds an install script,
  • a CVE appears for a known dependency,
  • a registry or scanner flags a malicious version.

Dormant maintainer-account compromise is harder to spot because it starts from existing trust. A package may already be approved. A maintainer may already have the right to publish. A gem may have sat harmlessly in a dependency graph for years.

Aikido says it found more than one affected maintainer account. One package, Dendreo, first published in 2017, received fresh releases around the same time and added git_credential_manager as a dependency. Another affected project, fastlane-plugin-run_tests_firebase_testlab, had more than 574,000 total downloads and belonged to a different maintainer.

That pattern matters. If an attacker can reactivate old accounts and push a new dependency into trusted projects, defenders cannot treat “we already use this package” as a complete approval signal. The package name may be familiar while the current release path is not.

What teams should check

If you use RubyGems in application or build tooling, start by looking for the affected packages and versions named in the report:

  • git_credential_manager versions 2.8.0 through 2.8.3,
  • recent Dendreo releases that added git_credential_manager,
  • recent fastlane-plugin-run_tests_firebase_testlab releases around the same window.

Then widen the search from package names to behavior:

  • new transitive dependencies added by old packages,
  • releases from maintainer accounts that had been inactive for years,
  • package updates that download and execute external binaries,
  • code paths that disable TLS verification,
  • payloads hosted on generic Git hosting or file-sharing infrastructure,
  • workstation-only behavior that avoids CI environment variables.

Lockfiles and SBOMs are useful here because they give you a record of exactly which versions entered which projects. Registry proxy logs and package-manager caches are useful for a different question: which machines actually pulled the package?

Those two questions are different. An SBOM can tell you that a build included a package. Install logs can tell you whether a developer laptop or CI runner fetched a version during the exposure window. Incident response usually needs both.

Why this is not just a RubyGems story

RubyGems may be the ecosystem in this incident, but the control problem is broader.

Every package registry has some version of the same trust chain:

  1. maintainers or automation accounts can publish,
  2. downstream users trust package names and version ranges,
  3. dependency managers resolve updates automatically,
  4. developer machines and CI systems execute build or runtime code with useful credentials nearby.

When a maintainer account goes dormant, the risk does not disappear. In some ways it becomes easier to miss. There may be no active community watching changes, no recent release cadence to compare against, and no human memory of what a normal update should look like.

That makes “maintainer freshness” and “release surprise” useful signals. A dependency that suddenly wakes up after six years should be reviewed differently from a dependency with an active, predictable release pattern.

What to do next

The practical response is not to panic about every old dependency. It is to make old trust visible again.

A good baseline looks like this:

  • Track dependency versions in SBOMs for every release artifact.
  • Keep package-manager and registry-proxy logs long enough to answer who installed what.
  • Alert on new releases from dependencies that have been dormant for a long time.
  • Review newly introduced transitive dependencies, especially when added by old packages.
  • Treat external binary download-and-execute behavior as high risk.
  • Prefer dependency policies that can pause or review newly published versions before they reach workstations and CI.
  • Rotate credentials from a clean machine if a developer workstation may have executed a malicious package.

The SleeperGem pattern is uncomfortable because it uses the quietest part of the dependency graph: packages and accounts that teams stopped actively thinking about. That is exactly why inventory matters. You cannot review every line of every dependency every day, but you can keep enough history to notice when an old dependency starts behaving like a new risk.


boring.tools helps teams connect dependency inventory, SBOMs, and package-install visibility to real projects. When an old trusted package suddenly changes, that context is what turns a vague advisory into a scoped response.