Chapter 26Lesson 04~300 minutes

SBOMs, Dependency Lists, Vulnerability Management, Remediation, and Security Dashboards: Diagnostics, Failure Modes, Security, and Performance

Diagnose mismatched SBOM identity, unsafe dismissal, breaking upgrades, dashboard scope gaps, and the dangerous confusion between no-longer-detected and resolved.

DiagnosticsNo longer detectedScopeCompatibilityEvidence

Learning objectives

  • Diagnose an SBOM whose component identity does not match the built artifact.
  • Detect dismissals that hide unresolved risk or lack an owner/review trigger.
  • Handle a dependency upgrade that removes a CVE but breaks application compatibility.
  • Prove dashboard/project scope and distinguish a missing scanner from a resolved vulnerability.
  • Use a preserve-evidence-first diagnostic sequence and least-destructive repairs.
Availability baseline — verified 2026-08-22 against GitLab 19.3. A plain CycloneDX JSON file is an open, portable evidence format and can be generated, validated, hashed, stored as an ordinary CI artifact, and reviewed on GitLab Free. GitLab’s 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 diagnostic sequence

When vulnerability state looks wrong, do not begin by clicking Resolve or rerunning everything. Preserve the evidence that explains how the wrong state was produced.

  1. Preserve: pipeline/job IDs, commit SHA, SBOM/report hashes, scanner logs, finding/vulnerability IDs, MR and deployment identity.
  2. Scope: offering, tier, instance version, namespace/project, default branch, pipeline source, runner, artifact/image and dashboard scope.
  3. Inspect: scanner configuration, report schema, permissions, lifecycle activity, API/GraphQL response, advisory/component identity.
  4. Correct: choose the least destructive fix: regenerate evidence, restore scanner config, repair scope, revert incompatible upgrade, or change status with documented reason.
  5. Verify: independently prove the post-fix component version and rescan state.

2. Failure: SBOM version does not match the built artifact

Suppose the release manifest says widget-parser=1.2.1 but the uploaded SBOM still says 1.2.0. The dashboard may show the old vulnerability correctly—for the wrong build evidence.

$ cat release.manifest
widget-parser=1.2.1
$ python - <<'PY'
import json
c=json.load(open('sbom.cdx.json'))['components'][0]
print(c['purl'])
PY
pkg:npm/widget-parser@1.2.0

Root cause: stale SBOM copied from a previous stage/cache, or generator ran before dependency resolution. Repair: regenerate SBOM from the same locked workspace/artifact build, fail the pipeline when manifest and SBOM diverge, and preserve the old evidence for diagnosis rather than overwriting it.

3. Failure: dismissal becomes an invisible permanent exception

A finding is dismissed as “acceptable risk,” but there is no owner, expiry, mitigating control or review event. GitLab preserves dismissal activity, but governance still needs your organization-specific review metadata. The least destructive correction is not to delete the record—vulnerability records are retained for audit. Reopen/revert the status if the rationale is no longer valid, add a tracked risk item, and document the review trigger.

4. Failure: the CVE is gone but the application is broken

An upgrade to 2.0.0 removes the advisory but changes an API contract. A “zero finding” outcome is not a successful remediation if the release is unusable. Verify security and compatibility in parallel.

Evidence Before After upgrade Interpretation
SBOM component 1.2.0 2.0.0 Security identity changed.
Dependency finding High No longer detected Advisory mapping disappeared.
Contract tests Pass Fail Application compatibility regressed.
Disposition Confirmed Do not mark Resolved yet Choose compatible fixed version, adaptation, or mitigation.

The production correction may be a different patched version, application code adaptation, or a temporary mitigating control. “Security fix” and “safe release” are related but distinct outcomes.

5. Failure: dashboard scope excludes the project

A group dashboard shows zero critical vulnerabilities because the affected project was moved to a subgroup outside the aggregation scope or never added to the Security Center. Diagnose membership/path scope and scanner coverage before interpreting counts. A useful control is a separate coverage inventory: expected projects versus projects with a recent default-branch security/SBOM pipeline.

6. Failure: scanner no longer runs, so the finding disappears

This is the most dangerous false resolution. A template include is removed, rules exclude the default branch, a runner tag no longer matches, or the report becomes malformed. The next pipeline has no finding because it has no valid scan.

# Intentionally broken training example
workflow:
  rules:
    - if: '$CI_COMMIT_BRANCH != $CI_DEFAULT_BRANCH'

# Result: default branch may create no relevant security job/report.
# Do NOT mark prior findings Resolved merely because the new pipeline emits nothing.

Repair the scanner/configuration first, prove a valid report was produced for the same target, then interpret “no longer detected.” Keep the original cause visible in the incident/evidence record.

7. API and permission signals are evidence too

Current vulnerability and export APIs are Ultimate and authenticated. Treat status codes semantically:

Response Likely class Next check
401 Authentication failed Token presence/type/expiry; never print the token.
403 Authenticated but unauthorized/tier surface Role, custom permission, tier, security feature access.
404 Resource hidden/not found Project membership, encoded path/ID, vulnerability existence.
429 Rate/export concurrency limit Retry/backoff; export APIs allow limited concurrent work.

8. Destructive and sensitive operations

Security-sensitive: changing vulnerability status can suppress or close risk visibility. Destructive: deleting projects, security artifacts, packages/images, or rewriting Git history can remove evidence. Use disposable resources, preserve IDs/hashes before cleanup, never force-push a valuable repository, and never treat history rewrite as secret response before revoking/rotating the credential.

Knowledge check

The SBOM says 1.2.0 and release manifest says 1.2.1. What should happen first?

A dependency finding is no longer detected but contract tests fail after the upgrade. Should you resolve it?

What is the first diagnostic question when a dashboard count unexpectedly drops to zero?

Why is deleting a dismissed vulnerability record not the normal correction?

What does 403 from a vulnerability API suggest?

Summary and next bridge

Trustworthy vulnerability management is resilient to misleading absences. The checkpoint lab now makes you prove before/after component identity, simulate a missing-report failure, and distinguish Resolved, Dismissed and No longer detected without relying on a paid dashboard.

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.

Next lesson

Checkpoint Lab

Trace one synthetic dependency from inventory to finding to remediation and final disposition, including a deliberately broken scan.

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.

Ethereum / ERC-20
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0Send only Ethereum/ERC-20 compatible assets to this address.