How to return all vulnerabilities using GraphQL

I am using a hosted version of GitLab and trying to use GraphQL to return a list of all vulnerabilities in a project. I have been able to do so using the REST API, but the documentation says that it is being deprecated in favor of GraphQL. I have been able to get information back on a single vulnerability using GraphQL, but I am stuck when trying to get a list of vulnerabilities from a project. My latest attempt sends:

{
  vulnerabilities(projectId: [1394]) {
    pageInfo {
      endCursor
      startCursor
      hasNextPage
    }
    nodes {
      id
      state
      title
    }
  }
}

and all I get in return is:

{
  "data": {
    "vulnerabilities": {
      "pageInfo": {
        "endCursor": null,
        "startCursor": null,
        "hasNextPage": false
      },
      "nodes": []
    }
  }
}

What am I doing wrong?

1 Like

Hello, you can try with this structure it worked for me.

Hi, @minton55.

See below for an example that works for me.

@hdezcarlos, as @minton55 mentioned, the REST API is going to be deprecated. If there’s anything that you can’t do with the GraphQL API, please create an issue in gitlab-org/gitlab and tag me (@thiagocsf).

{
  project(fullPath: "gitlab-examples/security/security-reports") {
    id
    name
    vulnerabilities(severity: MEDIUM, reportType:CONTAINER_SCANNING) {
      nodes{
        id
        reportType
        title
        severity
        detectedAt
        updatedAt
        vulnerabilityPath
        description
        falsePositive
        state
        hasSolutions
        
        
        scanner {
          reportType
          externalId
          name
          vendor
        }
        identifiers {
          externalId
          externalType
          name
          url
        }
        project {
          id
          name
          fullPath
        }
        links {
          name
          url
        }
        location {
          ... on
          VulnerabilityLocationSecretDetection{
            file
            startLine
            endLine
            vulnerableClass
            vulnerableMethod
            blobPath
          }
          ... on 
          VulnerabilityLocationSast {
            file
            startLine
            endLine
            vulnerableClass
            vulnerableMethod
            blobPath
          }
          ... on 
           VulnerabilityLocationDependencyScanning{
            file
            dependency{
              package{
                name
              }
              version
            }
            blobPath
          }
        }
        
        details {
          ... on
          VulnerabilityDetailCode {
            description
            fieldName
            lang
            name
            value
          }
        }
      }
    }
  }
}

And the response

{
  "data": {
    "project": {
      "id": "gid://gitlab/Project/6102100",
      "name": "security-reports",
      "vulnerabilities": {
        "nodes": [
          {
            "id": "gid://gitlab/Vulnerability/46961567",
            "reportType": "CONTAINER_SCANNING",
            "title": "CVE-2022-22576 in curl-7.79.1-1.amzn2.0.1",
            "severity": "MEDIUM",
            "detectedAt": "2022-06-13T20:54:25Z",
            "updatedAt": "2023-04-27T05:09:37Z",
            "vulnerabilityPath": "/gitlab-examples/security/security-reports/-/security/vulnerabilities/46961567",
            "description": "A vulnerability was found in curl. This security flaw allows reusing OAUTH2-authenticated connections without properly ensuring that the connection was authenticated with the same credentials set for this transfer. This issue leads to an authentication bypass, either by mistake or by a malicious actor.",
            "falsePositive": false,
            "state": "DETECTED",
            "hasSolutions": true,
            "scanner": {
              "reportType": "CONTAINER_SCANNING",
              "externalId": "trivy",
              "name": "Trivy",
              "vendor": "GitLab"
            },
            "identifiers": [
              {
                "externalId": "CVE-2022-22576",
                "externalType": "cve",
                "name": "CVE-2022-22576",
                "url": "https://access.redhat.com/security/cve/CVE-2022-22576"
              }
            ],
            "project": {
              "id": "gid://gitlab/Project/6102100",
              "name": "security-reports",
              "fullPath": "gitlab-examples/security/security-reports"
            },
            "links": [
              {
                "name": null,
                "url": "https://access.redhat.com/security/cve/CVE-2022-22576"
              },
              {
                "name": null,
                "url": "https://curl.se/docs/CVE-2022-22576.html"
              },
              {
                "name": null,
                "url": "https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-22576"
              },
              {
                "name": null,
                "url": "https://ubuntu.com/security/notices/USN-5397-1"
              }
            ],
            "location": {},
            "details": []
          },
          {
            "id": "gid://gitlab/Vulnerability/26233",
            "reportType": "CONTAINER_SCANNING",
            "title": "CVE-2016-10228 in glibc",
            "severity": "MEDIUM",
            "detectedAt": "2020-01-17T04:05:42Z",
            "updatedAt": "2020-01-17T04:05:42Z",
            "vulnerabilityPath": "/gitlab-examples/security/security-reports/-/security/vulnerabilities/26233",
            "description": "The iconv program in the GNU C Library (aka glibc or libc6) 2.25 and earlier, when invoked with the -c option, enters an infinite loop when processing invalid multi-byte input sequences, leading to a denial of service.",
            "falsePositive": false,
            "state": "DETECTED",
            "hasSolutions": null,
            "scanner": {
              "reportType": "CONTAINER_SCANNING",
              "externalId": "clair",
              "name": "Clair",
              "vendor": "GitLab"
            },
            "identifiers": [
              {
                "externalId": "CVE-2016-10228",
                "externalType": "cve",
                "name": "CVE-2016-10228",
                "url": "https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2016-10228"
              }
            ],
            "project": {
              "id": "gid://gitlab/Project/6102100",
              "name": "security-reports",
              "fullPath": "gitlab-examples/security/security-reports"
            },
            "links": [
              {
                "name": null,
                "url": "https://security-tracker.debian.org/tracker/CVE-2016-10228"
              }
            ],
            "location": {},
            "details": []
          }
        ]
      }
    }
  }
}

