본문으로 건너뛰기

소프트웨어 구성 분석 (SCA)

SCA란

소프트웨어에 포함된 오픈소스 컴포넌트를 분석해 알려진 취약점(CVE)을 탐지하는 기법입니다. SBOM을 기반으로 의존성 전체를 추적하고 신규 CVE 발견 시 즉시 대응합니다. SBOM이 무엇인지는 SBOM 기본에 있습니다.

아래 설정은 예시입니다 — 작동하는 전체 구현은 참조 저장소에

이 페이지의 YAML·명령은 핵심을 보여주는 예시입니다. 복사해 바로 쓸 수 있는 전체 파이프라인(정책 파일·샘플 앱 포함)은 Best Practice 저장소에서 확인하세요.


SBOM 생성 — syft

기본 사용법

Bash
# CycloneDX JSON 생성 (권장)
syft . -o cyclonedx-json=sbom.cdx.json

# SPDX JSON 생성
syft . -o spdx-json=sbom.spdx.json

# 컨테이너 이미지 분석
syft nginx:latest -o cyclonedx-json=sbom.cdx.json

포맷 선택

포맷주관권장 용도
CycloneDX JSONOWASP보안·취약점 관리 (grype 연동)
SPDX JSONLinux Foundation공급망 공유·규제 대응

보안 파이프라인 중심이라면 CycloneDX JSON을 권장합니다.

cdxgen

CycloneDX 프로젝트가 직접 만드는 또 다른 생성기입니다. syft 가 디스크에 있는 파일을 읽는다면 cdxgen 은 언어별 패키지 관리자를 통해 의존성을 해석합니다. 그래서 파일 기반 스캔이 보지 못하는 의존성까지 복원할 수 있습니다. lockfile 이 없거나 의존성 트리가 빌드 시점에야 확정되는 프로젝트에서 차이가 납니다. 30종이 넘는 생태계를 지원하며 CycloneDX 를 바로 내보냅니다.

Bash
# 현재 프로젝트의 CycloneDX JSON 생성
npx @cyclonedx/cdxgen@latest -o sbom.cdx.json

TRUSCA 는 생성기로 cdxgen 을 씁니다. 둘 중 무엇을 고를지는 빌드가 의존성을 설치 시점에 확정하는지(syft 로 충분), 빌드 시점에 확정하는지(cdxgen 이 놓치는 것을 복원)로 갈립니다.


취약점 스캔 — grype

GitHub Actions 전체 워크플로우

YAML
# .github/workflows/sca.yml

name: SCA — SBOM & Vulnerability Scan

on:
pull_request:
branches: [main, develop]

jobs:
sca:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7

- name: Generate SBOM
uses: anchore/sbom-action@v0
with:
format: cyclonedx-json
output-file: sbom.cdx.json

- name: Scan vulnerabilities
uses: anchore/scan-action@v7
with:
sbom: sbom.cdx.json
fail-build: true
severity-cutoff: high
config: .grype.yaml

- name: Upload SBOM artifact
uses: actions/upload-artifact@v7
with:
name: sbom-${{ github.sha }}
path: sbom.cdx.json
retention-days: 90

GitLab CI

YAML
# .gitlab-ci.yml (sca 잡 부분)

sca:
stage: test
image: ubuntu:22.04
script:
# ubuntu 기본 이미지에는 curl이 없음
- apt-get update -qq && apt-get install -y -qq curl ca-certificates
- curl -sSfL https://get.anchore.io/syft
| sh -s -- -b /usr/local/bin
- curl -sSfL https://get.anchore.io/grype
| sh -s -- -b /usr/local/bin
- syft . -o cyclonedx-json=sbom.cdx.json
- grype sbom:sbom.cdx.json --fail-on high --config .grype.yaml
artifacts:
paths:
- sbom.cdx.json
expire_in: 90 days
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
grype 가 sbom format not recognized 를 낼 때

syft 1.51 이상은 CycloneDX 1.7 을 냅니다. grype 는 0.118 이상에서만 이 버전을 읽습니다. 두 도구를 함께 올리거나, 올릴 수 없으면 syft ... -o cyclonedx-json@1.6 으로 낮춰 생성하세요.

