CRA Desk
Every generate step

Generating an SBOM for Ruby (Bundler)

The step below writes a CycloneDX JSON software bill of materials (SBOM) in your own pipeline. The CRA Desk scan reads that file and turns it into a Cyber Resilience Act (CRA) readiness report - it never generates one for you.

Run in CI:

bundle install
npx @cyclonedx/cdxgen -t ruby -o sbom.json .
Produces:
sbom.json
Format:
CycloneDX JSON
Generator documentation

What the generator actually reads

The resolved bundle records platform-specific gems the way bundler locked them, so an SBOM generated on the deployment platform and one generated on a developer's laptop can legitimately differ. Generate it where you build the artefact you ship, not where you happen to run the command.

Versions and package URLs

Gems come out as pkg:gem purls matching OSV's RubyGems advisories. Gemfile groups are the trap: development and test gems are in the lockfile and therefore in the inventory unless the bundle was installed without them, so a report about a shipped application can end up carrying advisories against its own test harness.

The whole CI job

GitHub Actions

- uses: actions/checkout@v4
- run: bundle install
- run: npx @cyclonedx/cdxgen -t ruby -o sbom.json .
- uses: mmalinowski/cradesk-action@v1
  with:
    sbom-path: sbom.json

GitLab CI/CD

generate-sbom:
  script:
    - bundle install
    - npx @cyclonedx/cdxgen -t ruby -o sbom.json .

include:
  - component: gitlab.com/cradesk/scan/readiness@1
    inputs:
      sbom_path: sbom.json

Only the first step changes with your stack - the CRA Desk step after it is identical everywhere.

What goes wrong here

Run bundle install first: the inventory is read from the resolved bundle, not from the Gemfile. cdxgen is used here because the older cyclonedx-ruby gem defaults to XML, which the scan refuses.

Repositories with more than one thing in them

A gem that wraps native code is one component here, whatever it compiles underneath. That boundary is worth stating in the report: an advisory against the C library behind a gem is not a RubyGems advisory and no SBOM generated this way will surface it.

What CRA Desk does with the result

Components from this build carry pkg:gem package URLs, which the watch matches against OSV's RubyGems advisories when the SBOM arrives and again as new advisories land. Matching runs on every plan; e-mail alerts and the full match list are what a paid plan adds.

A generator that runs is not the same as coverage. Components with no purl, no version, or from an ecosystem outside the ones we watch are counted as gaps in every report rather than reported as clean.

Other stacks