Safeguard
Software Supply Chain•

How should you manage Ruby gem dependencies safely?

Manage Ruby gems with a committed Gemfile.lock, pessimistic version ranges, checksums, a release cooldown, scoped sources and an advisory audit in CI.

Safeguard Security Team
4 min read

Manage Ruby gems safely by committing Gemfile.lock, constraining versions with the pessimistic operator, verifying checksums, pinning private gems to a scoped source, delaying brand-new releases with a cooldown, and running an advisory audit in CI. The Gemfile states intent. The lockfile records what you actually run.

What is the difference between the Gemfile and the lockfile?

The Gemfile lists the gems you want and the version ranges you accept. Bundler resolves those ranges to exact versions, including every transitive dependency, and writes the result to Gemfile.lock. Two machines with the same lockfile install the same gems.

For applications, commit the lockfile. Without it, a build on Tuesday can pull different code than a build on Monday with no change in your repository. That is the opening a malicious release needs.

How should you write version constraints?

The RubyGems Gemfile guide documents the pessimistic operator. It sets both a lower and an upper bound: ~> 2.0.3 means at least 2.0.3 and below 2.1, while ~> 2.1 means at least 2.1 and below 3.0.

Use it. A bare gem "rails" accepts any version on the next update. A hard pin like = 7.1.3 blocks security patches until you edit the file. The pessimistic form lets patch releases flow while keeping you off a major version jump you have not tested.

Can Bundler verify what it downloads?

Yes. According to the RubyGems security guide, Bundler records a CHECKSUMS section in newly generated lockfiles and verifies each gem against its checksum during installation, so a gem tampered with after the lockfile was created fails to install. For an older lockfile, the bundle lock command with its add-checksums option adds the section.

Checksums do not tell you a gem is safe. They tell you it is the same file you recorded earlier. The decision to trust it still happened when you first added or updated it.

What is a dependency cooldown?

The same guide describes a cooldown that excludes versions newer than a set number of days from resolution. The reasoning given is that most malicious releases are detected and yanked within days of publication, so waiting a week avoids many of them. You can enable it with bundle config set cooldown 7, and exempt a trusted internal source with a value of zero.

The trade-off is plain. A cooldown also delays a real security fix. Teams usually keep an override path for urgent patches, reviewed by a person.

How do you keep private gems from being hijacked?

If you host internal gems, declare them inside a source block so Bundler installs them only from your private server. The RubyGems security guide describes this approach. The guide adds a caveat: a source declared in a block can still be a candidate for gems without an explicit source, so assign every internal gem to its source. Otherwise a public gem with the same name as your internal one can win the resolution, which is the classic dependency confusion mistake.

What should you do about your own gems?

If you publish, require multi-factor authentication for owners and use scoped API keys rather than one all-powerful key. The RubyGems security guide covers both.

How to check or apply this

  1. Commit Gemfile.lock for every application, and review lockfile changes in pull requests like code.
  2. Replace bare gem lines and hard pins with pessimistic ranges.
  3. Add checksums to existing lockfiles and confirm CI fails on a mismatch.
  4. Put private gems in source blocks.
  5. Set a cooldown of a few days and document the urgent-patch exception.
  6. Run bundle-audit check in CI, with its advisory database updated first. The bundler-audit project checks your lockfile against the ruby-advisory-db.
  7. Install in CI in a mode that fails if the Gemfile and lockfile disagree.
  8. Remove gems you no longer require. Fewer dependencies means fewer advisories.

Where does Safeguard fit?

Safeguard produces a dependency inventory from lockfiles and uses reachability analysis to show whether a vulnerable gem's affected code is actually called by your application. That helps order the audit results from step 6. The free Gold scan at gold.safeguard.sh/scan checks up to 100 dependencies in the browser.

Quick check

Should libraries commit Gemfile.lock?

Applications should. For a library, practice differs, since consumers resolve their own versions. Check the RubyGems guidance for your case, and test against a range of dependency versions in CI.

Does bundle-audit catch malicious gems?

Only those already recorded in an advisory database. It is a vulnerability check, not malware detection. Use cooldowns and review for the rest.

Sources

Last reviewed: 18 October 2026.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.