CycloneDX SBOM to security findings
Focus: how a dependency-scanning cyclonedx report becomes security_findings.
The SBOM-specific part is that the findings are synthesized from the SBOM by
matching its components against Package Metadata DB (PMDB) advisories at store
time, not parsed from a scanner’s own vulnerability report. This is what “DS
findings are now ingested during the main ingestion process” refers to.
All paths are under ee/. Sbom::* and PackageMetadata::* models live on the
sec DB (gitlab_sec). The security_findings table lives on main/ci.
flowchart TD
A["CI job completes<br/>(cyclonedx and/or security-report artifact)"] --> B["Ci::JobSecurityScanCompletedEvent<br/>(a cyclonedx job counts as a security_job)"]
B --> C["Security::Scans::IngestReportsWorker → IngestReportsService"]
C --> D["Security::StoreScansService"]
subgraph SBOMP["SBOM path (new dependency scanning): findings synthesized from the SBOM"]
D -->|"Important: skipped if the same job also emitted<br/>gl-dependency-scanning-report.json"| E["store_sbom_scans → StoreGroupedSbomScansService → StoreSbomScanService"]
E --> F["JobArtifact#security_reports (cyclonedx branch)<br/>parse_sbom_reports → Parsers::Sbom::Cyclonedx"]
F --> G["VulnerabilityScanning::SecurityReportBuilder<br/>scan_sbom_report_occurrences (DS-source SBOMs only)"]
ADV[("pm_advisories / pm_affected_packages")] -.->|"match components<br/>(AdvisoryUtils + FindingBuilder)"| G
G --> H["Reports::Security::Report(:dependency_scanning)<br/>synthetic scanner SecurityScanner.fabricate<br/>→ MergeReportsService (dedup)"]
H --> I["StoreSbomFindingsService<br/>(keep valid, drop existing uuids)"]
end
subgraph LEG["gl-dependency-scanning-report.json path: findings parsed from the security report"]
D --> J["store_security_scans → StoreGroupedScansService → StoreScanService"]
J --> K["Parsers::Security::* → Reports::Security::*"]
K --> L["StoreFindingsService"]
end
I --> M[("security_findings")]
L --> M
M -.->|"generic promotion, all scanners<br/>(see security report ingestion overview)"| N["Security::Ingestion → vulnerabilities"]
Steps
- Trigger. A CI job that produced a cyclonedx (or security-report) artifact
completes and
Ci::BuildpublishesCi::JobSecurityScanCompletedEvent. A cyclonedx job counts as asecurity_job?, so it enters the same pipeline as analyzer reports. - Store stage.
Security::Scans::IngestReportsWorker→Security::StoreScansService, which forks intostore_sbom_scans(cyclonedx) andstore_security_scans(other reports). Important: the cyclonedx SBOM finding-synthesis is skipped when the same job also emitted agl-dependency-scanning-report.json(job-scoped, matched byjob_id), so the same dependency-scanning findings are not ingested twice. The skip applies only to this finding-synthesis path; the separatesbom_*occurrence ingestion still processes the cyclonedx report. See work item 546429. - SBOM path, build the report. For a cyclonedx artifact,
JobArtifact#security_reportsparses the SBOM (Parsers::Sbom::Cyclonedx) and hands it toVulnerabilityScanning::SecurityReportBuilder. - Advisory matching (the SBOM-specific step).
SecurityReportBuilder#scan_sbom_report_occurrencesmatches SBOM components against PMDB advisories (pm_advisories/pm_affected_packages) usingAdvisoryUtils+FindingBuilder, producing aReports::Security::Report(:dependency_scanning)with a synthetic scanner (SecurityScanner.fabricate). Only dependency-scanning-source SBOMs (with an input file path) are processed;MergeReportsServicededups within the report. - Persist findings.
StoreSbomScanServicecallsStoreSbomFindingsService, which keeps valid findings not already present and writessecurity_findings. - The
gl-dependency-scanning-report.jsonpath (the overlap). A dependency-scanning analyzer that emits its own security report parses viaParsers::Security::*and writes the samesecurity_findingsthrough the genericStoreFindingsService(the same path other analyzers use). - What happens next (out of focus here).
security_findingsare promoted tovulnerabilitiesby the genericSecurity::Ingestionpath, identical for every scanner; see Security report ingestion overview. Separately, the cyclonedx report is ingested again into thesbom_*occurrence tables (the dependency inventory) and linked back to these vulnerabilities, which is a distinct flow (see the SBOM occurrence ingestion diagram).
Key point: the SBOM-specific logic is entirely in cyclonedx →
security_findings (advisory matching). Findings → vulnerabilities is generic, so
it is intentionally not redrawn here.
Related
- Security report ingestion overview
- The generic findings → vulnerabilities promotion.
- SBOM occurrence ingestion (dependency inventory + vulnerability linkage), the companion diagram.
- Continuous Vulnerability Scanning (CVS), the off-pipeline sibling of the advisory matching shown here.