CRA Desk
Every generate step

Generating an SBOM for Python (pip / Poetry)

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:

pip install -r requirements.txt
pip install cyclonedx-bom
cyclonedx-py environment -o sbom.json
Produces:
sbom.json
Format:
CycloneDX JSON
Generator documentation

What the generator actually reads

Whatever shares that interpreter shares the inventory - cyclonedx-bom itself included, since the recipe above installs it into the same place. A separate virtualenv for the generator, or a build that installs the product's requirements and nothing else, is what keeps your tooling out of your product's component list.

Versions and package URLs

Everything installed carries a concrete version, so pkg:pypi purls come out pinned - the strongest starting point of any ecosystem on this list. The name in the purl is the distribution name from the index, which is not always the name you import: a component you cannot find in the report is usually filed under the name pip knows it by.

The whole CI job

GitHub Actions

- uses: actions/checkout@v4
- run: pip install -r requirements.txt
- run: pip install cyclonedx-bom
- run: cyclonedx-py environment -o sbom.json
- uses: mmalinowski/cradesk-action@v1
  with:
    sbom-path: sbom.json

GitLab CI/CD

generate-sbom:
  script:
    - pip install -r requirements.txt
    - pip install cyclonedx-bom
    - cyclonedx-py environment -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

cyclonedx-py environment describes the installed environment, not requirements.txt, so dependencies have to be installed first. For a lockfile instead, use cyclonedx-py poetry or cyclonedx-py requirements.

Repositories with more than one thing in them

A repository with several services usually means several environments. Generate one SBOM per environment and scan each of them rather than installing everything into one interpreter - a merged environment describes a product carrying dependencies it does not actually ship.

What CRA Desk does with the result

Components from this build carry pkg:pypi package URLs, which the watch matches against OSV's PyPI 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