Skip to content

Bundler Package Scanner

The Bundler package scanner automatically detects and extracts all third-party dependencies declared in your Ruby projects that use Bundler as their package manager.

What It Does

Default file: Gemfile

When you enable the Bundler scanner during SBOM creation, CAST SBOM Manager will:

  • Find all Bundler manifest files (Gemfile and Gemfile.lock) throughout your codebase
  • Extract declared dependencies with their version constraints
  • Parse version specifiers to identify exact pinned versions
  • Process lock files to capture exact resolved versions
  • Handle Git-based dependencies from GitHub and GitLab repositories

Gemfile vs. Gemfile.lock

The Bundler scanner processes two types of files, each serving a different purpose:

  • Gemfile - Declares dependencies with flexible version constraints (e.g., ~> 7.1)
  • Gemfile.lock - Contains exact resolved versions (e.g., 7.1.3.2)

If both are present, Gemfile.lock provides more precise version information for your SBOM. The scanner processes both files independently, so you'll see entries from both if they exist in your project.

What Gets Detected

The Bundler scanner identifies dependencies from two types of files:

Gemfile

From Gemfile files, the scanner extracts:

  • Gem declarations using the gem directive
  • Package names and their version constraints
  • Exact versions when specified with = operator
  • Git-based dependencies from GitHub or GitLab

Supported formats:

  • Simple gem names: gem 'rake'
  • With version constraints: gem 'rails', '~> 7.1'
  • Multiple constraints: gem "rack", "~> 2.2", ">= 2.2.8"
  • Exact versions: gem 'puma', '= 6.4.0'
  • With parentheses: gem('nokogiri', '~> 1.13')
  • Git sources: gem 'my_gem', git: 'https://github.com/org/repo'

Version handling:

  • Equality constraints with exact versions (e.g., '= 6.4.0' or '6.4.0') are captured as pinned versions
  • Version ranges and operators (e.g., '~> 7.1', '>= 2.0, < 3.0') are recognized but no specific version is pinned
  • Multiple constraints (e.g., gem "rack", "~> 2.2", ">= 2.2.8") are combined and parsed together, typically resulting in no pinned version since they form a range
  • Dependencies with version constraints are still recorded, allowing you to see which gems are declared even when their exact version will be resolved by Bundler

Git dependencies:

  • When a gem specifies a GitHub or GitLab URL, the scanner extracts the organization/repository name as the component name
  • The dependency name becomes org/repo instead of the gem name
  • Both HTTPS and SSH Git URLs are supported

Gemfile.lock

From Gemfile.lock files, the scanner extracts:

  • Direct dependencies only - gems listed at the first level under specs:
  • Exact locked versions for each direct dependency
  • Gems from all sources (RubyGems, Git repositories, local paths)
  • Platform-specific versions when present

Note: Transitive dependencies (nested dependencies of your direct dependencies) are not captured from Gemfile.lock. Only the gems you directly depend on are extracted.

How It Works

Gemfile Processing

When scanning a Gemfile, the scanner:

  1. Reads the file line by line
  2. Strips comments (anything after #)
  3. Identifies gem declarations using pattern matching
  4. For each gem declaration:
    • Extracts the gem name from the first quoted string
    • Looks for Git URLs in subsequent options (git:, github:)
    • If a GitHub or GitLab URL is found, uses org/repo as the name
    • Collects all quoted strings that look like version constraints
    • Combines multiple version constraints with commas
    • Parses using Ruby-style version specifier parsing
    • If the constraint represents an exact equality (e.g., '6.4.0' or '= 6.4.0'), stores it as the pinned version

Gemfile.lock Processing

The Gemfile.lock file has a specific format with sections like:

GEM
  remote: https://rubygems.org/
  specs:
    actionpack (6.1.7.7)
      activesupport (= 6.1.7.7)
    rake (13.2.1)

The scanner processes this format by:

  1. Reading the file line by line
  2. Tracking when it enters a specs: section
  3. Monitoring indentation levels to identify direct dependencies vs. transitive dependencies
  4. Extracting only direct dependency entries that appear exactly 2 spaces deeper than the specs: line
  5. Parsing the gem name and version from each line using the pattern: name (version) (lock files always contain concrete versions)
  6. Parsing and validating the version using Ruby-style version parsing
  7. Skipping transitive dependency lines (4+ spaces deeper than specs:)

Ruby Version Specifier Parsing

The scanner recognizes Ruby/Bundler's version specifier syntax and extracts exact versions when specified. When a version constraint represents an equality (a single exact version), it is captured as a pinned version in the SBOM. All other constraints (ranges, operators like ~>, compound expressions) result in the gem being recorded without a pinned version.

What It Doesn't Detect

The Bundler scanner focuses on gems managed by Bundler. It does not detect:

  • System gems - Gems installed globally outside of Bundler
  • Ruby standard library - Built-in Ruby libraries that aren't gems
  • Transitive dependencies - Indirect dependencies (dependencies of your dependencies) are not captured
  • Manually copied Ruby libraries not declared in Gemfile
  • Embedded or copy-pasted code from open source projects

For complete open source detection including undeclared components and copied code, enable the OSS Knowledge Base scanning option in the Scanners step, which analyzes actual file content to identify all open source usage.