GHSA
A GHSA id — GHSA-xxxx-xxxx-xxxx — names one advisory in the GitHub
Advisory Database. It identifies a vulnerability in an open-source package
the way a CVE does, but it is assigned by GitHub, and a reviewed GHSA entry
carries what a CVE record often lacks: the exact package in npm, PyPI, Maven
or another ecosystem, and the version ranges that are affected and patched.
How the id is built
GHSA- plus three groups of four characters, each drawn from
23456789cfghjmpqrvwx — no vowels, no 0/o or 1/l pairs — so an id
read aloud or copied from a screenshot survives:
| Example | What it is |
|---|---|
GHSA-3h5v-q93c-6h6q |
ws request-header DoS, alias CVE-2024-37890 |
GHSA-j8r2-6x86-q33q |
requests proxy-header leak, alias CVE-2023-32681 and PYSEC-2023-74 |
GHSA-grv7-fg5c-xmjg |
braces uncontrolled resource use, alias CVE-2024-4068 |
The id is random, not sequential. It says nothing about date, ecosystem or severity — that is in the record.
Reviewed, unreviewed and malware
The database holds three kinds of advisory, and only one of them drives the alerts most people see:
- Reviewed — curated by GitHub, mapped to a package in a supported
ecosystem (npm, PyPI, Maven, NuGet, RubyGems, Go, Composer, crates.io, Pub,
Swift, Hex, GitHub Actions) with
vulnerable_version_rangeandpatched_versions. Dependabot alerts andnpm audituse these. - Unreviewed — imported automatically from the NVD, with a CVE and a description but no package mapping. They exist so the database is complete, and they trigger nothing.
- Malware — packages published to steal or damage, mostly on npm. The fix is always "remove it", never "upgrade".
GHSA and CVE
They are aliases, not competitors. A maintainer can draft a repository security advisory privately, fix the bug in a temporary private fork, and publish — and because GitHub is a CVE Numbering Authority, ask for the CVE in the same form. Once published and reviewed, it lands in the database with both ids. Flaws found by the NVD first arrive the other way round: CVE first, GHSA added on import.
That is why scanners disagree on what to call the same row. npm audit and
OSV-Scanner lead with the GHSA id; Trivy and Grype usually lead with the CVE
and list the GHSA beside it, or the reverse for advisories that have no CVE.
A report that groups by flaw rather than by id avoids counting one bug twice.
Severity
Each reviewed advisory has a label — Critical, High, Moderate or Low — and,
usually, a CVSS vector the label comes from. GitHub's label
can differ from the NVD's score for the same CVE, because GitHub's reviewers
rate the package-level impact. Scanners differ in which one they show;
OSV entries carry GitHub's label in
database_specific.severity.
Looking one up
# REST
curl -s https://api.github.com/advisories/GHSA-3h5v-q93c-6h6q
# every advisory for a package
curl -s "https://api.github.com/advisories?ecosystem=npm&affects=ws"
Or browse github.com/advisories/GHSA-…. The same records are in the public
github/advisory-database repository as OSV JSON files, and on osv.dev.
Where the scan goes next
A scanner hands you a list of GHSA and CVE ids; someone still has to decide which to fix this sprint. Drop the JSON into the free Trivy viewer (Trivy and Grype), the npm audit viewer or the pip-audit / OSV-Scanner viewer: each advisory links to its GitHub page with the aliases beside it. Then publish the report as a link and let the reviewer comment on the advisory itself.
Try it
Comma is free — unlimited reports, unlimited commenters, unlimited revision history.