본문으로 건너뛰기

SCA 스캔

프로젝트에서 사용하는 npm 패키지나 Docker 베이스 이미지에 보안 취약점이 있다면 어떻게 하시겠어요? SCA(Software Composition Analysis)는 컨테이너 이미지와 소프트웨어 의존성에 알려진 취약점(CVE)이 있는지 자동으로 분석해주는 기능입니다. 현대 애플리케이션은 코드의 80% 이상이 오픈소스 라이브러리로 구성되므로, 그중 하나라도 취약점이 있으면 전체가 위험해질 수 있습니다. SCA는 이런 숨겨진 위험을 자동으로 찾아줍니다.

SCA 스캔 결과

개요​

  • 분석 대상: 컨테이너 이미지, 의존성 패키지
  • 분석 엔진: Trivy + Dependency-Check (함께 실행해 결과를 합칩니다. 도구를 고르는 선택지는 없습니다)
  • 취약점 DB: NVD CVE 데이터베이스, Trivy DB 등
  • 함께 요청되는 스캔: 이미지 SBOM 및 라이선스 정보 (SCA의 부산물은 아니지만 이미지 SCA 실행 시 같은 이미지에 대해 함께 요청됨. SBOM · 라이선스 탭에서 단독 실행도 가능)

항목마다 어떤 도구가 탐지했는지 배지로 표시됩니다. 백엔드가 Trivy와 Dependency-Check를 함께 실행해 결과를 합치기 때문입니다. 한 도구만 탐지한 항목에는 '[도구명] 단독' 배지가, 두 도구가 모두 탐지한 항목에는 '교차검증 (Trivy + Dependency-Check)' 배지가 붙습니다. 사용자가 도구를 선택하는 토글은 제공되지 않습니다.


분석 대상​

SCA는 다양한 유형의 패키지와 이미지를 분석합니다.

이미지 취약점​

Docker 이미지에 포함된 모든 패키지를 분석합니다.

  • OS 패키지: Alpine, Debian, Ubuntu 등의 시스템 패키지 (apt, apk로 설치된 패키지)
  • 언어 패키지: npm, pip, maven, go 등 언어별 패키지 매니저로 설치된 패키지
  • 베이스 이미지: Dockerfile의 FROM 절에 지정된 베이스 이미지 자체의 취약점

의존성 취약점​

프로젝트의 의존성 파일을 분석합니다.

  • package-lock.json (Node.js)
  • requirements.txt, Pipfile.lock (Python)
  • pom.xml, build.gradle (Java)
  • go.sum (Go)
  • Gemfile.lock (Ruby)
  • composer.lock (PHP)

package.json만으로는 실제 설치된 버전을 알 수 없지만, package-lock.json 같은 lock 파일에는 정확한 설치 버전이 기록되어 있어 취약한 버전을 정확히 탐지할 수 있습니다.


Step 1: SCA 스캔 시작하기​

  1. 사이드바의 "보안" 그룹 > [보안 분석] 메뉴를 클릭합니다.
  2. 페이지 상단의 카드 캐러셀에서 분석할 서비스를 선택합니다.
  3. SCA 탭을 선택합니다.
  4. 상단 이미지 테이블에서 분석할 이미지 행의 [스캔] (또는 이미 스캔된 경우 [재스캔]) 버튼을 클릭하면 스캔 옵션 모달이 열리며, 모달에서 스캔 시작을 클릭하여 확정합니다. 현재 배포된 모든 이미지를 한 번에 점검하려면 상단 트리거 바의 배포 이미지 스캔 버튼을 사용합니다.

/security?id={서비스ID}&area=sca URL로 진입하면 해당 서비스의 SCA 탭이 바로 열립니다.


Step 2: 스캔 대상 설정​

2.1 이미지 선택 (2가지 방식)​

분석할 컨테이너 이미지를 두 가지 방식 중 하나로 지정합니다.

  • 빌드 이미지 드롭다운: 해당 서비스에서 빌드된 이미지 목록에서 선택 (권장)
  • 수동 입력: 전체 이미지 경로를 직접 입력 (예: harbor.company.com/project/app:v1.2.3)

상단 이미지 테이블에서 선택한 이미지가 결과 영역과 연동되어, 여러 이미지가 있을 때 대상 이미지를 전환할 수 있습니다.

2.2 Registry 인증 자동 적용​

  • 선택한 이미지가 속한 레지스트리에 저장된 인증 정보가 있으면 자동으로 적용됩니다.
  • 사용자가 별도로 자격증명을 입력할 필요 없이, 저장된 인증 정보가 백엔드로 자동 전송됩니다.
  • 인증이 필요한 Private 레지스트리도 별도 입력 없이 곧바로 스캔할 수 있습니다.

