컨테이너 보안 · 이미지 취약점 · 이론
스캔 결과가 깨끗하다는 것이 안전하다는 뜻은 아니다
한 줄 요약
이미지 스캐너가 하는 일은 두 단계뿐입니다. **레이어를 풀어 설치된 패키지 목록을
만들고, 그 이름과 버전을 취약점 DB 와 대조합니다.** 이미지를 실행하지도, 코드를
분석하지도 않습니다.
왜 이게 필요했나
스캐너를 마법 상자로 여기면 두 가지 잘못된 결론에 도달합니다. "스캔이 깨끗하니
안전하다"와 "1,247건이 나왔으니 다 고쳐야 한다". 둘 다 스캐너가 무엇을 하는지
모르는 데서 나옵니다.
동작 원리를 알면 한계도 자동으로 나옵니다.
(a) 패키지 메타데이터가 없으면 안 보입니다. 데비안 계열이면/var/lib/dpkg/status, RPM 계열이면 RPM DB, 언어 런타임이면 락파일을 읽습니다.
그래서 Dockerfile 에서 curl | tar xz 로 집어넣은 바이너리는 SBOM 에도 스캔
결과에도 나타나지 않습니다. 이것이 스캔 결과가 깨끗하다는 것이 안전하다는
뜻이 아닌 첫 번째 이유입니다.
(b) 목록에 있으면 실행 여부와 무관하게 보고됩니다. 애플리케이션이 한 번도
호출하지 않는 tar 의 취약점도 그대로 올라옵니다.
어떻게 동작하나
실제 수치로 보면 감이 옵니다. payments:1.4.2 (debian 12.6) 을 스캔하면Total: 1247 (LOW 812, MEDIUM 289, HIGH 137, CRITICAL 9) 가 나옵니다.
여기에 --ignore-unfixed --severity CRITICAL,HIGH 를 걸면 Total: 4 가 되고,
알려진 악용 목록(KEV)과의 교집합은 1건입니다.
정리하면 이렇습니다. **1,247건이 4건이 됐습니다. 아무것도 안전해지지 않았지만,
지금 조치할 수 있는 항목만 남았습니다.**
그리고 진짜 해법은 패치가 아니라 베이스 교체입니다.
| 베이스 | 크기 | 감지 패키지 | 수정가능 CRITICAL | HIGH |
| --- | --- | --- | --- | --- |
| node:22 | 1.12GB | 432 | 9 | 137 |
| node:22-slim | 231MB | 118 | 2 | 24 |
| node:22-alpine | 148MB | 41 | 0 | 3 |
| distroless/nodejs22 | 187MB | 19 | 0 | 1 |
| 정적 바이너리 + scratch | 24MB | 0 | 0 | 0 |
1,247개를 없애는 것은 패치가 아니라 베이스 이미지 교체입니다. 그리고 판단
기준은 이 한 문장입니다 — 애플리케이션이 실제로 링크하는 공유 라이브러리가 8개인데
이미지에 패키지가 432개 들어 있다면, 문제는 취약점이 아니라 이미지 구성입니다.
현장에서 만나는 모습
게이트 정책은 이 딜레마에서 출발합니다. **Critical 전부에서 실패시키면 개발이
멈춥니다. 실패시키지 않으면 아무도 보지 않습니다.** 실무에서 자리 잡는 타협은
수정본이 존재하는 Critical/High 에서만 실패시키는 것입니다. 고칠 수 없는
것으로 빌드를 세우면 사람들은 게이트를 끄는 법을 먼저 배웁니다. 그리고 예외에는
반드시 만료일(expired_at)을 붙여야 합니다. 예외가 조용히 영구화되는 것이
게이트가 무력해지는 가장 흔한 경로입니다.
우선순위는 CVSS 점수만으로 정해지지 않습니다.
CVE-2021-44228 epss 0.9444CVE-2023-45853 epss 0.00412CVE-2024-5535 epss 0.00196셋 다 CVSS 로는 Critical 등급입니다. 실제 우선순위는
악용 가능성 × 노출 여부 × 도달 가능성으로 정해집니다.
SBOM 포맷은 두 갈래입니다. SPDX 는 Linux Foundation 이 만들고 ISO/IEC 5962:2021
표준이 되었으며 라이선스 컴플라이언스 쪽 뿌리가 깊습니다. CycloneDX 는 OWASP 에서
시작해 ECMA-424 가 되었고 보안 취약점 관리에 초점이 맞춰져 있습니다. 다만 SBOM 의
진짜 용도는 문서 보관이 아니라 사고 당일 5분입니다. 새 취약점이 터졌을 때
40개 서비스 중 어디에 그 패키지가 몇 버전으로 들어 있는지 즉답할 수 있느냐,
그것 하나로 SBOM 의 가치가 결정됩니다.
다음 실습에서 할 것
패키지 인벤토리를 직접 만들어 베이스와 런타임 이미지를 비교하고, 늘어난 공격
표면을 숫자로 셉니다. SBOM 을 손으로 만들어 보고 정책 게이트 스크립트를 작성한
뒤, ENV 로 넣은 토큰이 이미지에 박제되는 것을 확인하고 실행 시점 주입으로
고칩니다.