VNX-RUBY-001 – Missing Gemfile.lock
Overview
This rule flags Ruby projects that have a Gemfile but no corresponding Gemfile.lock. The Gemfile.lock records the exact resolved version of every gem in the dependency graph — direct and transitive — at the time bundle install was last run. Without it, running bundle install on a fresh checkout resolves version constraints fresh from RubyGems.org, meaning two builds from the same source tree can install entirely different code depending on what was published between the two runs. This maps to CWE-829: Inclusion of Functionality from Untrusted Control Sphere.
Severity: High | CWE: CWE-829 – Inclusion of Functionality from Untrusted Control Sphere | OWASP ASVS: V14.2
Why This Matters
Without a Gemfile.lock, a dependency confusion attack, a compromised gem maintainer account, or a typosquat package on RubyGems.org can silently inject malicious code into your build. The substituted gem arrives as a legitimately resolved version that satisfies your floating constraint (e.g., gem 'rails', '~> 7.0'). Neither the developer nor the CI system sees anything unusual — the build completes successfully with malicious code included.
In CI/CD pipelines, where bundle install runs on every push, this attack is repeatable. A poisoned gem can steal environment variables, install a web shell, or silently modify application logic. MITRE ATT&CK technique T1195.001 (Supply Chain Compromise: Compromise Software Dependencies) documents this attack class.
The Gemfile.lock also enables bundle exec, which runs commands using exactly the gem versions recorded in the lock file, preventing version skew between local development and production environments. Bundler’s official rationale guide specifically states that the lock file is essential for reproducible builds.
What Gets Flagged
The rule fires when a directory is registered as containing Ruby source files but the file Gemfile.lock is absent from that same directory.
# FLAGGED: project directory has Gemfile but no Gemfile.lock
# $ ls
# Gemfile app/ lib/
# (Gemfile.lock is missing — gems are not pinned)
Remediation
- Generate the lock file. Run
bundle installin the directory containing yourGemfile. This resolves the full dependency graph and writesGemfile.lock.
bundle install
- Commit
Gemfile.lockto version control. The file must be present in source control so every developer, CI build, and deployment environment uses the identical set of resolved gem versions.
git add Gemfile.lock
git commit -m "chore: add Gemfile.lock to pin gem versions"
- Use
bundle execfor all commands. Running commands throughbundle execensures they run with exactly the gem versions recorded in the lock file, not whatever happens to be installed system-wide:
# SAFE: locked execution — uses exactly the versions in Gemfile.lock
bundle exec rails server
bundle exec rspec
bundle exec rake db:migrate
- Verify the lock file in CI before installing. Add a step that confirms the lock file is consistent with the current
Gemfilebefore proceeding with the build:
# SAFE: verify Gemfile.lock is up to date before installing
bundle check || bundle install
- For production deployments, install without development and test gems. This reduces the installed surface area and skips gems that are only needed for testing:
# SAFE: production install — locked versions, no dev/test gems
bundle install --without development test
Prevent accidental exclusion. Ensure
Gemfile.lockis not listed in.gitignore. For application repositories, the lock file should always be committed. For gem libraries (packages you publish to RubyGems), it is conventional to.gitignorethe lock file for the library itself — but this applies only to the published package, not to your library’s own CI test environment.Use
bundler-auditto check for known vulnerabilities. Once your lock file is committed, scan it regularly withbundler-audit, which queries the Ruby Advisory Database:
gem install bundler-audit
bundle-audit check --update
References
- CWE-829: Inclusion of Functionality from Untrusted Control Sphere
- OWASP ASVS v4 – V14.2 Dependency
- OWASP Software Component Verification Standard
- Bundler documentation – Gemfile.lock rationale
- Rails Security Guide
- bundler-audit
- MITRE ATT&CK T1195.001 – Supply Chain Compromise
- CAPEC-185: Malicious Software Download