Back to posts
Post

Automating SBOM and License Compliance in GitLab CI with Trivy

Learn how to use Trivy in GitLab CI to generate SBOMs and scan for HIGH/CRITICAL CVEs and license issues automatically.

DevopsTrivyGitLab CISBOMlicense compliancevulnerability scanning

In my environment, I’ve been using Trivy for a while to scan container images and filesystems for vulnerabilities. Recently, I needed to extend that to SBOM generation and license compliance checks as part of our GitLab CI pipeline. The goal was simple: fail the pipeline if any HIGH or CRITICAL CVE is found, or if incompatible licenses are detected. Trivy makes this straightforward with its --format sbom and --severity flags.

Setting up Trivy in GitLab CI

First, I make sure Trivy is available in the CI image. I use the official Aquasecurity/trivy image, which is lightweight and updated frequently. In my .gitlab-ci.yml, I define a job that runs after the build stage:

trivy-sbom-scan:
  image: aquasec/trivy:latest
  stage: test
  script:
    - trivy fs --format sbom --output sbom.spdx .
    - trivy fs --severity HIGH,CRITICAL --exit-code 1 .
  artifacts:
    paths:
      - sbom.spdx
    expire_in: 1 week

The first command generates an SBOM in SPDX format and saves it as an artifact. The second scans the filesystem for vulnerabilities with severity HIGH or CRITICAL and exits with code 1 if any are found, which fails the job.

Adding License Compliance Checks

Trivy also scans for license issues out of the box. I wanted to block certain licenses like GPL-3.0 or AGPL in our proprietary builds. To do this, I added a license policy file:

# trivy-license-policy.yaml
license:
  allowed:
    - MIT
    - Apache-2.0
    - BSD-3-Clause
  forbidden:
    - GPL-3.0
    - AGPL-3.0
    - LGPL-3.0

Then I updated the CI job to use this policy:

    - trivy fs --severity HIGH,CRITICAL --license-policy trivy-license-policy.yaml --exit-code 1 .

If Trivy finds a forbidden license, it will fail the scan and the pipeline stops. This gives us early feedback before anything gets pushed to a registry or deployed.

Viewing Results and Troubleshooting

Sometimes the SBOM generation fails if Trivy can’t access certain directories due to permissions. I ran into this when scanning a monorepo with restricted submodules. The fix was to ensure the CI runner has read access or to explicitly exclude problematic paths:

    - trivy fs --format sbom --output sbom.spdx --exclude-dir .git,node_modules .

Also, Trivy’s SPDX output can be large. I archive it as an artifact so auditors or compliance teams can review it later. In one case, as I mentioned before in my post about encrypting backups with Restic, we needed to retain SBOMs for regulatory reasons — having them in CI artifacts made that easier.

Why This Approach Works

Using Trivy this way keeps security and compliance checks close to the source. Instead of relying on external scans after push, we catch issues early. The --severity HIGH,CRITICAL focus reduces noise — we’re not failing on low-risk issues. And because Trivy updates its vulnerability database frequently, we stay current without managing feeds manually.

If you’re already using Trivy for image scanning, extending it to FS-based SBOM and license checks in GitLab CI is a natural next step. It’s fast, reliable, and integrates smoothly into existing pipelines.


Cover image: www.Pixel.la Free Stock Photos · CC0 (Wikimedia Commons / kamu malı) · https://commons.wikimedia.org/wiki/File:Fruits-grocery-bananas-market_(24300521606).jpg