Lesson 4: Overseeing Security Posture#

This lesson shifts the perspective from developer to application security (AppSec) team. Developers interact with security findings one merge request at a time. AppSec needs the broader, cumulative view — what is my project’s security state right now, and how is it trending? GitLab provides several tools for this.

This lesson covers:

  1. Viewing vulnerability reports and vulnerability pages
  2. Using risk assessment data to triage
  3. Accessing the security dashboard
  4. Viewing the security inventory
  5. Viewing audit events
  6. Viewing the Software Bill of Materials (SBOM)
  7. Continuous vulnerability scanning

Viewing vulnerability reports and vulnerability pages#

The vulnerability report is the centralized view of all vulnerabilities detected on the project’s default branch. Unlike the merge request widget (which shows new findings in a specific MR), the vulnerability report shows the cumulative security state of the application.

Each vulnerability links to a vulnerability page that provides:

  • Date the vulnerability was first detected
  • Status (Detected, Confirmed, Dismissed, Resolved)
  • Risk assessment data: severity, CVSS, EPSS, KEV, and reachability
  • Description of the vulnerability
  • Identifiers (CVE, CWE)
  • Scanner that detected it
  • Location in the code (file path and line number)
  • Activity: linked issues, available solutions, MRs that touch the finding
  • Code flow showing the data path through your code (with GitLab Advanced SAST)
  • Comments for team collaboration

Let’s walk through it:

  1. Navigate to Secure > Vulnerability report in the left sidebar

  2. Set the filter to Group by: Tool to organize vulnerabilities by scanner

  3. Expand the SAST section

  4. Click on the vulnerability titled Improper neutralization of special elements in data query logic with the path routes/basketItems.ts:85. This opens the vulnerability page. At the top you see status, severity, and identifiers. Below that, the description, and then the location in source.

  5. Click the Code flow tab to see the detailed path tainted data follows — from source (user input) to sink (the vulnerable database query). Each step shows file, line, and snippet so you can trace exactly how user-controlled data reaches the vulnerable function.

  6. Click the Edit vulnerability dropdown

  7. Select Change Status

  8. Choose a new status (e.g., Confirmed or Dismissed), add a comment, and click Change Status. A confirmation banner appears.

The status change is now recorded — the basis for systematic triage on the default branch.

  1. Scroll to the bottom and click Create Issue. You can create a standard or confidential issue to collaborate with developers on a fix.

  2. Fill in any relevant details, scroll down, and click Create Issue. The issue links back to the vulnerability and serves as the shared workspace for the fix.

Using risk assessment data to triage#

A pile of “high severity” findings is not actionable. To prioritize, AppSec teams combine multiple signals — that’s what risk assessment data gives you on the vulnerability page:

SignalWhat it tells you
CVSSHow severe the vulnerability is in the abstract (0–10)
EPSSThe probability the vulnerability will be exploited in the next 30 days
KEVWhether the vulnerability is on CISA’s Known Exploited Vulnerabilities list — i.e. someone is already exploiting it in the wild
ReachabilityWhether the vulnerable code is actually called from your code path (requires Static Reachability)

A practical triage order:

  1. KEV + reachable — drop everything
  2. High CVSS + reachable — this sprint
  3. High EPSS + reachable — next sprint
  4. Reachable but low CVSS/EPSS — backlog
  5. Unreachable — accept-risk or dismiss with a note

The vulnerability report supports filtering on each of these fields, so you can build the work queue directly.

Accessing the security dashboard#

The Security Dashboard is a high-level visual overview of how vulnerability count trends over time. It tracks when new vulnerabilities are introduced and resolved on the default branch.

  1. Navigate to Secure > Security dashboard in the left sidebar

The dashboard requires historical data, so it may be empty when you first set up the project. As new commits land, the chart populates with trend data.

  1. Once populated, the dashboard shows a line chart of open vulnerabilities over time, broken down by severity (Critical, High, Medium, Low, Unknown).

  2. At the group level, the same dashboard aggregates across every project in the group — handy when you need to spot which project is regressing.

Viewing the security inventory#

