SBOMs, Dependency Lists, Vulnerability Management, Remediation, and Security Dashboards: Concepts, Architecture, and Mental Model
Build a precise mental model of SBOM inventory, GitLab Dependency Lists, vulnerability records, triage states, remediation evidence, dashboards, and audit history.
Learning objectives
- Separate an SBOM component inventory from vulnerability findings and from GitLab vulnerability records.
- Explain how GitLab Dependency List interpretation differs from retaining the raw CycloneDX artifact.
- Use the current vulnerability lifecycle precisely: Needs triage, Confirmed, Dismissed, Resolved, and the distinct “No longer detected” activity state.
- Identify project/group/dashboard scope and the role/tier boundaries that control hosted triage views.
- Connect component purl/version, pipeline SHA, artifact hash, remediation MR, and rescanning evidence into one auditable chain.
artifacts:reports:cyclonedx ingestion, Dependency List,
Dependency Scanning, Vulnerability Report/details, Security
Dashboards, Security Inventory, vulnerability exports/APIs, and hosted
vulnerability-management lifecycle are currently
Ultimate across GitLab.com, Self-Managed, and
Dedicated. Therefore every mandatory lab in this chapter has a
Free-compatible fixture path; Ultimate steps are clearly
optional/read-only. GitLab 19.3 is the current monthly release,
published 2026-08-20.
1. The practical problem: scanner output is only the beginning
Chapter 25 separated scanner execution from security conclusions. Chapter 26 starts after that scan: dozens or thousands of component and finding records now need ownership, prioritization, remediation, exception handling, and durable evidence. A scanner report by itself does not tell you whether the affected package was actually in the released build, whether the finding was reviewed, whether an upgrade broke compatibility, or whether “disappeared from the next scan” means “fixed.”
The operational question is therefore not “Did a scanner run?” but Can we trace a specific component identity from build inventory to finding to decision to remediation and back to independently verified build evidence?
2. Inventory, finding, record, decision, evidence
Use four layers. An SBOM is machine-readable inventory. A finding is scanner evidence that maps a component or code location to a suspected weakness. A GitLab vulnerability record is hosted lifecycle state around a finding. A disposition is the governed decision: confirm, dismiss with a reason, or resolve after verifying remediation. Keeping these layers distinct prevents dashboards from becoming substitutes for build identity.
flowchart TD A[Source + lockfile] --> B[Pipeline / trusted runner] B --> C[CycloneDX SBOM artifact] C --> D[Component inventory] C --> E[Dependency scanner / advisory match] E --> F[Vulnerability finding] F --> G[Vulnerability record] G --> H[Triage / confirm / dismiss] H --> I[Remediation MR] I --> J[New pipeline + SBOM] J --> K[No longer detected evidence] K --> L[Resolve after verification]
Source and lockfile state enter a trusted pipeline; the runner produces inventory, scanners correlate that inventory with advisories, GitLab may create lifecycle records on eligible tiers, and only a verified remediation build plus rescan justifies a final resolution decision.
Every arrow in the diagram matters. The runner must scan the intended ref; the SBOM must describe the artifact actually built; advisory matching must target the same package version; the hosted record must preserve the finding identity; the remediation MR must change the dependency; and the new pipeline must prove the component version changed before the record is marked resolved.
3. SBOM: inventory, not a verdict
GitLab workflows commonly use CycloneDX JSON. A useful component
identity normally includes a type, name, version and—where
possible—a Package URL (purl). An SBOM can prove that a
package version was inventoried, but it does not prove reachability,
exploitability, runtime loading, or absence of vulnerabilities.
Those are separate analyses.
{
"bomFormat": "CycloneDX",
"specVersion": "1.6",
"version": 1,
"metadata": {"component": {"type": "application", "name": "sbom-lab", "version": "1.0.0"}},
"components": [
{"type": "library", "name": "widget-parser", "version": "1.2.0",
"purl": "pkg:npm/widget-parser@1.2.0"}
]
}
This is intentionally synthetic training data. On Free, store it as an ordinary artifact and hash it. On Ultimate, a conforming CycloneDX report from the latest default-branch pipeline can feed GitLab’s Dependency List when configured as a CycloneDX report artifact. Current GitLab accepts CycloneDX 1.4, 1.5, and 1.6 for Dependency List ingestion.
4. Dependency List is GitLab interpretation, not the raw file
The GitLab Dependency List is an Ultimate hosted view over interpreted dependency data. It can combine dependencies from dependency/container scanning and CycloneDX reports from the latest default-branch pipeline. That view is valuable for filtering, dependency paths, vulnerabilities, licenses and group aggregation—but it is not a replacement for retaining the underlying pipeline identity and raw evidence you need for reproducibility.
| Layer | Question it answers | Failure if confused |
|---|---|---|
| Raw SBOM artifact | What components did this pipeline claim to inventory? | You lose exact pipeline evidence if you rely only on a later dashboard. |
| Dependency List | What dependency inventory does GitLab currently interpret for the project/group? | A fresh default-branch pipeline can update the view and hide historical context. |
| Vulnerability finding | What weakness did a scanner/advisory match report? | Presence of a package is mistaken for exploitability. |
| Vulnerability record | What lifecycle decision has the team made? | A status label is mistaken for proof the built artifact changed. |
5. Vulnerability lifecycle: status and detection are separate
Current GitLab vulnerability status values are
Needs triage, Confirmed,
Dismissed, and Resolved.
Exports/API terminology may use detected for the UI’s
Needs triage state. A newly discovered vulnerability normally starts
at Needs triage. Confirmed means a human has accepted the finding as
real and requiring analysis. Dismissed means the team intentionally
decided not to remediate it and recorded a dismissal reason/comment.
Resolved means the team verified the vulnerability was fixed or no
longer present.
| State/evidence | Meaning | Operational action |
|---|---|---|
| Needs triage / detected | New record needs assessment. | Validate scope, identity and severity. |
| Confirmed | Finding is accepted as accurate and relevant enough for analysis. | Track owner, remediation plan and verification. |
| Dismissed | Finding intentionally not remediated; reason/comment is recorded. | Review exception periodically; dismissal is not a fix. |
| No longer detected | Scanner did not report it in a later tracked/default-branch scan. | Ask why: fixed, scanner removed, scope changed, or report broken? |
| Resolved | Team/policy concluded remediation is verified. | Retain link to MR, pipeline, SBOM/artifact identity and verification evidence. |
6. Project, group, dashboard, and permission scope
Security dashboards, Security Inventory, Dependency List and vulnerability reports are Ultimate surfaces with project/group scope. A group dashboard can only summarize the projects in its effective scope; it cannot prove that an omitted project is safe. The Security Center is a user-selected multi-project view, not a magic organization-wide source of truth.
Changing vulnerability status is also a permissioned action. Current
GitLab requires Security Manager, Maintainer, Owner, or an
appropriate custom role with admin_vulnerability.
Developer no longer has this ability by default. That separation is
governance: being able to push code is not the same as being allowed
to dismiss organizational risk.
7. Inspect before changing anything
Start with identities. Record project path, default branch, commit SHA, pipeline ID, job ID, SBOM artifact hash, component purl/version and the finding’s stable identifiers. Only then inspect hosted state.
git rev-parse HEAD
git status --short
sha256sum evidence/sbom-before.cdx.json
python -m json.tool evidence/sbom-before.cdx.json >/dev/null
# Optional Ultimate/read-only: dependency and vulnerability APIs are authenticated, tier-gated surfaces.
# Prefer GraphQL for long-lived vulnerability automation because current REST project-vulnerability APIs are unstable/deprecating.
8. Common misconceptions that create audit gaps
- “SBOM means vulnerability scan.” No. Inventory and vulnerability matching are separate.
- “No longer detected means resolved.” No. It is evidence that must be explained.
- “Dismissed means fixed.” No. Dismissal is a governed exception.
- “Dashboard has zero critical findings, therefore all projects are safe.” Only if scope, scanner coverage and pipeline freshness are proved.
- “The dependency is present, therefore exploitable.” Presence is not reachability or exploitability.
Knowledge check
What is the strongest reason to retain the raw SBOM even when GitLab shows a Dependency List?
The raw artifact can be tied to a specific pipeline/SHA and independently hashed; a current hosted view can evolve with later default-branch pipelines.
A vulnerability disappears from the next scan. Is it automatically Resolved?
No. GitLab records No longer detected activity, but the status remains until a user or vulnerability-management policy changes it after verification.
Which is a lifecycle decision rather than scanner evidence: Dismissed or component purl?
Dismissed. The purl is component identity; Dismissed is a governed vulnerability-record decision.
Why can a group security dashboard create false confidence?
If a project is outside dashboard scope, stale, or lacks a functioning scanner, the aggregate can look clean without representing that project’s risk.
Who can currently change vulnerability status by default?
Security Manager, Maintainer, Owner, or a custom role with admin_vulnerability; Developer no longer has that permission by default.
Summary and production pattern
A trustworthy vulnerability-management system keeps component inventory, scanner findings, hosted lifecycle state, remediation change, rescanning evidence, and final disposition connected by immutable identities. Chapter 25 taught how evidence is produced. Chapter 26 teaches how that evidence becomes accountable work.
Next lesson
Next, build a Free-compatible synthetic SBOM/finding workflow, then map the same evidence to optional Ultimate Dependency List and vulnerability-management surfaces without requiring a paid subscription.
Primary sources and version notes
These lessons were finalized against current official GitLab documentation on 2026-08-22. Re-check tier, feature-flag, API, and Self-Managed-version behavior before using the same workflow later.
Keep the academy open
Support free, practical DevOps education.
Every lesson is designed to remain readable in a browser, downloadable from GitHub, and usable without a paid learning platform. Contributions help expand and maintain the curriculum.
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0Send only Ethereum/ERC-20 compatible assets to this
address.