# GitLab DevSecOps Part 9: Overcoming Vulnerability Management Challenges

> Part 9 of the GitLab DevSecOps series. Patrick Steger and I look at the GitLab Vulnerability Management tool: the security dashboard, the vulnerability report, how to triage findings, and the limitations you have to plan around.

- Date: 2022-10-12
- Source: https://romanoroth.com/en/blogs/gitlab-devsecops-vulnerability-management/
- Tags: DevSecOps, GitLab, CI/CD, DevOps, Vulnerability Management, Application Security, Security Dashboard, Triage


After eight sessions of adding scanners to our GitLab pipeline — SAST, secret detection, SCA, license compliance, container scanning, DAST — we now have a different problem. We have hundreds of vulnerability findings. In Part 9, Patrick Steger and I look at GitLab's built-in Vulnerability Management: what it gives you, where it falls short, and how to actually triage findings without losing your mind.

<div style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;">
			<iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen" loading="eager" referrerpolicy="strict-origin-when-cross-origin" src="https://www.youtube-nocookie.com/embed/XSrlVyv0H1c?autoplay=0&amp;controls=1&amp;end=0&amp;loop=0&amp;mute=0&amp;start=0" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;" title="YouTube video"></iframe>
		</div>


## What GitLab's Vulnerability Management Gives You

GitLab Ultimate ships a Vulnerability Management module that aggregates findings from every scanner we wired into the pipeline. There are two main views. The **security dashboard** shows the number of vulnerabilities and how they develop over time. The **vulnerability report** lets you view and track individual findings.

One important detail: both views always reflect your **default branch**. In our project that is `master`. Vulnerabilities found on feature branches are not what you see here — only what hits the default branch counts.

In our sample Java project the report lists 165 vulnerabilities: 35 critical, 70 high, 48 medium, 11 low, and one unknown. You can filter by tool (SAST, dependency scanning, DAST, container scanning, secret detection) and by severity. Open a finding and you get an extended description — for example, a container scanning finding pointing at an SSL library, or a critical secret detection finding showing the exact line where an AWS access token landed in the source code.

From a finding you can do three things that matter: create an issue in GitLab's issue tracker, mark it as fixed, or dismiss it. When you re-run the pipeline after a fix, GitLab even detects findings that are no longer reported by the scanners and marks them as **potentially fixed**, which you can then confirm as resolved.

## The Limitations You Need to Plan Around

The tool is a good starting point, but Patrick lists the limitations clearly, and they matter for any serious security process.

**No comment on dismissals.** When you dismiss a finding, you cannot say *why*. Six months later nobody knows whether it was a false positive, an accepted risk, or a misclick.

**No time-boxed dismissal.** You cannot say "accept this risk for six months and re-review." It is dismissed or it is not.

**Dismissal does not distinguish between false positive and accepted risk.** Both end up in the same bucket. From a governance perspective those are very different things.

**Strict format for third-party tools.** You can integrate other scanners, but they must produce reports in the format GitLab expects. We would prefer the Vulnerability Management to be flexible enough to adapt to multiple formats — instead it is the tools that have to adapt.

**Manual entries are clumsy.** When you want to add a finding from a manual penetration test, GitLab demands fields like a CVE ID and an identifier URL — fields that simply do not exist for a manual finding. The workaround is to enter dummy values, which then live forever in the report. The information you can attach is also very limited.

**Findings drift when source code changes.** Patrick saw cases where, after a code change, the existing finding no longer pointed to the right line.

## Triage Workflow in Practice

In the demo we walked through the typical lifecycle. Most findings start as **Needs Triage**. Investigate one: if it is real, set it to **Confirmed**, then create an issue from the finding so a developer picks it up. The issue and the vulnerability are linked both ways, so you can navigate from finding to issue and back. If it is not real, **Dismiss** it — and accept that you cannot record why.

For a manual entry we tried "cross-site scripting from a penetration test." GitLab refused the submission until we filled in an identifier code and URL. We added placeholder values, submitted again, and then filtered the report by tool = "manually added" to see it.

After fixing a batch of findings — in our case, bumping Spring Boot from version 2 to 2.7.2 and updating the test framework accordingly — we re-ran the pipeline. Filtering the vulnerability report by **activity = no longer detected** showed a long list of issues the scanners no longer find. We bulk-set them to **Resolved**. Same shortcoming as dismissal: no place to record context.

Creating an issue is also the practical workaround for the missing comment field. The issue gives you a place to write down what you actually did, which the vulnerability record itself does not offer.

## Key Takeaways

1. **Vulnerability Management is part of the pipeline, not an afterthought.** Once you have five or six scanners running on every commit, you need a place to triage their output. Without it, the scanners produce noise that nobody acts on.

2. **The default-branch-only view is a real constraint.** Findings on feature branches do not show up in the dashboard. Plan your branching model and your security gates around that.

3. **Dismissal without a reason is a governance gap.** False positive and accepted risk should not look the same. Until GitLab fixes this, use linked issues to record the reasoning.

4. **Manual findings deserve a first-class workflow.** The current path forces you to fake CVE IDs. If you do a lot of manual penetration testing, expect to keep a separate tool alongside GitLab.

5. **Re-runs detect "no longer present" findings.** Use the **activity = no longer detected** filter after every fix sweep — it is the fastest way to clean up the report and see real progress.

6. **Issues are the workaround for everything the report cannot store.** Comments, history, attachments, audit trail — all of that lives on the issue, not on the vulnerability. Build that habit early.

