Docker Hardened Image의 VEX 조회하기
Docker Hardened Image의 VEX 조회하기
DHI API의 imagePackagesForImageCoords 쿼리를 사용해 digest별로 Docker Hardened Image(DHI)의 VEX 문과 억제된 CVE를 가져오는 방법을 안내해요.
출처: 문서
본문
이 페이지는 DHI API를 사용해 digest로 Docker Hardened Image(DHI)의 VEX 문과 억제된 CVE를 가져오는 안내 예시예요. imagePackagesForImageCoords 쿼리를 사용하며, 이미지 digest를 받아 모든 패키지, 그 패키지에 대해 보고된 모든 CVE, Docker가 해당 CVE를 억제하는지, 그 이유를 반환해요.
[!NOTE] 일회성 조회나 로컬 스캔 워크플로에는
docker scout vex get이 더 간단할 수 있어요. 여기서 설명하는 API는 많은 이미지를 프로그래밍 방식으로 조회해야 할 때 사용해요.
API 엔드포인트와 인증에 대한 내용은 Use the DHI API 문서를 봐요. 이 페이지는 이미 유효한 토큰이 있다고 가정해요.
억제된 CVE 조회하기
이 예시에서 사용하는 imagePackagesForImageCoords 쿼리는 다음과 같아요. 이미지의 모든 패키지, 그 패키지에 대해 보고된 모든 CVE, Docker가 해당 CVE를 억제하는지 여부를 가져와요.
query BaseVex($ctx: Context!, $q: IpImagePackagesForImageCoordsQuery!) {
imagePackagesForImageCoords(context: $ctx, query: $q) {
imagePackages {
packages {
package {
purl
name
version
vulnerabilities {
sourceId
isExcepted
fixedBy
cvss {
severity
}
vulnerabilityExceptions {
id
sourceType
type
justification
additionalDetails
isDhiStatement
}
}
}
}
}
}
}
변수와 함께:
{
"ctx": { "organization": "your-org" },
"q": {
"digest": "sha256:<platform-manifest-digest>",
"hostName": "hub.docker.com",
"repoName": "your-org/your-repo",
"includeExcepted": true,
"includeNodsa": true
}
}
전체 인수 참조는 imagePackagesForImageCoords를 봐요.
액세스 토큰 가져오기
Use the DHI API에 설명된 대로 조직 액세스 토큰(OAT)이나 개인 액세스 토큰(PAT)을 액세스 토큰으로 교환해요.
$ DHI_API_TOKEN=$(curl -s -X POST https://hub.docker.com/v2/auth/token \
-H "Content-Type: application/json" \
-d "{\"identifier\": \"<identifier>\", \"secret\": \"<token>\"}" \
| jq -r .access_token)
PAT의 경우 identifier에 Docker Hub 사용자 이름을, OAT의 경우 조직 이름을 사용해요.
요청 보내기
Use the DHI API에 설명된 대로 쿼리와 변수를 요청 본문에 결합해요. 다음 예시는 쿼리가 여러 줄에 걸쳐 있으므로 jq를 사용해 본문을 안전하게 만드는 방법을 보여줘요.
$ QUERY='query BaseVex($ctx: Context!, $q: IpImagePackagesForImageCoordsQuery!) {
imagePackagesForImageCoords(context: $ctx, query: $q) {
imagePackages {
packages {
package {
purl
name
version
vulnerabilities {
sourceId
isExcepted
fixedBy
cvss {
severity
}
vulnerabilityExceptions {
id
sourceType
type
justification
additionalDetails
isDhiStatement
}
}
}
}
}
}
}'
$ curl https://api.dso.docker.com/v1/graphql \
-H "Authorization: Bearer ***" \
-H "Content-Type: application/json" \
-d "$(jq -n --arg query "$QUERY" '{
query: $query,
variables: {
ctx: { organization: "your-org" },
q: {
digest: "sha256:<platform-manifest-digest>",
hostName: "hub.docker.com",
repoName: "your-org/your-repo",
includeExcepted: true,
includeNodsa: true
}
}
}')"
조직, digest, 호스트, 저장소를 바꿔 넣어요.
샘플 응답(Sample response)
다음 예시는 단일 패키지로 축약된 것이에요.
{
"package": {
"purl": "pkg:deb/debian/[email protected]%2Bdfsg-3.1%2Bdhi1?os_distro=trixie&os_name=debian&os_version=13",
"name": "tar",
"version": "1.35+dfsg-3.1+dhi1",
"vulnerabilities": [
{
"sourceId": "CVE-2025-45582",
"cvss": { "severity": "MEDIUM" },
"fixedBy": null,
"isExcepted": false,
"vulnerabilityExceptions": []
},
{
"sourceId": "CVE-2026-18477",
"cvss": { "severity": "MEDIUM" },
"fixedBy": null,
"isExcepted": true,
"vulnerabilityExceptions": [
{
"id": "debian-nodsa-CVE-2026-18477",
"sourceType": "EXTERNAL",
"type": "FALSE_POSITIVE",
"justification": null,
"additionalDetails": "Debian NODSA",
"isDhiStatement": false
}
]
}
]
}
}
CVE가 억제되었는지 판단하려면 isExcepted를 사용해요. 전체 응답 필드 참조와 OpenVEX 매핑은 imagePackagesForImageCoords를 봐요.
커스터마이즈 이미지 조회하기
DHI VEX 문은 커스터마이즈 기능으로 빌드한 이미지에 직접 적용돼요. 커스터마이즈된 이미지 자체의 digest를 조회해 그 패키지, CVE, 억제를 한 번의 호출로 가져오면 돼요. 베이스 이미지를 별도로 조회할 필요는 없어요.
주의사항(Caveats)
특정 digest의 억제 집합은 새 권고(advisory)와 평가가 게시됨에 따라 바뀔 수 있어요. 응답을 영구적인 것으로 취급하지 말고, digest별로 짧은 TTL로 결과를 캐시해요.