When Log4Shell surfaced on December 9, 2021, it carried three different labels depending on where a security team looked: CVE-2021-44228 in the National Vulnerability Database, GHSA-jfh8-c2jp-5v3q in GitHub's Advisory Database, and that same GHSA ID again inside OSV.dev, cross-referenced with its CVE alias. These three identifier schemes are not interchangeable, and treating them as synonyms creates real gaps in vulnerability management — a scanner that matches only on CVE IDs will miss advisories that GitHub or an ecosystem maintainer ships days or weeks before MITRE assigns a number. CVE, GHSA, and OSV are three separate systems for identifying and describing vulnerabilities, run by different organizations, updated on different timelines, and built on different data models. This post breaks down what each format actually is, how they relate to one another, and which one your tooling should be reading first.
What is a CVE, and who assigns the identifiers?
A CVE (Common Vulnerabilities and Exposures) is a unique identifier in the format CVE-YYYY-NNNN (or more digits) assigned to a specific publicly disclosed vulnerability, maintained by the MITRE-operated CVE Program under the sponsorship of the U.S. Cybersecurity and Infrastructure Security Agency (CISA). The program launched in 1999 and has published more than 260,000 CVE records since then. Individual CVE IDs are handed out not by MITRE directly but by more than 400 CVE Numbering Authorities (CNAs) spread across 40+ countries as of 2025 — major vendors like Microsoft, Red Hat, and GitHub itself are all CNAs, each responsible for assigning IDs for vulnerabilities in their own products or ecosystems. A raw CVE record, at the moment it's reserved, often contains little more than a placeholder description and a reference link; severity scoring (CVSS), CWE classification, and affected-version data get layered on afterward, usually by the CNA or by NVD's enrichment process. That lag between "CVE reserved" and "CVE enriched with usable data" is a recurring pain point — NVD's own analysis backlog pushed some records past 30 days without a CVSS score during 2024.
What is a GHSA, and how is it different from a CVE?
A GHSA (GitHub Security Advisory) is GitHub's own vulnerability identifier, formatted as GHSA-xxxx-xxxx-xxxx using a 32-character alphabet that strips visually ambiguous characters like 0, O, I, and l, and it's issued through the GitHub Advisory Database rather than through MITRE. GitHub launched the Advisory Database in November 2019, initially for npm and a handful of ecosystems, and has since expanded it to cover PyPI, Maven, Composer, RubyGems, Go, NuGet, crates.io, Pub, and more. Because GitHub became a CVE CNA in 2020, many GHSAs do carry a CVE alias, but a GHSA can exist entirely on its own: a maintainer can publish a security advisory for their own repository and get a GHSA ID assigned without ever requesting a CVE. The GitHub Advisory Database now lists more than 200,000 entries as of 2024, a mix of GitHub-reviewed advisories and unreviewed records mirrored in from NVD. The practical difference for defenders is speed and structure — GHSA records ship with machine-readable semver-style affected ranges and ecosystem tags from day one, and Dependabot alerts fire directly off that GHSA data, often days ahead of when the matching CVE record finishes NVD enrichment.
What is OSV, and is it a new identifier scheme or something else?
OSV isn't a new competing ID scheme so much as a schema and aggregation layer — OSV (Open Source Vulnerability) is a JSON format and public API created by Google's Open Source Security Team in 2021 that pulls together vulnerability data from more than 20 existing sources instead of minting its own universal ID for every entry. OSV.dev ingests GHSA advisories, PyPA's PYSEC- records, the Go vulnerability database's GO- entries, RustSec's RUSTSEC- advisories, Debian's DSA/DLA bulletins, Alpine's advisories, and OSS-Fuzz findings, among others. When OSV ingests a GHSA, it keeps GHSA-xxxx-xxxx-xxxx as the record's primary "id" field and lists any corresponding CVE-YYYY-NNNNN under an "aliases" array rather than replacing it. Google released osv-scanner, an open source command-line tool, in 2022, and it's now embedded in a number of CI pipelines and SBOM scanners that query the free OSV API against a dependency manifest. Because OSV normalizes affected-version data into one consistent structure across ecosystems, it functions less like a fourth naming authority and more like a translation layer that lets one query cover sources that would otherwise need 20 separate lookups.
Why does one vulnerability end up with a CVE, a GHSA, and an OSV entry?
One vulnerability ends up with multiple identifiers because three separate organizations run independent disclosure pipelines, and OSV deliberately preserves those upstream identifiers rather than replacing them. Log4Shell is the clearest example: the Apache Software Foundation, acting as CNA, assigned CVE-2021-44228 on December 10, 2021, GitHub's Advisory Database separately published GHSA-jfh8-c2jp-5v3q for the same flaw, and OSV.dev's record is keyed on that GHSA ID with the CVE listed as an alias. It also happens in the other direction — a Python package vulnerability might get a PYSEC-2023-NNN ID from PyPA with no CVE ever requested, because ecosystem-native advisory databases aren't obligated to file a CVE for every entry, particularly for lower-severity issues maintainers patch quietly. That asymmetry means a vulnerability feed built exclusively around CVE IDs can systematically under-report findings in ecosystems where maintainers default to GHSA, PYSEC, GO, or RUSTSEC advisories instead of requesting a CVE, which skews coverage toward vendor-heavy CNAs and away from smaller open source projects.
Which format should security and engineering teams rely on for scanning?
No single format is sufficient on its own — teams should track every identifier alias attached to a finding and query by SBOM component and ecosystem rather than by ID format, because leaning on one scheme creates blind spots at both ends of the disclosure timeline. In practice, GHSA data for an npm or PyPI package is typically visible in the Advisory Database and in Dependabot within 24-48 hours of disclosure, while the matching CVE record can sit in "Received" or "Awaiting Analysis" status in NVD for days to weeks before CVSS scoring and affected-version data are added. OSV narrows that gap somewhat, since it mirrors GHSA and ecosystem-native sources close to real time and surfaces the CVE alias once one exists, which is why it's increasingly the backend of choice for scanners that need to reconcile a security bulletin citing a CVE with a fix commit that only ever referenced a GHSA or PYSEC ID.
How Safeguard Helps
Safeguard ingests vulnerability data from CVE, GHSA, and OSV simultaneously and normalizes every alias against the SBOMs it generates for your codebase, so a finding surfaced under any one identifier format resolves to the same underlying dependency instead of showing up as three separate alerts. Griffin AI, Safeguard's reasoning engine, cross-references those identifiers with reachability analysis to determine whether the vulnerable function in a flagged package — whether it's labeled CVE-2021-44228 or GHSA-jfh8-c2jp-5v3q — is actually called from your code paths, filtering out advisories that don't apply to how you use a dependency. When a finding is confirmed reachable, Safeguard can open an auto-fix pull request that bumps the dependency to the first version where the OSV- or GHSA-listed affected range is closed, without waiting on NVD to finish CVE enrichment. Because Safeguard both generates SBOMs from your own builds and ingests SBOMs produced elsewhere in your pipeline, that identifier normalization holds regardless of which format — CVE, GHSA, or OSV — reaches your team first.