The dashboard tells you how findings trend on the projects you already scan. The Security Inventory answers the prior question — which assets do I have, and which of them are actually being scanned? As the security saying goes, “you can’t secure what you can’t see.” The inventory gives AppSec a single map across a top-level group, its subgroups, and every project, so you can spot coverage gaps and prioritize by risk.

For each project it shows:

  • Scanner coverage for SAST, Dependency Scanning, Container Scanning, Secret Detection, DAST, and IaC Scanning — regardless of how each scanner was enabled
  • Scanner status — derived from the most recent default-branch pipeline:
    • Enabled — configured and completed successfully
    • Not enabled — not configured
    • Failed — ran but did not complete successfully
    • Stale — previously enabled but has not run in the last three consecutive pipelines
  • Vulnerability counts for each group and project, sorted by severity

Let’s walk through it:

  1. On the top bar, select Search or go to and find your group

  2. In the left sidebar, select Secure > Security inventory

  3. Select a group to drill into its subgroups, projects, and security assets — or search for a specific project to inspect its scanner coverage

  4. Use the filters to focus the view, for example:

  • Projects with a critical vulnerability count at or above a threshold
  • Projects where a given scanner is Not enabled or Failed
  • A specific project by name

The Security Inventory requires GitLab Ultimate and the Security Manager, Developer, Maintainer, or Owner role on the group. It is the same view used to apply security configuration profiles from Lesson 2 — find a coverage gap here, then enable the missing scanner in a few clicks.

Where the inventory shows you where scanning is missing, the vulnerability report is where you act on the individual findings once coverage is in place.

Viewing audit events#

Audit Events provide a tamper-proof log of important actions within a project. This answers the compliance question who did what, when:

  • Who changed user permissions, and when
  • Who added or removed a user, and when
  • Who changed a security policy, and when
  • Who dismissed a vulnerability, and when
  1. Navigate to Secure > Audit events in the left sidebar

  2. Review the logged events. Each entry shows actor, action, and timestamp.

Audit events can be streamed to external systems (SIEM, log warehouse) for alerting and long-term retention. Common targets are Splunk, Sumo Logic, and AWS S3. This is the usual setup for regulated environments.

Viewing the Software Bill of Materials (SBOM)#

A Software Bill of Materials (SBOM) is a complete inventory of every component (dependency, library, package) in your application. SBOMs are increasingly required by government regulations and enterprise procurement processes (US Executive Order 14028, EU Cyber Resilience Act).

GitLab automatically generates an SBOM from the latest successful security scan on the default branch and presents it as a Dependency List. It requires:

  • A Dependency Scanning or Container Scanning job in your pipeline
  • A successful pipeline run on the default branch
  1. Navigate to Secure > Dependency list in the left sidebar

  2. Review each dependency:

ColumnDescription
ComponentDependency name and version
PackagerPackage manager used (npm, pip, bundler, …)
LocationFor system dependencies, the container image scanned. For application dependencies, a link to the lock file that declared the dependency.
LicenseLicense(s) attached to the dependency
  1. Use the search bar and filters at the top to narrow by component name, packager, or license.

The SBOM can be downloaded in CycloneDX format from the Dependency Scanning job artifacts — CycloneDX is the standard wire format for exchanging SBOM data with auditors, partners, and downstream tooling. See the CycloneDX documentation.

Continuous vulnerability scanning#

A traditional scan tells you which CVEs were known on the day the pipeline ran. New CVEs are published every day, against the same dependencies you already shipped. Continuous Vulnerability Scanning closes that gap.

When enabled, GitLab continuously re-evaluates the stored SBOM against the GitLab Advisory Database. When a new advisory matches a component already in your application, a new vulnerability appears in the report without any code change or pipeline run.

To enable it:

  1. Navigate to Settings > Security and compliance in the left sidebar

  2. Expand Continuous Vulnerability Scanning

  3. Toggle on the scans you want — Dependency Scanning and Container Scanning are the two available scans

The same continuous-rescan concept applies to your container image in the registry: as long as the image is in your registry and Container Scanning ran on it at least once, newly disclosed CVEs against its base layers show up the next time the advisory database is updated.


Now that we have covered how AppSec teams oversee security posture, let’s see how GitLab Duo AI accelerates vulnerability triage and resolution.

Previous Lesson Next Lesson