Trivy limitations: Critical packages undetected in SBOM generation

Summary

When GitLab's Trivy generates SBOMs for container scanning, it fails to detect key software components, causing Xeol to miss critical end-of-life packages in the resulting EOL reports

Steps to reproduce

I tested two container images, generating SBOMs using both:

  1. GitLab's default container scanner (Trivy)
  2. Syft

Both SBOMs were then scanned with Xeol to detect EOL packages.

Test 1: Node:16 image

Link to image -> https://hub.docker.com/layers/library/node/16/images/sha256-c94b82f9827cab6e421b350965a9ef11b25b13ffbd1030536203d541f55dcbe2

Test 2: Python:3.7.17-slim-bullseye image

To Reproduce this:

  • Run pipeline with Python 3.7.17 image
    • GitLab's Trivy generates SBOM
    • Xeol scans and finds 0 EOL packages
  • Same image with Syft
    • Syft generates SBOM
    • Xeol scans it and finds Python 3.7.17 EOL
  • Repeat with Node:16 image
    • Trivy misses Node.js 16.20.2
    • Syft detects it correctly

See a similar github discussion on this here.

.gitlab-ci.yml
include:
  - template: Jobs/Container-Scanning.gitlab-ci.yml

stages:
  - c_scan
  - eol-scan
  - syft_scan

# GitLab's default container scanning with Trivy
container_scanning:
  stage: c_scan
  variables:
    CS_IMAGE: "python:3.7.17-slim-bullseye@sha256:603879aeff06df23f0d392a19f7ce02aa85e14e6b4d25fd9647b116e0cb93467"
    # Alternative test image:
    # CS_IMAGE: "node:16@sha256:c94b82f9827cab6e421b350965a9ef11b25b13ffbd1030536203d541f55dcbe2"
    CS_REPORT_OS_EOL: "true"
    CS_DISABLE_SBOM: "false"
    TRIVY_SBOM: "true"
  artifacts:
    reports:
      container_scanning: gl-container-scanning-report.json
    paths:
     - gl-container-scanning-report.json
     - gl-sbom-report.cdx.json
    expire_in: 1 week

# Xeol scan of Trivy-generated SBOM
xeol_eol_scan:
  stage: eol-scan
  image: 
    name: alpine:3.19
    entrypoint: [""]
  before_script:
    # Install dependencies
    - apk add --no-cache curl bash jq ca-certificates
    # Install Xeol
    - |
      echo "Installing Xeol..."
      curl -sSfL https://raw.githubusercontent.com/xeol-io/xeol/main/install.sh | sh -s -- -b /usr/local/bin
      xeol version
  script:
    - echo "Available files:"
    - ls -la
    # Find SBOM file
    - |
      if [ -f "gl-sbom-report.cdx.json" ]; then
        echo "Found GitLab SBOM file"
        SBOM_FILE="gl-sbom-report.cdx.json"
      else
        echo "SBOM file not found. Checking for other SBOM formats..."
        
        find . -name "*.cdx.json" -o -name "*sbom*.json" | head -5
        exit 1
      fi
    # Run Xeol EOL scan
    - echo "Running Xeol EOL scan on $SBOM_FILE"
    - xeol ${SBOM_FILE} -o json > trivy-xeol-eol-report.json
  artifacts:
    paths:
      - trivy-xeol-eol-report.json
    expire_in: 1 week
  allow_failure: true

# Syft SBOM generation and Xeol scan
syft-container_scanning:
  stage: syft_scan
  image: docker:25.0-cli
  services:
    - docker:25.0-dind
  variables:
    DOCKER_HOST: "tcp://docker:2375"
    DOCKER_TLS_CERTDIR: ""
    CS_IMAGE: "python:3.7.17-slim-bullseye@sha256:603879aeff06df23f0d392a19f7ce02aa85e14e6b4d25fd9647b116e0cb93467"
    # Alternative test image:
    # CS_IMAGE: "node:16@sha256:c94b82f9827cab6e421b350965a9ef11b25b13ffbd1030536203d541f55dcbe2"
    CS_REPORT_OS_EOL: "true"
  before_script:
    - apk add --no-cache curl bash
    - curl -sSfL https://raw.githubusercontent.com/anchore/syft/main/install.sh | sh -s -- -b /usr/local/bin
    - curl -sSfL https://raw.githubusercontent.com/xeol-io/xeol/main/install.sh | sh -s -- -b /usr/local/bin
  script:
    # Pull public Docker Hub image
    - docker pull "$CS_IMAGE"
    # Generate SBOM with Syft 
    - syft "docker:$CS_IMAGE" -o json > sbom.json
    # Run Xeol against SBOM
    - xeol sbom.json -o json > xeol-report.json
    - mkdir -p gl-container-scanning-report
    - cp xeol-report.json gl-container-scanning-report/syft-xeol-eol-report.json
  artifacts:
    paths:
      - gl-container-scanning-report/syft-xeol-eol-report.json
    expire_in: 1 week

Actual behavior

Trivy's SBOM generation misses key software components as listed above

Expected behavior

The SBOM generated by Gitlab's container scanner should include all software components in the container

Relevant logs and/or screenshots

job log
Add the job log

Environment description

config.toml contents
Add your configuration here

Used GitLab Runner version

Running with gitlab-runner 18.4.0~pre.115.gb2218bab (b2218bab)

on blue-4.saas-linux-small-amd64.runners-manager.gitlab.com/default J2nyww-sK, system ID: s_cf1798852952

Possible fixes