Why an Empty ‘vulnerabilities’ Array Means Your GitLab SAST Scan Passed
The article explains GitLab SAST’s standardized JSON report format, walks through the meaning of the scan metadata and the vulnerabilities array, and shows that an empty vulnerabilities list together with a success status simply indicates a clean, successful static analysis run.
GitLab’s security scanners (SAST, DAST, dependency scanning, etc.) all output a standardized JSON report, allowing GitLab to parse and display results uniformly regardless of the underlying engine such as Semgrep or Brakeman.
Report Core Structure: JSON from the Start
A typical SAST report consists of two top‑level sections: scan (metadata about the scan) and vulnerabilities (the list of detected issues).
Understanding the scan Section
The scan object records everything about the scan job and acts as its “identity card”. Example:
{
"analyzer": {
"id": "semgrep",
"name": "Semgrep",
"url": "https://gitlab.com/gitlab-org/security-products/analyzers/semgrep",
"vendor": {"name": "GitLab"},
"version": "5.32.0"
},
"scanner": {
"id": "semgrep",
"name": "Semgrep",
"url": "https://github.com/returntocorp/semgrep",
"vendor": {"name": "GitLab"},
"version": "1.110.0"
},
"type": "sast",
"start_time": "2025-08-21T05:27:34",
"end_time": "2025-08-21T05:27:44",
"status": "success"
}analyzer vs. scanner : the analyzer is GitLab’s integration wrapper; the scanner is the actual tool (e.g., Semgrep).
type : indicates the scan kind, here sast.
start_time / end_time : timestamps of the scan.
status : success means the scan finished without configuration or runtime errors.
From the scan data we can conclude that the scan itself executed successfully.
The Crucial vulnerabilities Array
The core of the report is the vulnerabilities field. In the example provided it is an empty array:
{
"vulnerabilities": []
}According to GitLab’s definition, this array holds a JSON object for each detected issue. An empty array, combined with scan.status = "success", unequivocally means the scan completed successfully and found no vulnerabilities matching the configured rule set.
For contrast, here is a fragment where a vulnerability is reported:
{
"vulnerabilities": [
{
"id": "605d1ad8-da1e-4784-859a-199708846fee",
"identifiers": [{
"name": "CKV_AWS_18",
"type": "checkov",
"url": "https://docs.prismacloud.io/en/enterprise-edition/policy-reference/aws-policies/s3-policies/s3_13-enable-logging",
"value": "CKV_AWS_18"
}],
"location": {"file": "main.tf", "start_line": 1, "end_line": 8},
"name": "Ensure the S3 bucket has access logging enabled",
"description": "Further info can be found None",
"severity": "Unknown"
}
]
}When a problem is found, each vulnerability object includes fields such as id, location, name, and severity.
Process Visualization: How the Report Is Generated
The following UML diagram (illustrated below) shows the flow from the scanner to the final JSON report. The vulnerabilities array is populated only when the scanner discovers issues; otherwise it remains empty, indicating a clean scan.
Conclusion
Scan succeeded : scan.status is success, ruling out configuration or execution errors.
Project is clean : an empty vulnerabilities array means no security issues were found under the current rule set.
Thus, when you encounter an empty vulnerabilities array in a GitLab SAST report, it is typically good news, not a cause for alarm. Continuous security still requires additional testing (DAST, dependency scanning) and regular rule updates to maintain a robust defense.
Ops Development & AI Practice
DevSecOps engineer sharing experiences and insights on AI, Web3, and Claude code development. Aims to help solve technical challenges, improve development efficiency, and grow through community interaction. Feel free to comment and discuss.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