Hi @thiagocsf , tried the same GraphQL query you have posted. I just replaced the project fullPath with my project fullPath and reportType:SAST as I have the SAST report generated and available but the GraphQL response returns no data.
{
“data”: {
“project”: null
}
}
Any changes made to the API in the new versions? I tried this in GitLab ultimate trial. I am getting the response using REST API

@vinothmailbox, I re-ran the query from my answer just now using GraphiQL, and I get a populated response. This rules-out any breaking API changes since June/2023.

What is the equivalent REST API call that you’re making?

Make sure that you’re looking for Vulnerabilities (Query.vulnerability), and not Findings (Pipeline.securityReportFindings). The difference is that Vulnerabilities will show in the project vulnerability report, whereas security findings only show in the pipeline security report.

To ensure this is not a data problem, you can fork GitLab-examples / security / security-reports · GitLab, run a pipeline on the default branch, and then run the query again.

Please note that the vulnerability REST APIs are due to be deprecated, so if you’re building any integrations it’s advisable to get GraphQL working as you’ll need it sooner or later.

While I’m back here, I want to leave links to more examples on how to replace the vulnerability REST API with GraphQL:

While I am no longer the engineering manager responsible for this feature, you can find information about the team in our handbook: Threat Insights.

The above query is great but how can the project based one (not the pipeline one) be used to also obtain each vulnerability’s evidence (request, response, urls, etc.)?

@coobr01, these are the available Vulnerability fields: GraphQL API resources | GitLab. You can add any of them to my example above.

Note that the information you look might be in the details field, which has multiple types.

Each Vulnerability type also uses its own VulnerabilityLocation, and the available fields are different. For example, VulnerabilityLocationSast has file and startLine whereas VulnerabilityContainerScanning has image and operatingSystem.

This is what ... on VulnerabilityLocationSast etc do: pick the fields you want for each location type.

I can see some of the fields you asked in VulnerabilityLocationDast (e.g. hostname, path, requestMethod, param). I would expect the GitLab DAST analyzer to provide responses in the details property.

Thanks for the reply, I’m focused on obtaining the DAST results I can see in the UI via the GraphQL. So when I visit the UI, i see the data but I can’t seem to get the same data using GraphQL (Note: I can get to the data using the legacy APIs). I noticed the location help content says - Introduced in GitLab 16.3. Status : Experiment. Location of the vulnerability finding… < I’m not sure if that may be my issue.

I’m using v16.9.1-ee.

Basically,

  1. I’m looking to retrieve the the full request/response details but I only see “details”: [{}, {}] in my GraphQL results when I see full data in the UI.

  2. I’d like to only get results for Status = (“Needs Triage” and “Confirmed”) and Activity = “Still detected”.

@coobr01, can you please share your GraphQL query?

1 Like

Thanks @thiagocsf , i didn’t get a notice that there was a response.

{
project(fullPath: “[REDACTED]”) {
id
name
vulnerabilities(state: [DETECTED, CONFIRMED], reportType: [DAST]) {
nodes{
id
reportType
title
severity
detectedAt
updatedAt
vulnerabilityPath
description
falsePositive
state
hasRemediations

    scanner {
      reportType
      externalId
      name
      vendor
    }
    identifiers {
      externalId
      externalType
      name
      url
    }
    project {
      id
      name
      fullPath
    }
    links {
      name
      url
    }

          
    location {
                                ... on
      VulnerabilityLocationDast{
        hostname
        param
        path
        requestMethod
      }

      ... on
      VulnerabilityLocationGeneric{
        description
      }
      
      ... on
      VulnerabilityLocationSecretDetection{
        file
        startLine
        endLine
        vulnerableClass
        vulnerableMethod
        blobPath
      }
      ... on 
      VulnerabilityLocationSast {
        file
        startLine
        endLine
        vulnerableClass
        vulnerableMethod
        blobPath
      }
      ... on 
       VulnerabilityLocationDependencyScanning{
        file
        dependency{
          package{
            name
          }
          version
        }
        blobPath
      }
    }
    
    details {
      ... on
      VulnerabilityDetailCode {
        description
        fieldName
        lang
        name
        value
      }
    }
  }
}

}
}

