Use the list global security advisories endpoint and filter with the affects parameter, which accepts package names with optional versions, up to 1,000 at a time. By default it returns only reviewed advisories that are not malware. Add the type parameter to include unreviewed or malware entries, and follow the Link header cursors to page.
What the endpoint is
GitHub's REST API exposes the GitHub Advisory Database as global security advisories. This is different from repository security advisories, which are a separate set of endpoints managed per repository. Global advisories are the public database that many scanners and alerts rely on.
The list endpoint takes query parameters to narrow results. These are the ones tool builders use most.
| Parameter | What it does |
|---|---|
| ghsa_id | Return the advisory with this GHSA identifier |
| cve_id | Return advisories with this CVE identifier |
| ecosystem | Filter by ecosystem |
| severity | Filter by unknown, low, medium, high or critical |
| cwes | Filter by weakness numbers, such as 79, 284, 22 |
| affects | Advisories affecting a package or package at a version |
| type | reviewed, malware or unreviewed |
| is_withdrawn | Return only withdrawn advisories |
| published, updated, modified | Date or date range filters |
| sort, direction | Sort by updated, published and EPSS fields |
The documentation lists the ecosystem values: rubygems, npm, pip, maven, nuget, composer, go, rust, erlang, actions, pub, other and swift. Note the names. They are GitHub's own, not purl types, so map them in your code.
The default surprises people
With no other parameters, the documentation says a request returns only reviewed advisories that are not malware. The type parameter defaults to reviewed. If your tool needs malware reports, you must ask for them with type equals malware. Unreviewed advisories are another separate value.
That default is sensible for most users, but it is easy to miss. A scanner that never sets type will never show a malware entry, and the missing results will look like a clean bill of health.
Query by package and version
The affects parameter takes a package, or a package and a version joined with an at sign. The documentation example is affects equals package1,package2@1.0.0,package3@2.0.0. A maximum of 1,000 packages can be specified. If the URL grows past what your client supports, send fewer packages per request.
Since names are not qualified with an ecosystem in that example, combine affects with the ecosystem parameter to avoid cross ecosystem name collisions.
Paging and sorting
Results are paged with cursors. The documentation defines before and after parameters whose values come from the Link header, a per page setting with a default of 30 and a maximum of 100, and a direction that defaults to descending. The default sort is by published date, and you can sort by updated, published, EPSS percentage or EPSS percentile.
For a sync job, sort by updated, descending, and stop when you reach an entry you have already stored.
Error handling
The documented responses include 200 for success, 422 when validation fails or the endpoint has been spammed, and 429 for too many requests. Back off on 422 and 429 rather than retrying immediately.
When to use this instead of OSV
The OSV format also carries GitHub advisories, and querying OSV by package and version is simpler for batch lookups. See checking a package version for known vulnerabilities with OSV. The GitHub API is the better source when you want GitHub specific filters such as the type split or EPSS sorting.
Try it yourself
Click through it at your own pace, or open it full screen. Look at how an advisory ties to a package, an affected range and a fix.
Where this fits
Safeguard offers SBOM and dependency scanning, and the free scan lets you see advisory matches on a real project without writing a client.
Quick check
Why does my query never return malware advisories?
The default type is reviewed and excludes malware. Set type to malware to include them.
How many packages can one affects parameter hold?
Up to 1,000, but the URL length limit of your client may force fewer.
Sources
Last reviewed: 19 October 2026.