쓰는 컴포넌트에 CVE 가 떴는지 정기적으로 확인해야 한다. 흔히 두 곳을 잡아 둔다.
- NVD —
https://services.nvd.nist.gov/rest/json/cves/2.0 - OSV —
https://api.osv.dev/v1/query
주소는 둘 다 맞다. 그런데 "NVD 우선, OSV 보완" 이라는 순서는 2026년 기준으로
더 이상 맞지 않는다. NVD 가 2026년 4월에 운영 방침을 바꿨기 때문이다.
이 글은 그 변화를 확인하고, 그래서 무엇을 더 봐야 하는지까지 정리한다.
| 소스 | 무엇에 쓰나 |
|---|---|
| CVE List (cvelistV5) | CVE 원본 기록. 가장 빠르고 빠짐이 없다 |
| NVD | CPE 매칭과 NVD 자체 분석. 2026년부터 전수 분석이 아니다 |
| OSV | 패키지·버전 단위 판정. 언어 생태계 + 리눅스 배포판 |
| GitHub Advisory | 언어 패키지 권고. 영향 버전 범위가 정확하다 |
| 배포판 보안 트래커 | 컨테이너 베이스 이미지의 오탐을 걸러 낸다 |
| CISA KEV | 실제로 악용 중인 취약점. 우선순위 1순위 |
| EPSS | 악용될 확률. 남은 것들의 순서를 정한다 |
참고
이 글의 API 주소와 파라미터는 각 서비스의 공식 문서로 확인한 것이다. 다만
글을 쓴 환경에서 이 API 들로 나가는 통신이 막혀 있어, 응답을 직접 받아
붙이지는 못했다. 명령은 그대로 쓰면 되지만 출력은 각자 확인한다.
1. NVD — 주소는 맞고, 전제가 바뀌었다#
https://services.nvd.nist.gov/rest/json/cves/2.0 이 맞다. CVE 하나를 보는
가장 짧은 형태는 이렇다.
curl -s "https://services.nvd.nist.gov/rest/json/cves/2.0?cveId=CVE-2021-44228" | jq .
정기 점검에 쓸 만한 파라미터는 이 정도다.
| 파라미터 | 쓰임 |
|---|---|
cveId |
CVE 하나를 콕 집어 조회 |
cpeName |
CPE 로 특정 제품·버전에 걸린 CVE |
keywordSearch |
설명 문구 검색 |
lastModStartDate / lastModEndDate |
마지막 조회 이후 바뀐 것만 — 배치에 이걸 쓴다 |
startIndex / resultsPerPage |
페이징 |
API 키를 받는다#
한도가 꽤 빡빡하다.
| 한도 | |
|---|---|
| 키 없이 | 30초 롤링 윈도우당 5회 |
| 키 발급 후 | 30초 롤링 윈도우당 50회 |
키는 nvd.nist.gov/developers/request-an-api-key
에서 받고, 요청에 apiKey 헤더로 넣는다.
curl -s -H "apiKey: $NVD_API_KEY"
"https://services.nvd.nist.gov/rest/json/cves/2.0?lastModStartDate=2026-09-01T00:00:00.000&lastModEndDate=2026-09-08T00:00:00.000"
키가 있어도 NIST 는 요청 사이에 몇 초씩 쉬라고 권한다. 컴포넌트 200개를
한 번에 돌리는 배치라면 이 대기 시간부터 계산에 넣는다.
여기가 중요하다 — 2026년 4월의 방침 변경#
NIST 는 2026년 4월 15일부터 들어오는 CVE 를 전부 분석하지 않는다. CVE 접수량이
2020년에서 2025년 사이 263% 늘어난 것이 이유다. 전면 분석 대상은 셋으로 좁혀졌다.
- CISA KEV 카탈로그에 오른 CVE
- 미 연방정부가 쓰는 소프트웨어의 CVE
- 행정명령 14028 이 정의한 핵심 소프트웨어의 CVE
여기에 못 드는 것은 "Lowest Priority — not scheduled" 로 분류된다. 밀려 있던
약 29,000건도 이 상태로 넘어갔다. 게다가 CNA 가 이미 CVSS 를 매긴 CVE 에는
NVD 가 자기 점수를 따로 붙이지 않는다.
주의
실무에서 이게 무슨 뜻이냐면 — NVD 에서 CVSS 가 안 나온다고 "심각하지 않다"
가 아니다. "아무도 분석하지 않기로 했다" 일 수 있다. NVD 응답만 보고
심각도를 판정하는 파이프라인이 있다면, 점수가 비어 있을 때 어떻게 할지를
정해 두어야 한다. 조용히 통과시키면 안 된다.
NVD 를 버리라는 얘기가 아니다. CPE 매칭은 여전히 NVD 가 제일 낫다. 다만
"공식이니까 여기가 최신이고 제일 완전하다" 는 전제만 버린다.
2. OSV — 주소도 맞고, 지금은 이쪽이 더 실용적이다#
https://api.osv.dev/v1/query 가 맞다. 인증이 없고, 패키지 이름과 버전을
그대로 물어볼 수 있다 는 게 핵심이다. CPE 문자열을 만들 필요가 없다.
curl -s -X POST "https://api.osv.dev/v1/query" -d '{
"package": {"name": "express", "ecosystem": "npm"},
"version": "4.17.1"
}' | jq '.vulns[].id'
CVE 하나만 보려면 GET 이다.
curl -s "https://api.osv.dev/v1/vulns/CVE-2021-44228" | jq .
엔드포인트는 셋이다.
| 엔드포인트 | 메서드 | 쓰임 |
|---|---|---|
/v1/query |
POST | 패키지+버전 하나, 또는 커밋 해시로 조회 |
/v1/querybatch |
POST | 여러 개를 한 번에 — 한 요청에 최대 1,000건 |
/v1/vulns/{id} |
GET | ID 로 상세 조회 |
querybatch 는 ID 와 수정 시각만 돌려주고, 입력과 같은 순서로 온다. 상세가
필요한 것만 골라 /v1/vulns/{id} 로 한 번 더 부른다. 개별 질의가 1,000건을
넘거나 전체가 3,000건을 넘으면 페이지가 나뉘고 next_page_token 이 붙는다.
팁
OSV 는 이제 언어 생태계만 다루지 않는다. Debian, Ubuntu, Alpine, Red Hat,
Rocky, AlmaLinux, SUSE/openSUSE, Chainguard/Wolfi 까지 버전 질의가 된다.
컨테이너 베이스 이미지 점검을 여기서 같이 처리할 수 있다.
3. 빠진 소스들#
두 곳으로는 "이게 진짜 문제인가" 를 판단할 수 없다. 다음이 그 자리를 메운다.
CVE 원본 — cvelistV5#
CVE 기록 자체는 CVE Program 이 GitHub 저장소로 낸다.
github.com/CVEProject/cvelistV5 가
공식 캐시이고 약 7분마다 갱신된다. NVD 가 분석을 미뤄도 원본 기록은 여기 있다.
git clone --depth 1 https://github.com/CVEProject/cvelistV5.git
예전 CSV·XML·CVRF 다운로드는 2024년 6월 30일로 전부 끝났다. 그 형식을 긁던
스크립트가 남아 있다면 지금 동작하지 않는다.
GitHub Advisory Database#
curl -s "https://api.github.com/advisories?ecosystem=npm&severity=critical" | jq '.[].ghsa_id'
공개 권고만 볼 거면 인증 없이도 된다. 언어 패키지의 영향 버전 범위가
정확해서, "우리가 쓰는 4.17.1 이 진짜 걸리는가" 를 판정하기 좋다.
참고
기본 응답에는 악성 패키지(malware)가 빠져 있다. 공급망 쪽까지 보려면
type=malware를 따로 붙여야 한다.
배포판 보안 트래커 — 컨테이너 쓰면 필수#
스캐너가 컨테이너 이미지를 "취약" 이라고 하는데 실제로는 아닌 경우가 많다.
배포판이 패치만 뒤로 이식(backport)하고 버전 번호는 그대로 두기 때문이다.
업스트림 버전 숫자만 보면 안 고쳐진 것처럼 보인다.
같은 CVE-2023-0464 를 NVD 는 HIGH 로, Red Hat 은 Low 로 본다. 어느 쪽이 틀린 게
아니라 보는 대상이 다르다. 그래서 Trivy 같은 스캐너는 배포판 권고를 NVD 보다
우선한다.
| 배포판 | 트래커 |
|---|---|
| Debian | security-tracker.debian.org |
| Ubuntu | ubuntu.com/security/cves |
| Red Hat | access.redhat.com/security/security-updates/cve (OVAL 제공) |
Red Hat 계열은 버전만이 아니라 NEVRA(Epoch:Version-Release) 전체를 OVAL 과
맞춰야 backport 가 제대로 반영된다.
CISA KEV — 우선순위의 출발점#
실제로 악용이 확인된 취약점 목록이다. 하루 한 번 받아서 우리 CVE 목록과
교집합을 내면, 오늘 당장 손볼 것이 나온다.
curl -s "https://www.cisa.gov/sites/default/files/feeds/known_exploited_vulnerabilities.json"
| jq -r '.vulnerabilities[].cveID' > kev.txt
comm -12 <(sort our-cves.txt) <(sort kev.txt)
cisa.gov/kev 로도 들어가진다. 미러가 필요하면
github.com/cisagov/kev-data 가 같은 데이터를
CSV·JSON 으로 낸다.
KEV 는 NVD 방침 변경과도 직접 엮인다. KEV 에 오른 CVE 는 NVD 가 계속 전면
분석하는 세 부류 중 하나다. 뒤집어 말하면 KEV 밖의 CVE 는 NVD 분석을 기대하기
어렵다.
EPSS — 나머지의 순서#
KEV 는 "이미 악용 중" 만 담는다. 그 밖의 수천 건 순서는 EPSS 로 정한다. FIRST 가
매일 갱신하고 인증이 없다.
curl -s "https://api.first.org/data/v1/epss?cve=CVE-2021-44228" | jq '.data[]'
두 값이 나온다.
epss— 앞으로 30일 안에 악용될 확률 (0~1)percentile— 전체 CVE 중 백분위
CVSS 9.8 인데 EPSS 0.0004 인 것과, CVSS 6.5 인데 EPSS 0.7 인 것 중 뭘 먼저
고쳐야 하는지는 명확하다. CVSS 는 심각도이지 시급성이 아니다.
국내 — KNVD, 보호나라#
국내 공지가 필요하면 KISA 의 취약점 정보 포털 knvd.krcert.or.kr 과 보호나라
보안공지를 본다. 다만 이쪽은 웹 페이지 기준이고, 공개 REST API 는 확인하지
못했다. 자동화가 필요하면 위 국제 소스를 파이프라인에 두고, 국내 공지는 사람이
읽는 쪽으로 분리하는 편이 현실적이다.
4. 그래서 어떻게 조합하나#
세 단으로 나눈다. 한 소스가 전부를 하려 들면 실패한다.
1단 — 무엇이 걸렸나 (탐지)
컴포넌트 목록(SBOM)을 OSV querybatch 에 밀어 넣는다. 컨테이너 이미지면 배포판
권고까지 OSV 가 같이 본다. 언어 패키지는 GitHub Advisory 로 버전 범위를 한 번 더
확인한다.
2단 — 진짜인가 (검증)
배포판 트래커에서 backport 여부를 본다. 여기서 걸러지는 게 컨테이너 오탐의 대부분이다.
상세가 필요하면 NVD 로 CPE 매칭을, 원본이 필요하면 cvelistV5 를 본다.
3단 — 뭘 먼저 (우선순위)
KEV 교집합을 최우선으로 올린다. 남은 것은 EPSS 로 줄을 세운다. CVSS 는 그다음이다.
주의
NVD 를 1단(탐지)에 두지 않는다. 2026년 4월 이후 NVD 는 전수 분석을 하지
않으므로, 탐지 기준을 NVD 로 잡으면 분석되지 않은 CVE 를 통째로 놓친다.
NVD 는 2단(검증)에서 쓴다.
확인#
파이프라인을 짜고 나면 아는 CVE 하나로 전 구간을 통과시켜 본다. Log4Shell
(CVE-2021-44228) 이 편하다 — 모든 소스에 다 있고 KEV 에도 올라 있다.
CVE=CVE-2021-44228
echo "--- OSV ---"; curl -s "https://api.osv.dev/v1/vulns/$CVE" | jq -r '.id, .severity'
echo "--- NVD ---"; curl -s -H "apiKey: $NVD_API_KEY"
"https://services.nvd.nist.gov/rest/json/cves/2.0?cveId=$CVE" | jq -r '.totalResults'
echo "--- EPSS ---"; curl -s "https://api.first.org/data/v1/epss?cve=$CVE" | jq -r '.data[].epss'
echo "--- KEV ---"; curl -s "https://www.cisa.gov/sites/default/files/feeds/known_exploited_vulnerabilities.json"
| jq -r --arg c "$CVE" '.vulnerabilities[] | select(.cveID==$c) | .dateAdded'
네 줄이 다 값을 내면 연결은 끝난 것이다. 그다음엔 일부러 최근 CVE 로도 한 번
해 본다. NVD 만 비어 나오는 경우를 직접 봐 두면, 위에서 말한 "점수가 없는 것과
안전한 것은 다르다" 가 손에 남는다.
NVD 한도도 확인해 둔다. 키 없이 30초에 6번을 부르면 막힌다. 배치가 컴포넌트
수에 비례해 커진다면 여기서 먼저 터진다.
정리#
- 두 주소는 맞다.
services.nvd.nist.gov/rest/json/cves/2.0과api.osv.dev/v1/query둘 다 유효하다. - "NVD 우선" 이라는 순서만 뒤집는다. 2026년 4월부터 NVD 는 KEV·연방 소프트웨어·EO 14028 핵심 소프트웨어만 전면 분석한다. 탐지는 OSV 로, NVD 는 검증용으로 쓴다.
- 점수가 없는 것과 안전한 것을 구분한다. NVD 응답의 빈 CVSS 를 "이상 없음" 으로 처리하는 코드가 있다면 지금 고친다.
- 탐지와 우선순위는 다른 소스가 답한다. 무엇이 걸렸는지는 OSV 가, 뭘 먼저 고칠지는 KEV 와 EPSS 가 답한다. CVSS 하나로 줄을 세우면 순서가 틀린다.
- 컨테이너를 쓴다면 배포판 트래커는 선택이 아니다. backport 를 모르면 스캐너 결과의 상당수가 오탐이고, 그 오탐이 진짜를 덮는다.
참고
사내에 Black Duck 같은 상용 SCA 가 이미 있다면, 그건 이 API 들과 하는 일이
다르다. 여기 소스들은 이름과 버전을 알아야 물어볼 수 있고, 상용 SCA 는
파일에서 컴포넌트를 먼저 알아낸다. 그 차이는
Black Duck 은 어떻게 검사하나에서 따로 다룬다.

댓글