VEX Hub 필터는 항상 적용되며 화면에서 끄거나 켤 수 없습니다.

이미지 SCA를 실행하면 이미지 SBOM과 라이선스 분석이 같은 이미지에 대해 함께 요청됩니다. 다만 SBOM은 SCA의 부산물이 아니라 별개 스캔이므로 결과는 SBOM / 라이선스 탭에서 확인합니다. 소스 SBOM은 함께 요청되지 않으며 그 탭에서 직접 실행해야 합니다. 자세한 내용은 SBOM 생성 문서를 참조하세요.


Step 3: 스캔 실행​

스캔이 시작되면 Trivy가 실행되고, AST 백엔드는 Dependency-Check를 병렬로 함께 실행합니다. 두 도구의 결과는 합집합으로 병합되며, 각 CVE에는 어떤 도구가 탐지했는지가 함께 기록됩니다. 진행률은 WebSocket을 통해 실시간으로 표시됩니다.

[1/4] Pulling image...                 ← 이미지 다운로드
[2/4] Scanning OS packages... ← OS 패키지 분석
[3/4] Scanning application packages... ← 애플리케이션 패키지 분석
[4/4] Applying VEX filters... ← VEX 적용
Scan completed! ← 완료

(위 박스는 진행 단계를 이해하기 위한 일반화된 예시이며, KIOPS 콘솔의 실제 출력 형식과 정확히 일치하지 않습니다. UI에는 코드에 정의된 stage 라벨이 표시됩니다.)

이미지 SCA를 실행하면 이미지 SBOM(CycloneDX 1.6)과 라이선스 분석이 같은 이미지에 대해 함께 요청됩니다. 개별 이미지의 [스캔] 버튼과 상단 [배포 이미지 스캔] 버튼 모두 동일하게 동작합니다.

다만 SBOM은 SCA의 부산물이 아니라 별개의 독립 스캔입니다. 그래서 다음이 성립합니다.

  • SBOM 스캔이 실패해도 CVE 스캔 결과에는 영향이 없습니다(반대도 마찬가지).
  • SBOM 결과는 CVE 결과보다 늦게 도착할 수 있습니다.
  • 소스 코드 SBOM은 SCA로 만들어지지 않습니다. SBOM · 라이선스 탭에서 직접 실행하세요.
  • 라이선스 분석은 SBOM 스캔에 포함되며 결과는 license_analysis 테이블에 누적 저장됩니다.

자세한 내용은 SBOM 생성 문서를 참조하세요.

예상 스캔 시간​

스캔 시간은 환경(이미지 크기, 네트워크 속도, 패키지 수, 취약점 DB 캐시 상태 등)에 따라 다릅니다. 아래 값은 일반적인 환경을 가정한 참고치입니다.

분석 서버를 새로 배포한 직후에는 Dependency-Check가 취약점 데이터베이스를 내려받아야 해서 첫 스캔이 평소보다 오래 걸릴 수 있습니다. 데이터베이스는 한 번 받으면 유지되므로 이후 스캔에는 영향이 없습니다.

  • 100MB 이하: 약 30초
  • 100-500MB: 1-2분
  • 500MB 이상: 2-5분

Step 4: 결과 확인​

4.1 결과 요약​

스캔이 완료되면 다음 정보를 한눈에 확인할 수 있습니다.

  • 총 취약점: 탐지된 취약점의 총 개수
  • 심각도 분포: Critical/High/Medium/Low별 취약점 수
  • 수정 가능: 패키지 업데이트로 수정할 수 있는 취약점 수
  • 탐지 도구: 각 항목에 실제 탐지 도구가 표시됩니다. 한 도구만 탐지한 항목은 '[도구명] 단독'(예: Trivy 단독, Dependency-Check 단독) 배지로, 두 도구가 모두 탐지한 항목은 '교차검증 (Trivy + Dependency-Check)' 배지로 표시됩니다. 모든 항목에 도구명이 표시되므로 어느 도구의 결과인지 추적할 수 있습니다.

4.2 카테고리별 결과 보기​

각 취약점은 다음 상태로 분류 및 처리할 수 있습니다.

  • open: 새로 발견된 미처리 항목
  • resolved: 수정 완료
  • false_positive: 오탐으로 확인됨
  • accepted_risk: 위험 수용 (인지했으나 수정하지 않음)

4.3 취약점 상세​

각 취약점을 클릭하면 다음 정보를 확인할 수 있습니다.

  • CVE ID: 취약점의 고유 식별자 (예: CVE-2021-44228)
  • 패키지명: 취약점이 있는 패키지 이름
  • 현재 버전: 현재 설치된 버전
  • 수정 버전: 취약점이 수정된 버전 (있는 경우)
  • 심각도: CVSS 점수 기반 심각도
  • 설명: 취약점에 대한 상세 설명
  • 참조 링크: NVD, 공급사 보안 권고 등의 추가 정보

