CVE/OSV 데이터 모델
취약점 정보의 두 가지 언어
소프트웨어 보안을 다루다 보면 두 가지 식별자가 자주 등장한다. CVE(Common Vulnerabilities and Exposures)는 1999년부터 존재한 전통적 취약점 번호 체계이고, OSV(Open Source Vulnerability)는 2021년 Google·OpenSSF가 제안한 오픈소스 중심의 구조화된 포맷이다. 이 두 포맷은 경쟁 관계가 아니라 계층 관계다. 대부분의 OSV 레코드는 CVE를 aliases 필드로 참조하고, NVD(National Vulnerability Database)는 CVE 원천 데이터를 호스팅한다.
이 챕터에서는 두 데이터 모델이 어떻게 생겼고, 어떤 정보를 담으며, 실제로 어떻게 연결되는지 살펴본다.
CVE 데이터 모델
CVE 번호 구조
CVE 번호는 CVE-<연도>-<일련번호> 형태다. CVE-2021-44228(Log4Shell)처럼 연도와 4자리 이상 일련번호로 구성된다. CNA(CVE Numbering Authority)가 배정하며, 전세계 300개 이상의 조직이 CNA로 등록되어 있다.
NVD CVSS 점수
NIST NVD는 각 CVE에 CVSS(Common Vulnerability Scoring System) 점수를 부여한다. 버전별로 다르지만 핵심 구성은 동일하다.
| CVSS 버전 | 점수 범위 | 벡터 예시 |
|---|---|---|
| CVSS v2 | 0.0 – 10.0 | AV:N/AC:L/Au:N/C:C/I:C/A:C |
| CVSS v3.1 | 0.0 – 10.0 | CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H |
| CVSS v4.0 | 0.0 – 10.0 | CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/… |
벡터 문자열을 파싱하면 공격 경로(Network/Local), 복잡도(Low/High), 영향 범위(Confidentiality/Integrity/Availability) 등 세부 정보를 얻을 수 있다.
CVE 포맷의 한계
전통적인 CVE/NVD 포맷은 어떤 소프트웨어가 영향받는지를 비정형 텍스트로 기록한다. CPE(Common Platform Enumeration) 필드가 있지만 cpe:2.3:a:apache:log4j:2.14.0:*:*:*:*:*:*:* 같은 표현이 패키지 생태계별 버전 비교에는 적합하지 않다. 오픈소스 라이브러리의 경우 동일 취약점이 npm, PyPI, Maven 등 여러 생태계에 동시에 존재하는데, 이를 CPE 한 줄로 표현하기 어렵다.
OSV 데이터 모델
OSV 포맷은 이 문제를 해결하기 위해 설계됐다. 패키지 생태계별 버전 범위를 구조적으로 표현할 수 있고, JSON 형태로 기계가 바로 파싱할 수 있다. 현재 버전은 1.7.5(2026년 1월 기준)이며 OpenSSF가 관리한다.
최상위 구조
id 와 데이터베이스 접두사
id 필드는 <DB>-<ENTRYID> 형식이다. 주요 데이터베이스 접두사는 다음과 같다.
| 접두사 | 출처 | 예시 |
|---|---|---|
CVE | NVD (National Vulnerability Database) | CVE-2021-44228 |
GHSA | GitHub Security Advisory | GHSA-jfh8-c2jp-hdmh |
PYSEC | PyPI Advisory Database | PYSEC-2021-855 |
RUSTSEC | Rust Advisory Database | RUSTSEC-2019-0033 |
GO | Go Vulnerability Database | GO-2022-0191 |
OSV | OSS-Fuzz (퍼징 발견) | OSV-2020-111 |
DEBIAN | Debian Security Tracker | DSA-5098-1 |
aliases 와 related
동일한 취약점이 여러 데이터베이스에 등록된 경우 aliases로 연결한다. 예를 들어 GHSA 레코드는 같은 취약점의 CVE 번호를 aliases에 포함한다.
{
"id": "GHSA-jfh8-c2jp-hdmh",
"aliases": ["CVE-2021-44228"],
"related": ["GHSA-7rjr-3q55-vv33"]
}aliases: 완전히 동일한 취약점 (대칭 관계)related: 연관됐지만 별개의 취약점 (대칭, 비전이적)
affected — 핵심 필드
가장 중요한 필드다. 영향받는 패키지·버전 범위를 생태계별로 기술한다.
"affected": [
{
"package": {
"ecosystem": "npm",
"name": "lodash",
"purl": "pkg:npm/lodash"
},
"ranges": [
{
"type": "SEMVER",
"events": [
{ "introduced": "0" },
{ "fixed": "4.17.21" }
]
}
],
"versions": ["4.17.20", "4.17.19", "4.17.18"],
"ecosystem_specific": {},
"database_specific": {}
}
]#### package
ecosystem: 패키지 생태계 (npm, PyPI, crates.io, Maven, Debian, Ubuntu 등)name: 생태계 내 패키지 이름purl: Package URL 표준 식별자 (선택)
#### ranges
버전 범위를 이벤트 기반으로 표현한다. type은 세 가지다.
| type | 의미 | 예시 |
|---|---|---|
SEMVER | SemVer 2.0.0 순서 기준 | "introduced": "1.0.0", "fixed": "1.0.2" |
ECOSYSTEM | 생태계 고유 버전 문자열 | Debian buster 같은 표현 |
GIT | 전체 Git 커밋 해시 | "introduced": "abc123..." |
이벤트 객체는 네 종류 중 하나만 가진다:
취약점 시작 → 1.0.1 (여전히 취약) → fixed: 1.0.2
취약점 종료 → 이후 버전 안전
특수값: "introduced": "0" 은 출시 이전부터 취약하다는 의미, "limit": "*" 는 무한(상한 없음)이다.
#### versions
버전 목록을 명시적으로 나열한다. ranges만으로 표현이 어렵거나, 검색 도구가 버전 순서 비교 코드를 갖추지 않아도 바로 사용할 수 있도록 함께 제공하는 경우가 많다.
severity
CVSS 점수를 배열로 담는다. 여러 버전의 CVSS를 동시에 제공할 수 있다.
"severity": [
{
"type": "CVSS_V3",
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H"
},
{
"type": "CVSS_V4",
"score": "CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:H/VA:H/SC:H/SI:H/SA:H"
}
]지원 타입: CVSS_V2, CVSS_V3, CVSS_V4, Ubuntu (Ubuntu 자체 우선도 표현).
references
보안 권고, 소스 패치, 버그 리포트 URL을 타입과 함께 기록한다.
"references": [
{ "type": "ADVISORY", "url": "https://nvd.nist.gov/vuln/detail/CVE-2021-44228" },
{ "type": "FIX", "url": "https://github.com/apache/logging-log4j2/commit/abc" },
{ "type": "ARTICLE", "url": "https://www.lunasec.io/docs/blog/log4j-zero-day/" }
]주요 type 값: ADVISORY, ARTICLE, DETECTION, REPORT, FIX, INTRODUCED, PACKAGE, EVIDENCE, WEB.
CVE와 OSV 비교
| 항목 | CVE/NVD | OSV |
|---|---|---|
| 주 용도 | 취약점 식별·공개 | 오픈소스 패키지 취약점 자동화 매칭 |
| 영향 버전 표현 | CPE (비정형) | affected[].ranges (구조적) |
| 멀티 생태계 | 어렵다 | affected[] 배열로 지원 |
| 버전 비교 | 수동 파싱 필요 | SEMVER/ECOSYSTEM/GIT |
| 관계 연결 | 없음 | aliases, related, upstream |
| 관리 주체 | MITRE/NIST | OpenSSF + 각 DB |
실제 레코드 예: Log4Shell
Log4Shell(CVE-2021-44228)의 OSV 레코드를 단순화하면 이렇다.
{
"schema_version": "1.3.0",
"id": "GHSA-jfh8-c2jp-hdmh",
"aliases": ["CVE-2021-44228"],
"published": "2021-12-10T00:00:00Z",
"modified": "2023-04-11T01:46:00Z",
"summary": "Remote code execution in Log4j2",
"affected": [
{
"package": {
"ecosystem": "Maven",
"name": "org.apache.logging.log4j:log4j-core"
},
"ranges": [
{
"type": "ECOSYSTEM",
"events": [
{ "introduced": "2.0-beta9" },
{ "fixed": "2.15.0" }
]
}
]
}
],
"severity": [
{
"type": "CVSS_V3",
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H"
}
]
}2.0-beta9 이상 2.15.0 미만의 모든 버전이 영향받는다는 사실을 기계가 명확히 읽을 수 있다.
Open Questions
- OSV 1.7.5 기준이며, 이후 버전에서
upstream필드 처리 방식이 변경될 수 있음. - CVSS v4.0 보급률은 아직 낮아 대부분의 레코드는 CVSS v3.1 기준.
References
- https://ossf.github.io/osv-schema/
- https://github.com/ossf/osv-schema/blob/main/docs/schema.md
- https://osv.dev/
- https://openssf.org/blog/2023/05/02/getting-to-know-the-open-source-vulnerability-osv-format/
- https://nvd.nist.gov/general/cve-process
- https://google.github.io/osv.dev/data_quality.html
- https://github.com/google/osv-scanner