오픈소스 의존성이 공격 경로가 된다 — DevSecOps·SBOM으로 소프트웨어 공급망 보안 구축하기
2021년 12월, Log4Shell이 터지던 날 밤을 아직도 잊지 못합니다. 팀 전체가 "우리 서비스 어디에 Log4j 있어?"를 외치며 의존성 트리를 뒤지고 있었고, 그 작업에만 이틀이 꼬박 걸렸습니다. 나중에 SBOM이라는 개념을 제대로 파고들면서 알게 됐는데, SBOM이 갖춰져 있었다면 그 이틀이 채 몇 분으로 줄었을 겁니다. 그 차이가 실제 장애 시간, 실제 비즈니스 손실과 직결된다는 걸 그때 뼈저리게 느꼈습니다.
지금 이 글을 읽는 분 중에 "보안은 보안팀이 하는 거 아닌가요?"라고 생각하시는 분이 계실 수도 있습니다. 하지만 현대 소프트웨어 개발에서는 그 경계가 완전히 무너졌습니다. npm install 한 번 실행하는 순간, 수백 개의 오픈소스 라이브러리가 시스템 안으로 들어옵니다. 그 중 하나에 취약점이 있으면? 공격자 입장에서는 우리가 직접 문을 열어준 셈입니다.
이 글에서는 DevSecOps의 핵심 철학과 SBOM이 왜 지금 가장 중요한 보안 도구인지, 그리고 실제 CI/CD 파이프라인에 어떻게 녹여낼 수 있는지를 함께 살펴봅니다.
핵심 개념
DevSecOps: 보안을 개발 흐름 안으로
DevSecOps는 이름 그대로 Development + Security + Operations의 합성어입니다. 핵심 철학은 "Shift Left Security", 즉 보안 검증을 개발 사이클의 가장 앞쪽으로 당겨오는 것입니다.
기존 방식은 이랬습니다. 개발자가 코드를 다 짜고 → QA 팀이 테스트하고 → 보안팀이 출시 전에 점검하는 구조. 문제는 이 구조에서 보안 이슈가 발견되면 이미 엄청난 공수가 들어간 뒤라는 점입니다. 코드를 갈아엎어야 할 수도 있고, 출시 일정이 밀리기도 합니다. 그래서 점점 "그냥 이 정도면 괜찮겠지"라는 타협이 일어납니다.
DevSecOps는 이 흐름을 바꿉니다.
[코드 커밋] → Secret 탐지 (Gitleaks) → SAST (Semgrep) → SCA (Trivy)
→ [빌드] → SBOM 생성 (Syft/CycloneDX) → SLSA 프로버넌스 생성¹ → 컨테이너 서명 (Cosign)
→ [배포] → SLSA 프로버넌스 검증¹ → DAST → 런타임 모니터링¹ SLSA(Supply-chain Levels for Software Artifacts): 빌드 무결성을 보장하는 레벨 기반 프레임워크입니다. 빌드 단계에서 출처 증명(프로버넌스)을 생성하고, 배포 시점에 이를 검증합니다. 다음 편에서 상세히 다룹니다.
커밋 하나가 올라가는 순간부터 자동으로 보안 레이어가 작동합니다. 개발자 입장에서는 PR을 올렸더니 "이 라이브러리에 CVE 있어요"라는 피드백이 바로 오는 경험을 하게 됩니다. 수정 비용이 가장 낮은 시점에 문제를 잡을 수 있게 되는 것입니다.
이렇게 파이프라인 전반에 보안이 녹아들려면 그 기반이 되는 도구가 필요합니다. 그 핵심이 바로 SBOM입니다.
공급망 보안: 내 코드가 아닌 것들이 문제다
**소프트웨어 공급망(Software Supply Chain)**이란 소스 코드, 오픈소스 의존성, 빌드 시스템, 아티팩트, 배포 파이프라인 전체를 포함하는 개념입니다. 공격자는 이 중 가장 약한 고리 하나를 노립니다.
2020년 말 SolarWinds 사건이 공급망 보안을 전 세계에 각인시킨 사례입니다. 공격자는 SolarWinds의 빌드 파이프라인에 침투해 정상적인 소프트웨어 업데이트에 SUNBURST 백도어를 심었습니다. 18,000개 이상의 고객사가 "공식 업데이트"를 설치하면서 자기도 모르게 감염된 것입니다. 빌드 파이프라인 자체가 공격 대상이 될 수 있다는 사실을 뼈저리게 깨달은 사건이었습니다.
Log4Shell은 또 다른 형태입니다. Apache Log4j 2라는 Java 로깅 라이브러리의 RCE(원격 코드 실행) 취약점이었는데, 이 라이브러리가 전 세계 수억 개 시스템에 퍼져 있었습니다. 많은 팀이 자기 서비스가 Log4j를 사용하는지조차 몰랐고, 그 이유가 정확히 SBOM이 없었기 때문입니다.
이런 공급망 위협에 대응하는 첫 번째 도구가 SBOM입니다.
SBOM: 소프트웨어 성분표
SBOM(Software Bill of Materials)은 내 소프트웨어를 구성하는 모든 컴포넌트의 목록입니다. 식품 포장지 뒷면의 성분표와 똑같은 개념으로, "이 소프트웨어에는 어떤 라이브러리가, 어떤 버전으로, 어떤 라이선스로 들어가 있는가"를 기계가 읽을 수 있는 형식으로 명세합니다.
SBOM 표준 형식은 크게 세 가지입니다. 솔직히 처음엔 뭘 골라야 할지 꽤 헷갈렸는데, 막상 써보면 도구 두 개 돌려보고 더 결과가 잘 나오는 걸로 가면 됩니다.
| 표준 | 주도 기관 | 특징 |
|---|---|---|
| SPDX | Linux Foundation | ISO/IEC 5962 국제 표준, 범용 |
| CycloneDX | OWASP Foundation | 보안 분석 최적화, GitLab 공식 채택 |
| SWID | NIST | 엔터프라이즈 소프트웨어 자산 관리 |
새로 시작하신다면 CycloneDX나 SPDX 중 하나를 고르시면 됩니다. GitLab을 쓰신다면 CycloneDX가 자연스럽게 통합되고, GitHub Actions 생태계라면 SPDX가 더 편합니다.
규제 의무화: 지금 당장 준비해야 하는 이유
규제가 본격적으로 움직이기 시작했습니다. 미국은 2021년 행정명령 EO 14028을 통해 연방정부에 납품하는 소프트웨어에 SBOM 제공을 의무화했습니다. EU는 2024년 12월 사이버 복원력 법(CRA)이 발효되어 2026년 말이면 전면 적용됩니다. 디지털 제품을 판매하는 제조사라면 SBOM 제공, 취약점 처리, 보안 설계 원칙 준수가 법적 의무가 됩니다.
숫자로도 체감이 됩니다. 2026년 현재 DevSecOps 시장 규모는 86억~109억 달러에 달하며, SBOM 관리 시장은 연평균 22.1% 성장세를 이어가고 있습니다. "대기업 얘기"가 아니라 우리 팀 얘기가 되어가고 있습니다.
실전 적용
잠깐: 아래 예시 중 컨테이너나 CI/CD가 아직 낯선 분이라면(프론트엔드나 데이터 엔지니어링 쪽이라면), 예시 1과 예시 4만 먼저 적용해보셔도 충분합니다. 예시 2, 3은 컨테이너 이미지를 빌드하는 환경에서 더 직접적으로 활용됩니다.
예시 1: GitHub Actions에서 SBOM 자동 생성하기
가장 빠르게 시작해볼 수 있는 방법은 GitHub Actions에 anchore/sbom-action을 붙이는 것입니다. PR이 올라올 때마다 자동으로 SBOM을 생성하고 아티팩트로 저장합니다.
사전 준비: GitHub Actions가 활성화된 레포지토리면 충분합니다. 별도 설치 없이 바로 사용 가능합니다.
# .github/workflows/sbom.yml
name: Generate SBOM
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
sbom:
runs-on: ubuntu-latest
permissions:
contents: read # 아티팩트 업로드만 할 경우 read로 충분합니다
steps:
- name: Checkout
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Generate SBOM (SPDX)
uses: anchore/sbom-action@v0
with:
format: spdx-json
output-file: sbom.spdx.json
- name: Generate SBOM (CycloneDX)
uses: anchore/sbom-action@v0
with:
format: cyclonedx-json
output-file: sbom.cyclonedx.json
- name: Upload SBOM artifact
uses: actions/upload-artifact@v4
with:
name: sbom-files
path: |
sbom.spdx.json
sbom.cyclonedx.json이렇게 하면 매 빌드마다 SBOM 파일이 생성되어 아티팩트로 저장됩니다. Log4Shell 같은 사태가 터졌을 때 "우리 서비스에 영향이 있나?"를 수 분 안에 확인할 수 있게 됩니다. 실제로 이 차이가 이틀과 몇 분의 차이입니다.
예시 2: Trivy로 컨테이너 이미지 취약점 스캔 + SBOM 연동
Trivy는 컨테이너 이미지, 파일시스템, Git 레포지토리를 통합 스캔할 수 있는 도구입니다. CNCF 졸업 프로젝트이기도 하고, 저도 팀에서 가장 먼저 도입한 도구 중 하나입니다.
사전 준비: 로컬 테스트라면 brew install trivy (macOS) 또는 공식 설치 스크립트로 설치할 수 있습니다. CI/CD 예시는 컨테이너 이미지가 이미 빌드되어 있어야 합니다.
# 컨테이너 이미지 취약점 스캔
trivy image --severity HIGH,CRITICAL myapp:latest
# SBOM 생성 (CycloneDX 형식)
trivy image --format cyclonedx --output sbom.json myapp:latest
# 기존 SBOM 파일로 취약점 매칭
trivy sbom sbom.jsonCI/CD 파이프라인에 녹이면 이렇게 됩니다.
# GitHub Actions 예시
# 실제 사용 시 @master 대신 SHA 해시로 고정하는 것을 강력히 권장합니다
- name: Scan container image
uses: aquasecurity/trivy-action@master # SHA 해시로 교체 필요
with:
image-ref: myapp:${{ github.sha }}
format: table
exit-code: 1 # CRITICAL 발견 시 빌드 실패
severity: CRITICAL,HIGH
- name: Generate SBOM from image
run: |
trivy image \
--format cyclonedx \
--output sbom-${{ github.sha }}.json \
myapp:${{ github.sha }}exit-code: 1 설정이 중요합니다. CRITICAL 취약점이 발견되면 빌드 자체를 실패시켜서 해당 이미지가 배포되지 않도록 막는 것입니다. 처음엔 오탐이 많아서 개발팀이 불만을 가질 수 있는데, .trivyignore 파일로 예외 처리를 관리하면서 점진적으로 수위를 높이는 방식을 권장합니다.
예시 3: Cosign으로 컨테이너 이미지 서명하기
빌드한 이미지가 배포 과정에서 변조되지 않았다는 것을 어떻게 보장할 수 있을까요? Sigstore의 Cosign이 그 답입니다. 키리스(keyless) 서명을 지원해서 별도의 키 관리 없이도 서명할 수 있습니다.
키가 없는데 어떻게 안전한지 궁금하실 수 있습니다. GitHub Actions의 OIDC 토큰이 단기 수명(ephemeral) 인증서 역할을 하기 때문에, 장기 비밀 키를 어딘가에 저장하지 않아도 됩니다. 토큰 자체가 곧 만료되니 탈취되더라도 재사용이 불가능한 구조입니다.
사전 준비: brew install cosign (macOS) 또는 공식 설치 가이드로 Cosign을 설치하고, GHCR(GitHub Container Registry) 로그인이 필요합니다.
# Cosign 설치
brew install cosign
# GitHub Actions에서 키리스 서명 (OIDC 기반)
cosign sign --yes ghcr.io/myorg/myapp:latest
# 서명 검증 (Cosign v2 문법 — 정확한 identity 지정)
cosign verify \
--certificate-identity "https://github.com/myorg/myapp/.github/workflows/release.yml@refs/heads/main" \
--certificate-oidc-issuer "https://token.actions.githubusercontent.com" \
ghcr.io/myorg/myapp:latest
# 여러 브랜치/태그를 허용할 경우 regexp 옵션 활용
cosign verify \
--certificate-identity-regexp "^https://github.com/myorg/myapp/" \
--certificate-oidc-issuer "https://token.actions.githubusercontent.com" \
ghcr.io/myorg/myapp:latestGoogle은 GKE 클러스터에 Binary Authorization 정책을 적용해서 서명되지 않은 컨테이너는 아예 배포가 안 되도록 막고 있습니다. Kubernetes 클러스터를 운영하신다면 이런 방향을 고려해보시면 좋습니다.
예시 4: GitHub Actions 서드파티 액션 보안 강화
2025년 3월, tj-actions/changed-files 액션에 악성 코드가 삽입되는 사건이 있었습니다. 수천 개의 레포지토리가 영향을 받았고, CI/CD 파이프라인이 처리하던 클라우드 자격증명과 API 토큰 등 민감한 시크릿이 빌드 로그를 통해 유출됐습니다. 많은 팀이 uses: tj-actions/changed-files@v35처럼 태그를 참조했는데, 태그는 언제든 다른 커밋을 가리키도록 변경될 수 있다는 게 문제였습니다.
# 위험한 방식 — 태그는 변조 가능
- uses: actions/checkout@v4
# 안전한 방식 — SHA 해시는 불변
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2SHA 해시로 고정하면 해당 커밋이 정확히 어떤 코드인지 보장됩니다. 귀찮아 보이지만, Dependabot이나 Renovate를 설정해두면 자동으로 업데이트 PR을 올려줘서 관리 부담이 많이 줄어듭니다.
장단점 분석
장점
| 항목 | 내용 |
|---|---|
| 취약점 가시성 | 어떤 컴포넌트에 CVE가 있는지 즉시 파악 가능 |
| 인시던트 대응 속도 | Log4Shell 같은 사태에서 영향받은 시스템을 수 분 내 특정 |
| 규정 준수 | EU CRA, 미국 EO 14028 등 법적 요건 충족 |
| 신뢰 체계 확립 | 소프트웨어 공급자-구매자 간 투명성 확보 |
| 자동화 기반 | CI/CD 통합으로 사람의 개입 없이 지속적 보안 검증 |
단점 및 주의사항
| 항목 | 내용 | 대응 방안 |
|---|---|---|
| 도입 복잡성 | 파이프라인 재설계, 도구 통합, 팀 교육 필요 | 단계적 도입, 작은 프로젝트부터 시작 |
| SBOM 품질 문제 | 자동 생성 SBOM의 전이 의존성 누락 등 정확성 한계 | 여러 도구 병행 사용, 주기적 검증 |
| 오탐(False Positive) | SAST/SCA 도구의 오탐으로 개발 속도 저하 가능 | .trivyignore 등으로 관리, 점진적 기준 강화 |
| 운영 오버헤드 | SBOM 생성·보관·갱신의 지속적 관리 부담 | 아티팩트 저장소 자동화, 보존 정책 설정 |
| 표준 분산 | SPDX vs CycloneDX 선택 및 상호운용성 관리 | 도구 선택 후 일관성 유지, 변환 도구 활용 |
**SCA(Software Composition Analysis)**는 오픈소스 의존성을 분석해 알려진 취약점(CVE)을 탐지하는 기법입니다. SAST(Static Application Security Testing)가 직접 작성한 코드의 보안 결함을 찾는 것과 구별됩니다.
**CVE(Common Vulnerabilities and Exposures)**는 공개된 보안 취약점의 공통 식별 체계입니다.
CVE-2021-44228이 Log4Shell의 공식 식별자입니다.
실무에서 가장 흔한 실수
-
SBOM을 한 번만 생성하고 업데이트하지 않는 것입니다. SBOM은 살아있는 문서입니다. 의존성이 바뀔 때마다 재생성되어야 의미가 있습니다. CI/CD 파이프라인에 붙여서 자동화하지 않으면 결국 아무도 관리하지 않는 파일이 됩니다.
-
처음부터 모든 파이프라인에 강한 정책을 적용하는 것입니다. HIGH 취약점이 발견될 때마다 빌드를 실패시키면, 초기에는 배포가 막혀서 팀 전체가 혼란에 빠질 수 있습니다. CRITICAL만 차단하는 것부터 시작해서 점진적으로 기준을 높이는 방식을 권장합니다.
-
서드파티 GitHub Actions 액션을 태그로만 참조하는 것입니다. 앞서 언급했듯 태그는 변조될 수 있습니다. 특히 비공개 소스 코드를 다루는 워크플로에서는 반드시 SHA 해시로 고정하는 것이 좋습니다.
마치며
SBOM은 단순한 보안 도구가 아니라, 팀과 팀 사이, 공급자와 사용자 사이의 신뢰를 만드는 언어입니다. 그리고 지금은 그 언어를 익혀야 할 시점이기도 합니다.
당장 모든 것을 다 할 필요는 없습니다. 아래 세 단계는 로컬 탐색 → CI/CD 통합 → 파이프라인 보안 강화 순서로 설계되어 있어서, 하나씩 밟아가시면 자연스럽게 쌓입니다.
-
로컬에서 SBOM 생성을 경험해볼 수 있습니다.
brew install syft후syft packages .명령어를 실행해보시면 현재 프로젝트의 의존성 목록이 쭉 나옵니다. "우리 서비스에 이런 라이브러리들이 들어가 있구나"를 처음 확인하는 경험이 꽤 충격적일 수 있습니다. -
CI/CD 파이프라인에 Trivy 스캔을 추가해볼 수 있습니다. GitHub Actions를 쓰신다면
aquasecurity/trivy-action을 워크플로에 붙이는 데 10분이면 충분합니다. 처음엔exit-code없이 결과만 확인하는 모드로 시작하셔도 됩니다. -
GitHub Actions 서드파티 액션을 SHA 해시로 고정하는 것을 권장합니다. 현재 사용 중인
.github/workflows/*.yml파일을 열어서@v3,@v4같은 태그 참조를 SHA 해시로 교체해보시면 좋습니다. Dependabot을 켜두면 자동으로 업데이트 PR이 생성됩니다.
다음 글: SLSA 프레임워크 레벨 1부터 4까지, 빌드 무결성을 단계적으로 확보하는 실전 가이드
참고 자료
- CISA - Software Bill of Materials (SBOM)
- CISA - 2025 Minimum Elements for a Software Bill of Materials
- DevSecOps Trends 2026: AI, Supply Chain & Zero Trust - Practical DevSecOps
- The 2026 Guide to Software Supply Chain Security - Cloudsmith
- SBOMs in 2025: Trends & Predictions - Anchore
- Software Supply Chain Security: SBOM, SLSA, Sigstore (2025) - Elysiate
- The Ultimate Guide to SBOMs - GitLab
- What is an SBOM? - GitHub
- Lessons from Log4Shell: 4 key takeaways for DevSecOps teams - ReversingLabs
- SolarWinds Attack: Play by Play and Lessons Learned - Aqua Security
- SLSA Framework Guide - Practical DevSecOps
- Sigstore - OpenSSF
- Top 5 SBOM Tools 2025 - OX Security