"수정 버전"이 표시된 취약점은 패키지를 업데이트하면 해결되므로, 수정 버전이 없는 취약점보다 먼저 처리하면 빠르게 취약점 수를 줄일 수 있습니다.


Step 5: SCA 스캔 이력 보기​

SCA는 매 스캔 결과를 누적하여 보관합니다. [보안 분석] 페이지에서 SCA 탭의 "스캔 이력" 섹션을 확인하면 다음을 볼 수 있습니다.

  • 이미지 저장소별 부모 행: 이미지 저장소 단위로 그룹화되며, 최신 스캔의 심각도 카운트가 표시됩니다.
  • 태그별 이력 펼치기: 부모 행을 펼치면 태그별 스캔 이력이 최신순으로 나열되고, 직전 스캔 대비 취약점 증감이 함께 표시됩니다.
  • 스캔/재스캔 트리거: 각 행의 [스캔] / [재스캔] 버튼으로 해당 이미지에 대한 스캔을 바로 실행할 수 있습니다.
  • 우선순위 배지: 현재 배포 중인 이미지와 최근 빌드된 이미지에는 배지가 표시되어, 어떤 이미지를 먼저 점검해야 하는지 쉽게 파악할 수 있습니다.
  • "보는 중" 라벨: 선택된 이미지 행에는 눈 아이콘과 함께 파란색 "보는 중" 라벨이 표시되어, 결과 영역에 표시되고 있는 이미지를 시각적으로 명시합니다.

대시보드 및 보안 게이트의 위험도는 현재 배포된 이미지 기준으로만 계산됩니다. 이전 빌드나 미배포 이미지의 취약점은 현재 위험도에 반영되지 않으므로, 새 빌드를 배포하면 게이트 판정이 달라질 수 있습니다.


VEX Hub 필터링 (항상 켜져 있음)​

VEX란?​

VEX(Vulnerability Exploitability eXchange)는 특정 취약점이 실제로 해당 제품에 영향을 미치는지를 평가한 데이터입니다. 취약한 함수가 코드에 존재하더라도 실제로 그 함수가 호출되지 않으면 영향이 없습니다.

동작 방식​

  • SCA 스캔에는 VEX Hub 필터가 항상 적용되며, 화면에서 끄거나 켤 수 없습니다.
  • 사용자가 UI에서 VEX 필터를 켜고 끄는 토글은 제공되지 않습니다.
  • VEX 판정 결과는 SBOM에 함께 기록됩니다.

필터링 상태​

  • Affected: 실제로 영향받음 - 조치가 필요합니다.
  • Not Affected: 영향받지 않음 - VEX 판정에 의해 제외됩니다.
  • Fixed: 이미 수정됨 - 최신 버전에서는 해결되었습니다.
  • Suppressed: VEX 또는 사용자 처리에 의해 표시에서 제외된 항목

취약점 수정​

패키지 업데이트​

가장 일반적인 수정 방법은 취약점이 해결된 버전으로 패키지를 업데이트하는 것입니다.

  1. 스캔 결과에서 "수정 버전"을 확인합니다.
  2. 해당 버전으로 의존성 파일을 업데이트합니다.
    # Node.js 예시
    npm update lodash

    # Python 예시
    pip install --upgrade requests
  3. 이미지를 다시 빌드합니다.
  4. 재스캔하여 취약점이 해결되었는지 확인합니다.

베이스 이미지 자체에 취약점이 많다면 더 최신 버전이나 다른 이미지로 변경하는 것이 효과적입니다. Alpine Linux는 최소한의 패키지만 포함해 취약점이 적은 편입니다.

# 취약한 버전
FROM node:16-alpine3.14

# 수정된 버전
FROM node:20-alpine3.19

문제 해결​

스캔 실패​

  • 이미지 풀 실패: 저장된 레지스트리 자격증명이 만료되었거나 권한이 부족할 수 있습니다. 인증정보 설정에서 자격증명을 갱신하세요.
  • 타임아웃: 이미지 크기가 너무 큰 경우 스캔이 타임아웃될 수 있습니다. 이미지 최적화를 고려하세요.
  • DB 업데이트 실패: 취약점 데이터베이스 업데이트에 실패한 경우입니다. 네트워크 연결을 확인하고 다시 시도해보세요.

과다 탐지 (너무 많은 취약점)​

취약점이 너무 많이 탐지되어 관리가 어렵다면 확인된 항목을 false_positive 또는 accepted_risk로 분류하여 노이즈를 줄이세요. 베이스 이미지를 더 안전한 이미지로 교체하는 것도 효과적입니다.


관련 가이드​