Safeguard
Supply Chain•

How do you stop dependency confusion in a Gemfile with two sources?

With an internal gem server plus rubygems.org, put each internal gem in a source block and give every gem an explicit source. Steps to review a Gemfile.

Safeguard Security Team
3 min read

Put each internal gem inside a source block for its own server, so Bundler installs it from there. The RubyGems security guide also says to give every gem in the Gemfile an explicit source, because a source declared in a block still counts as a candidate for gems without one.

The risk

If your company runs an internal gem server alongside rubygems.org, a public gem published under the same name as an internal gem could be substituted for it. The RubyGems security page describes exactly this. The attacker does not need to break into anything. They only need to publish the name you forgot to claim.

The pattern

source "https://rubygems.org" do
  gem "rails"
  gem "pg"
end

source "https://gems.internal.example" do
  gem "acme-billing"
  gem "acme-auth"
end

Every gem sits inside a block. No gem is left to resolve from whichever source answers first.

Common setups and their risk

SetupRiskBetter approach
One global source line, internal gems listed without blocksName could resolve from the public sourceMove each internal gem into a block
Internal source in a block, public gems outside any blockBlock sources remain candidates for unscoped gemsWrap public gems in their own block
Git or path sources for internal gemsLow, source is explicitKeep, and pin by revision

Steps to review a Gemfile

  1. List every gem name that is internal to your company.
  2. Check each one is inside a block for the internal server.
  3. Check every other gem has an explicit source too.
  4. Register your internal gem names on rubygems.org if you can, or at least check that they are not already taken. Reserved names are covered in our note on RubyGems reserved namespaces.
  5. Re-run install and read the Gemfile.lock diff. Look at the remote lines for each source.
  6. Add a CI check that fails if a gem lacks an explicit source.

How Gemfile.lock helps

The lock file records which source each gem came from. After you restructure the Gemfile, the lock file diff is your evidence that internal gems now come from the internal server. Keep the lock file committed and run installs with frozen mode, as in our guide to frozen and deployment mode.

Try it yourself

Click through it at your own pace, or open it full screen. Check where each package in the inventory was sourced from.

Where Safeguard fits

Safeguard's policies and gates can check dependency changes in a pull request before merge. A free scan shows what it finds today.

Quick check

Is one source block enough?

No. Gems outside any block can still resolve from a block source, so give every gem an explicit source.

Does this apply to Composer too?

The idea is the same. Composer repositories can be limited with the only and exclude options, covered in our Composer guide.

Sources

Last reviewed: 19 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.