Hi, @coobr01.

I think the {} you’re seeing are types that your query hasn’t asked for. You can use __typename to see what they are.

For example, if

          	 ... on VulnerabilityDetailList {
              type: __typename
              name
              fieldName
              items {
                __typename
              }
            }

gives me

            "details": [
              {
                "type": "VulnerabilityDetailList",
                "name": "URLs",
                "fieldName": "urls",
                "items": [
                  {
                    "__typename": "VulnerabilityDetailUrl"
                  },
                  {
                    "__typename": "VulnerabilityDetailUrl"
                  },
                  {
                    "__typename": "VulnerabilityDetailUrl"
                  },
                  {
                    "__typename": "VulnerabilityDetailUrl"
                  }
                ]
              },

It tells me that I need a ... on VulnerabilityDetailUrl to expand the values.

So once I rewrite the query to:

          	 ... on VulnerabilityDetailList {
              type: __typename
              name
              fieldName
              items {
                __typename
                ... on VulnerabilityDetailUrl {
                  description
                  fieldName
                  href
                  name
                  text
                }
              }
            }

I get to see the {} values:

            "details": [
              {
                "type": "VulnerabilityDetailList",
                "name": "URLs",
                "fieldName": "urls",
                "items": [
                  {
                    "__typename": "VulnerabilityDetailUrl",
                    "description": null,
                    "fieldName": null,
                    "href": "http://34.136.183.135/._darcs",
                    "name": null,
                    "text": null
                  },
                  {
                    "__typename": "VulnerabilityDetailUrl",
                    "description": null,
                    "fieldName": null,
                    "href": "http://34.136.183.135/.bzr",
                    "name": null,
                    "text": null
                  },
                  {
                    "__typename": "VulnerabilityDetailUrl",
                    "description": null,
                    "fieldName": null,
                    "href": "http://34.136.183.135/.hg",
                    "name": null,
                    "text": null
                  },
                  {
                    "__typename": "VulnerabilityDetailUrl",
                    "description": null,
                    "fieldName": null,
                    "href": "http://34.136.183.135/BitKeeper",
                    "name": null,
                    "text": null
                  }
                ]
              },

The full example below should get you started.

I’m not an expert, and I had to stumble across vulnerability_detail.fragment.graphql to see how to write a query using details.

{
  group(fullPath: "gitlab-examples") {
    id
    name
    vulnerabilities(state:[DETECTED,CONFIRMED], reportType:DAST, hasResolution:false) {
      nodes{
        project {
          id
          path
        }
        id
        title
        details {
           ... on VulnerabilityDetailUrl {
              type: __typename
              name
              href
            }

             ... on VulnerabilityDetailDiff {
              type: __typename
              name
              before
              after
            }

             ... on VulnerabilityDetailCode {
              type: __typename
              name
              value
            }

             ... on VulnerabilityDetailFileLocation {
              type: __typename
              name
              fileName
              lineStart
              lineEnd
            }

             ... on VulnerabilityDetailModuleLocation {
              type: __typename
              name
              moduleName
              offset
            }

             ... on VulnerabilityDetailCommit {
              type: __typename
              name
              value
            }

             ... on VulnerabilityDetailText {
              type: __typename
              name
              value
            }

             ... on VulnerabilityDetailMarkdown {
              type: __typename
              name
              value
            }

             ... on VulnerabilityDetailBoolean {
              type: __typename
              name
              value
            }

             ... on VulnerabilityDetailInt {
              type: __typename
              name
              value
            }

             ... on VulnerabilityDetailNamedList {
              type: __typename
              name
              items {
                name
                fieldName
                }
              }

          	 ... on VulnerabilityDetailList {
              type: __typename
              name
            }

             ... on VulnerabilityDetailTable {
              type: __typename
              name
            }


      	}
    	}
  	}
	}
}

Results:

{
  "data": {
    "group": {
      "id": "gid://gitlab/Group/349181",
      "name": "GitLab-examples",
      "vulnerabilities": {
        "nodes": [
          {
            "project": {
              "id": "gid://gitlab/Project/40966370",
              "path": "simple-notes-demo"
            },
            "id": "gid://gitlab/Vulnerability/63667310",
            "title": "Hidden File Found",
            "details": [
              {
                "type": "VulnerabilityDetailList",
                "name": "URLs"
              },
              {
                "type": "VulnerabilityDetailText",
                "name": "Discovered at",
                "value": "2024-03-19T17:22:18.585"
              }
            ]
          },

Thanks, when I run the query, i still don’t see any Request/Response data/attributes.