New dependency scanning, the SBOM scan API
Focus: how the new dependency-scanning analyzer turns a CycloneDX SBOM into a
gl-dependency-scanning-report.json by calling the GitLab SBOM Vulnerability Scan
API. The API matches the SBOM against Package Metadata DB (PMDB) advisories
server-side and returns vulnerability data as a result file. This flow is
ephemeral and analyzer-facing: it does not create security_findings or
vulnerabilities; those are produced later when the report is ingested (see
CycloneDX to security findings).
Gated by the dependency_scanning_sbom_scan_api feature flag; endpoints use
job-token auth. All paths are under ee/.
flowchart TD
A["CI job: new dependency-scanning analyzer<br/>generates a CycloneDX SBOM"] --> C["POST /jobs/:id/sbom_scans<br/>(upload SBOM + optional sbom_digest)"]
%% preceded by POST /jobs/:id/sbom_scans/authorize (workhorse direct-upload authorize)
C --> D["CreateSbomScanService#execute<br/>create ephemeral SbomScan; return advisory_db_state"]
D --> F["ProcessSbomScanWorker"]
F --> H["ProcessSbomScanService (async)"]
subgraph SCAN["async scan — does NOT write to Vulnerability Management"]
H --> I["parse SBOM (Parsers::Sbom::Cyclonedx)<br/>validate: dependency_scanning source + GitLab taxonomy"]
I --> J["VulnerabilityScanning::SecurityReportBuilder<br/>match components vs advisories (AdvisoryUtils + FindingBuilder)"]
ADV[("pm_advisories / pm_affected_packages")] -.->|"advisory match"| J
J --> K["Reports::Security::Report(:dependency_scanning)"]
K --> L["save_result → result_file (JSON) on the ephemeral SbomScan"]
end
A -.->|"optional: reuse by digest<br/>POST /sbom_scans/:sbom_digest (SbomScanResultCachingService)"| M
L --> M["analyzer polls GET /jobs/:id/sbom_scans/:sbom_scan_id"]
M --> N["analyzer writes gl-dependency-scanning-report.json"]
N -.->|"later ingested by the pipeline"| O["gl-dependency-scanning-report.json path<br/>(see CycloneDX to security findings)"]
Steps
- Analyzer generates the SBOM. The new dependency-scanning analyzer runs in a CI job and produces a CycloneDX SBOM following the GitLab CycloneDX property taxonomy for dependency scanning.
- Authorize the upload. The analyzer calls
POST /jobs/:id/sbom_scans/authorize, which usesCreateSbomScanService#authorizeto return workhorse direct-upload headers (rate limited bydependency_scanning_sbom_scan_api_upload). - Upload the SBOM.
POST /jobs/:id/sbom_scansuploads the file.CreateSbomScanService#executecreates an ephemeralSbomScanrecord and enqueues processing viaProcessSbomScanWorker. The response includes theadvisory_db_state(PMDB advisory sync status) so the analyzer knows how fresh the advisory data is. - Async scan.
ProcessSbomScanServiceparses the SBOM (Parsers::Sbom::Cyclonedx), validates it is adependency_scanning-source cyclonedx, then runsVulnerabilityScanning::SecurityReportBuilderto match components against PMDB advisories (pm_advisories/pm_affected_packages) usingAdvisoryUtils+FindingBuilder. This is the same builder that the CycloneDX to security findings workflow uses, but here the output goes to a file, not to the database. - Save the result.
save_resultstores the resultingReports::Security::Report(:dependency_scanning)as a JSONresult_fileattached to the ephemeralSbomScan. Nosecurity_findingsorvulnerabilitiesare written. - Poll and download. The analyzer polls
GET /jobs/:id/sbom_scans/:sbom_scan_id:202while in progress,200with theresult_filewhen finished,410on failure. - Optional, reuse by digest. Before (or instead of) uploading, the analyzer
can call
POST /jobs/:id/sbom_scans/:sbom_digest(SbomScanResultCachingService) to reuse an existing result for an identical SBOM digest and purl types, skipping a re-scan. - Output the report. The analyzer writes the downloaded result as
gl-dependency-scanning-report.json, the standard dependency-scanning report artifact.
This is the overlap with the
CycloneDX to security findings workflow. The shared piece
is the logic that builds a vulnerability report from cyclonedx SBOM data,
VulnerabilityScanning::SecurityReportBuilder (with AdvisoryUtils and FindingBuilder). Both
workflows run the same builder to match SBOM components against PMDB advisories and produce a
Reports::Security::Report(:dependency_scanning). They differ only in what happens to that
report: this API saves it to a result_file, while that workflow ingests it into
security_findings.
How this connects: the report produced here is the input to the
CycloneDX to security findings workflow’s
gl-dependency-scanning-report.json path, where it is ingested into
security_findings. Because the analyzer already produced that report via this
API, when the same job also uploads the cyclonedx as a pipeline artifact, the
store stage skips the cyclonedx finding-synthesis to avoid double ingestion.
Related
- CycloneDX to security findings - ingests the
gl-dependency-scanning-report.jsonthis API produces. - GitLab CycloneDX property taxonomy - the SBOM format this API validates against.
- Continuous Vulnerability Scanning (CVS) - the off-pipeline flow that runs the same advisory matching over stored SBOM data.