cicd-quick 워크플로와의 차이

AI 코딩 — 30분 완성 Quick CI/CD에도 같은 구조의 워크플로가 있습니다. 그쪽을 이미 적용했다면 아래 세 가지만 더하면 이 페이지의 구성이 됩니다.

항목Quick CI/CD이 페이지
아티팩트 보관기본값(90일 미만일 수 있음)retention-days: 90, expire_in 90일
스캔 정책 파일없음.grype.yaml 지정으로 예외 관리
금지 라이선스 검사셸 스크립트로 SBOM 문자열 검색없음(라이선스는 정책 게이트로 분리)

Quick CI/CD 는 30분 안에 첫 게이트를 세우는 것이 목적이고, 이 페이지는 예외 관리와 증적 보관까지 다룹니다. 두 워크플로를 함께 두지 말고 하나만 남기세요.


취약점 정책 설계

심각도별 SLA

아래는 CI 게이트 운영에 맞춘 조직 강화안 예시입니다. KWG 기준선(Critical 1주, High 4주)과 대응 기한의 정본은 취약점 대응 기한과 VEX를 참조하세요.

심각도CVSS 범위강화안 SLA 예시빌드 차단
Critical9.0–10.024시간차단
High7.0–8.97일차단
Medium4.0–6.930일경고만
Low0.1–3.9다음 릴리즈무시

처음 도입 시에는 Critical만 차단하고 팀이 익숙해진 뒤 High로 확대하는 것을 권장합니다.

grype 정책 파일

무시 규칙은 반드시 이유와 승인일을 기록하세요

감사(Audit) 대응 시 근거 없는 예외는 오히려 컴플라이언스 리스크가 됩니다.

YAML
# .grype.yaml

fail-on-severity: high

ignore:
# 실제 코드 경로 미사용 — 보안팀 승인 2024-01-15
- vulnerability: CVE-2023-XXXXX
reason: '해당 함수 미사용 확인'
# 테스트 전용 패키지
- package:
name: some-test-lib
type: npm

Trivy

Aqua Security 가 만드는 또 다른 스캐너입니다. NVD, OSV, GHSA, EPSS, KEV 를 하나로 합친 데이터베이스를 함께 배포하므로 악용 확률과 실제 악용 여부가 조회를 한 번 더 하지 않아도 탐지 결과에 함께 옵니다. SBOM 파일뿐 아니라 컨테이너 이미지와 IaC 도 검사합니다.

Bash
# 이미 만들어 둔 SBOM 검사
trivy sbom sbom.cdx.json

# 프로젝트를 직접 검사
trivy fs --scanners vuln,license .

TRUSCA 는 대조 엔진으로 Trivy 를 씁니다. 탐지 결과에 CVSS 와 함께 EPSS, KEV 가 붙는 이유입니다.


개발자 워크스테이션도 스캔 범위입니다

지금까지의 대상은 저장소와 컨테이너 이미지였습니다. 코드가 들어오는 경로는 하나 더 있습니다. 개발자가 IDE 에 설치하는 확장입니다. 확장은 개발자 권한으로 실행되어 소스와 자격증명에 접근하지만 package.json 이나 lockfile 에 나타나지 않으므로 위의 SCA 결과에는 잡히지 않습니다.

  • GlassWorm 은 2025-10 Open VSX 마켓플레이스에서 확산해 설치 3만 5,800건을 기록했고 2025-11 에 2차로 재발했습니다. 2026-03 에는 전이 의존성을 통한 변형으로 확장 72개가 영향을 받았고, 여기에 Claude Code 와 Codex 를 사칭한 확장이 포함됐습니다.
  • MaliciousCorgi 는 2026-01 VS Code 마켓플레이스에서 AI 확장으로 위장해 약 150만 개발자에게 영향을 줬습니다.
  • JetBrains 마켓플레이스에서도 악성 AI 플러그인 15개가 2026-06 확인됐습니다.

실무에서는 세 가지를 같이 둡니다. 조직 정책으로 확장 allowlist 를 강제하고, 설치 목록을 주기적으로 다시 확인하며, 설치 전에 게시자와 연결된 저장소를 확인합니다. 이 통제를 MCP 서버와 에이전트 스킬까지 묶어 정리한 내용은 에이전트와 MCP 도구 거버넌스의 도구·확장 공급망 절에 있습니다.


게시 경로와 설치 경로도 공격면입니다

앞의 스캔은 이미 들어온 패키지를 검사합니다. 공격은 그 앞뒤 두 지점에서도 일어납니다. 패키지를 레지스트리에 올리는 게시 경로와, 내려받은 패키지가 설치 도중 스크립트를 실행하는 설치 경로입니다.

게시: 장기 토큰 대신 trusted publishing

메인테이너의 npm 토큰이 유출되면 정상 패키지의 새 버전으로 악성 코드가 배포됩니다. 2025년 하반기 이후 npm 공급망 공격 상당수가 이 경로를 썼습니다. npm 은 이후 토큰 정책을 강화해 classic token 을 폐기했고, 현재 공식 문서는 granular access token 만 지원한다고 안내합니다(2025-11 기준).

대안은 trusted publishing 입니다. CI 워크플로가 OIDC 로 레지스트리에 자신을 증명하고 그 자리에서 받은 단기 자격으로 게시하므로, 저장소 시크릿에 장기 토큰을 둘 필요가 없습니다. 게시본에는 어느 워크플로에서 나왔는지 기록한 출처(provenance) 증명이 --provenance 플래그 없이 자동으로 붙습니다. 현재 GitHub Actions, GitLab CI/CD, CircleCI 의 클라우드 러너에서 쓸 수 있고 self-hosted 러너는 아직 지원되지 않습니다. PyPI 와 RubyGems 도 같은 방식을 제공합니다.

YAML
# .github/workflows/publish.yml — npm trusted publishing
jobs:
publish:
runs-on: ubuntu-latest
permissions:
id-token: write # OIDC 토큰 발급에 필요
contents: read
steps:
- uses: actions/checkout@v7
- run: npm ci --ignore-scripts
- run: npm publish # NODE_AUTH_TOKEN 없이 게시

다만 출처 증명은 "이 빌드가 선언된 파이프라인에서 나왔다"만 보장합니다. 파이프라인 자체가 침해되면 증명은 그대로 유효한 채 악성 빌드가 나갑니다. 2026-05 Mini Shai-Hulud 에서 악성 패키지 84개가 유효한 SLSA Build Level 3 증명을 달고 배포된 것이 그 사례입니다.

설치: install 훅은 임의 코드 실행 지점입니다

npm 패키지는 설치 도중 preinstall, install, postinstall 스크립트를 자동으로 실행합니다. Shai-Hulud 계열(2025-09 최초, 2025-11 2.0, 2026-05 Mini, 2026-08 CHAINDROP)과 postmark-mcp 사건은 모두 이 훅으로 실행 시점을 확보했습니다. npm install 한 번이 곧 남의 코드 실행이라는 뜻입니다.

  • CI 에서는 npm ci --ignore-scripts 로 설치하고, 빌드에 스크립트가 꼭 필요한 패키지만 따로 실행합니다.
  • pnpm 은 기본값이 이미 차단입니다. 검토해서 허용한 패키지만 allowBuilds(pnpm 11 이전에는 onlyBuiltDependencies)에 적습니다.
  • 사내 반입 게이트를 운영한다면 install 훅이 있는 패키지를 검토 대상으로 표시합니다. 게이트 구성은 오픈소스 프로세스: 사용부터 배포까지의 3-1 절을 참조하세요.

에이전트가 설치하는 MCP 서버와 스킬도 같은 설치 경로를 지나갑니다. 이 통제를 도구 쪽으로 확장한 내용은 에이전트와 MCP 도구 거버넌스의 도구·확장 공급망 절에 있습니다.


VEX 활용

VEX(Vulnerability Exploitability eXchange)란: 특정 CVE가 해당 제품에서 실제로 악용 가능한지를 기계가 읽을 수 있는 형식으로 명시하는 문서입니다. "CVE는 존재하지만 해당 코드 경로 미사용"을 공식적으로 표현해 하위 공급망의 불필요한 알림을 방지합니다.

실무 활용: CycloneDX VEX, OpenVEX, CSAF, SPDX 3.0 네 형식이 실제로 쓰이고 있으며, 아직 하나로 수렴하지는 않았습니다. 납품처가 지정한 형식이 없다면 이미 만든 CycloneDX SBOM과 같은 CycloneDX vulnerabilities 필드로 시작하는 편이 도구 연계가 가장 쉽습니다. 상태값 4가지 등 개념 정리는 취약점 대응 기한과 VEX가 정본입니다.


SBOM 보관 정책

보관 위치: CI/CD 아티팩트로 저장하고 릴리즈 태그와 연결해 버전별 SBOM을 추적합니다. GitHub Actions upload-artifact, GitLab artifacts.paths를 활용합니다.

보관 기간: ISO/IEC 18974는 프로그램 존속 기간 동안 보존을 요구합니다. 실무적으로는 릴리즈 버전별 영구 보관을 권장합니다.

업데이트 시점: 의존성 변경 시마다 재생성합니다. PR 단위 자동 생성으로 항상 최신 상태를 유지합니다.


SBOM 분석기

syft·trivy·cdxgen으로 생성한 SBOM 파일을 업로드하면 취약점을 분석하고 대응 가이드를 자동으로 생성합니다.

먼저 샘플로 미리보기 (API 키 불필요)

같은 데모를 5분 빠른 시작에서도 열 수 있습니다. 아래에서 바로 확인한 뒤 본인 SBOM으로 실제 분석을 진행하세요.

내 SBOM으로 실제 분석하기

이 도구는 Anthropic API 키가 필요합니다

브라우저에서 직접 Anthropic API를 호출합니다. 본인의 Anthropic API 키를 입력하면 바로 사용할 수 있으며, 키와 입력 내용은 브라우저에서 Anthropic으로만 전송됩니다(trustedoss 서버를 거치지 않습니다). 사용량은 본인 Anthropic 계정에 과금됩니다.


실제 운영 사례

TRUSCA 의 sca-self.yml 은 cdxgen 으로 CycloneDX SBOM 을 생성한 뒤 Trivy 로 스캔하는 흐름을 매일 돌립니다. 도구를 버전 고정으로 설치하고 체크섬까지 확인합니다.

PR 단계 검사와 별도로 스케줄 실행을 두는 이유는, 배포 시점에 없던 취약점이 나중에 공개되기 때문입니다. 이 부분은 지속적 모니터링에서 이어집니다.

셀프 스터디

Claude Code로 SBOM 심층 분석

위 분석기는 브라우저에서 바로 사용 가능합니다. 더 상세한 분석과 .grype.yaml 정책 파일 자동 생성이 필요하면 아래 agent를 사용하세요.

사전 조건: Trusted OSS 저장소 클론 필요

Bash
cd agents/sbom-vuln-analyst
claude

agent가 아래를 자동으로 수행합니다.

  • CycloneDX / SPDX / grype 결과 자동 감지
  • 심각도별 분류 및 수정 버전 제시
  • .grype.yaml 예외 처리 예시 생성
  • CI/CD 파이프라인 연동 안내

다음 단계

매일 돌리는 SCA 엔진이 필요하다면

위 분석기는 한 번씩 결과를 확인하는 용도입니다. 팀 전체가 상시 운영하는 self-hosted SCA가 필요하면, 취약점(CVE)·라이선스·SBOM을 한 UI에서 관리하는 Apache-2.0 도구 TRUSCA로 이어갈 수 있습니다.

  • 직접 띄워 보기: TRUSCA 저장소 (Docker Compose 또는 Helm 배포)
  • 예산·인력·폐쇄망 제약이 있는 환경에서 상시 운영 SCA를 갖추는 경로입니다.

TRUSCA 포털에서 공개 데모 인스턴스를 열어 볼 수 있습니다. 다만 데모는 화면을 둘러보는 용도이므로, 실제 운영은 위 가이드로 본인 환경에 띄워야 합니다.