공급사 SBOM 제출 가이드

SK텔레콤에 소프트웨어를 공급하는 파트너사를 위한 SBOM 생성 및 제출 가이드입니다.

SK텔레콤은 소프트웨어 공급망의 투명성과 보안성을 강화하기 위해, 공급사로부터 납품받는 모든 소프트웨어 구성 요소 및 의존성에 대한 SBOM(Software Bill of Materials) 제출을 요청드리고 있습니다. 본 가이드는 공급사가 SK텔레콤의 보안 정책에 맞는 형식으로 SBOM을 생성하고 제출하는 방법을 안내합니다.

빠른 시작: 제출까지 5단계

  1. 제출 요구사항에서 허용 포맷(CycloneDX JSON 권장)과 필수 데이터 필드를 확인합니다.
  2. BomLens로 SBOM을 생성합니다. 자체 도구 체계를 이미 운영한다면 SBOM 생성 방법의 오픈소스 도구 안내를 참고하세요.
  3. OS 위에 애플리케이션을 얹어 납품하는 서버라면 SBOM 생성 방법의 서버 납품 절에 따라 층별로 생성해 함께 제출합니다.
  4. 검증 체크리스트로 PURL과 전이 의존성 포함 여부를 점검합니다.
  5. 제출 절차에 따라 파일명을 정하고 제출합니다.

타사가 제조한 상용 소프트웨어나 완제품을 공급해 소스코드에 접근할 수 없다면, 2~3단계 대신 상용 소프트웨어 공급에 따라 제조사로부터 SBOM을 받아 제출합니다. 제출한 SBOM이 반려되면 자주 발생하는 반려 사유에서 원인별 해결 방법을 확인합니다.

적용 대상

다음 형태의 소프트웨어를 납품하는 모든 공급사(개발사, 리셀러 포함)는 본 가이드라인의 적용을 받습니다.

  • 소스코드: Java, Python, JavaScript, Go, C/C++ 등으로 작성된 애플리케이션
  • 컨테이너 이미지: Docker 이미지 또는 OCI 호환 컨테이너
  • 실행 파일: 컴파일된 바이너리(.jar, .dll, .so) 및 라이브러리
  • 임베디드 시스템: 펌웨어 이미지, RootFS(추출한 루트 파일시스템), 디바이스 드라이버
  • 서버: OS(rootfs와 설치 패키지) 위에 애플리케이션이 결합된 시스템
  • 상용 소프트웨어·완제품: 타사가 제조한 패키지 소프트웨어 또는 어플라이언스 장비 (리셀러·총판 공급 포함)

SBOM 제출 프로세스

공급사는 계약 시점부터 최종 납품까지 아래의 절차에 따라 진행하시기 바랍니다.

flowchart TD
    A[계약 검토] --> B["소프트웨어 개발/빌드"]
    B --> C{SBOM 생성}
    C -->|SKT 제공 도구 활용| D[BomLens 활용]
    C -->|자체 도구 활용| E["오픈소스 도구 활용<br>(cdxgen, Syft 등)"]
    C -->|상용 완제품 공급| K[제조사 SBOM 수령]
    D --> F["데이터 검증 (PURL 확인)"]
    E --> F
    K --> F
    F --> G["SBOM 제출 (이메일/지정 채널)"]
    G --> H[SKT 보안성 검토]
    H -->|승인| I[납품 완료]
    H -->|반려| J[보완 및 재제출]
    J --> F

    classDef start fill:#F2F2F2,stroke:#171717,color:#171717,stroke-width:1.5px
    classDef proc fill:#ffffff,stroke:#c8c8c8,color:#171717,stroke-width:1px
    classDef decision fill:#FFF3CD,stroke:#E0A800,color:#5A4100,stroke-width:1.5px
    classDef good fill:#D9F0E4,stroke:#00A651,color:#0A5A32,stroke-width:1.5px
    classDef danger fill:#FDE1E7,stroke:#EA002C,color:#8A0019,stroke-width:1.5px
    classDef vendor fill:#FFF3CD,stroke:#E0A800,color:#5A4100,stroke-width:1.5px

    class A start
    class B,E,F,G proc
    class C,H decision
    class D,I good
    class J danger
    class K vendor

관련 문서

1 - SBOM 제출 요구사항

SK텔레콤 정책에 따른 표준 SBOM 형식, 필수 포함 정보, PURL 식별자 규칙을 상세히 정의합니다.

1. 표준 데이터 형식

SK텔레콤은 글로벌 표준으로 자리 잡은 두 가지 형식을 모두 지원합니다. 공급사는 사용하는 도구가 지원하는 형식을 선택하여 제출할 수 있습니다.

형식버전권장 용도파일 형식
CycloneDXv1.3, v1.4, v1.5, v1.6, v1.7애플리케이션 보안, 취약점 관리 중심JSON (권장), XML
SPDXv2.2, v2.3라이선스 컴플라이언스 중심JSON, Tag-Value

참고: 두 형식 모두 동등하게 인정되나, 내부 시스템 연동성을 위해 CycloneDX (JSON) 형식을 권장합니다.

요구 수준 요약

각 항목의 요구 수준입니다. 필수 항목이 누락되면 반려됩니다. 권장 항목은 없어도 반려되지 않지만 포함을 권합니다.

항목수준상세
표준 포맷과 버전 (CycloneDX 또는 SPDX)필수1. 표준 데이터 형식
메타데이터 (생성 일시, 생성 도구, 최상위 컴포넌트)필수2.1 메타데이터
컴포넌트 이름과 버전필수2.2 컴포넌트 정보
직접·전이적 의존성 포함필수2.3 의존성 범위
PURL(Package URL, 소프트웨어 패키지를 표준 형식으로 가리키는 식별자. pkg: 형식, 규격에 정의된 타입, 네임스페이스 필수 타입은 생략 불가)필수3. PURL 준수
개발 전용 의존성권장2.3 의존성 범위
라이선스 정보권장4. 샘플 문서

합격 기준을 충족하는 예시 SBOM 파일 (CycloneDX 1.6 JSON)을 내려받아 구조를 비교해 보시기 바랍니다.

2. 필수 포함 정보

제출하는 SBOM 문서에는 다음 정보가 반드시 포함되어야 합니다. 정보가 누락되면 반려될 수 있습니다.

2.1 메타데이터 (Metadata)

문서 자체와 생성 도구에 대한 정보입니다.

  • Timestamp: 생성 일시 (ISO 8601 형식)
  • Tool Info: 생성 도구의 벤더, 이름, 버전 (예: CycloneDX-Maven-Plugin v2.7.9)
  • Component Info: 납품하는 최상위 소프트웨어의 명칭 및 버전

Component Info의 명칭 값은 장비·제품을 특정할 수 있는 고유한 값이어야 합니다. 빈 값, .처럼 의미 없는 값, 생성 도구가 자동으로 채우는 고정 경로 값(예: /scan)은 다른 제출 건과 값이 겹쳐 등록이 거부됩니다. SK텔레콤은 이 값을 제출 건 전체에서 고유해야 하는 식별자로 취급합니다.

파일 이름과 일치

여러 층(OS·애플리케이션 등)으로 나눠 제출하는 경우, 각 층의 최상위 컴포넌트 이름과 버전은 그 SBOM 파일 이름의 앞부분({이름}_{버전})과 같은 값이어야 합니다. 예를 들어 파일 이름이 myserver-os_1.0.0_bom.json이면 metadata.component.name(CycloneDX) 또는 DocumentName(SPDX)은 myserver-os, 버전은 1.0.0이어야 합니다.

재제출할 때는 이 이름을 그대로 유지하시기 바랍니다. 이 이름이 스캔의 식별자이므로, 이름이 바뀌면 이전 제출분이 지워지지 않고 남아 이미 조치한 취약점이 계속 집계됩니다.

BomLens로 생성하면 --project와 --version 값이 이 필드에 자동으로 채워지므로 따로 손댈 필요가 없습니다. 층별 파일 이름 규칙은 오픈소스 도구 활용의 층별로 제출 절을 참고하세요.

생성 도구 명시 형식

생성 도구 정보는 형식에 따라 다음 필드에 기재해야 합니다.

  • SPDX: creationInfo.creators 필드에 Tool: 접두어로 도구명과 버전 기재
  • CycloneDX: metadata.tools 배열에 vendor, name, version 기재
// SPDX creationInfo 예시
"creationInfo": {
  "created": "2026-04-06T03:22:00Z",
  "creators": ["Tool: Syft-0.98.0", "Organization: VendorName"]
}

2.2 컴포넌트 정보 (Components)

소프트웨어를 구성하는 개별 라이브러리 정보입니다.

  • Name: 컴포넌트 이름 (예: commons-lang3)
  • Version: 컴포넌트 버전 (예: 3.12.0) — 필수. SPDX는 versionInfo, CycloneDX는 version 필드에 정확한 버전을 기재합니다. 버전이 없으면 취약점 매핑이 불가능합니다.
  • PURL (Package URL): [필수] 패키지 식별자

2.3 의존성 범위 (Dependency Scope)

중요: 전이적 의존성(Transitive Dependencies)을 반드시 포함해야 합니다.

SK텔레콤은 제출된 SBOM을 기반으로 취약점을 분석합니다. 직접 의존성만 포함된 SBOM은 숨겨진 취약점을 놓칠 수 있으므로 반려될 수 있습니다.

의존성 종류설명포함 여부
직접 의존성 (Direct)프로젝트가 직접 선언한 라이브러리필수
전이적 의존성 (Transitive)직접 의존성이 다시 의존하는 라이브러리필수
개발 전용 의존성 (Dev-only)테스트, 빌드 도구 등 런타임 미포함 라이브러리권장 포함

전이적 의존성이란?

예를 들어 프로젝트가 library-A를 직접 사용하고, library-A가 내부적으로 library-B를 사용하는 경우, library-B가 전이적 의존성입니다. library-B에 취약점이 있어도 SBOM에 포함되지 않으면 탐지할 수 없습니다.

올바른 SBOM 생성을 위한 전제 조건

전이적 의존성이 정확하게 포함되려면 빌드(또는 패키지 설치)가 완료된 상태에서 SBOM을 생성해야 합니다. 소스코드만 있는 상태에서는 전이적 의존성이 누락될 수 있습니다.

  • Java (Maven): mvn package 또는 mvn dependency:resolve 실행 후 생성
  • Java (Gradle): ./gradlew dependencies 실행 후 생성
  • Python: pip install -r requirements.txt (가상환경 활성화) 후 생성
  • Node.js: npm install 또는 yarn install 실행 후 생성
  • Go: go mod download 실행 후 생성

각 도구별 전이적 의존성 포함 방법은 오픈소스 도구 활용 가이드를 참고하시기 바랍니다.

3. Package URL (PURL) 준수

PURL(Package URL)은 소프트웨어 패키지를 고유하게 식별하기 위한 표준 URL 형식입니다. SK텔레콤의 취약점 분석 시스템은 PURL을 기준으로 동작하므로, 모든 컴포넌트에 유효한 PURL이 포함되어야 합니다.

여기서 컴포넌트는 SBOM의 components 목록(개별 라이브러리·패키지)을 뜻하며, 최상위 제품 자체(SBOM 메타데이터의 컴포넌트 정보)에는 적용되지 않습니다.

PURL은 반드시 pkg: 접두어로 시작하는 표준 형식이어야 합니다. name:version, org/repo:tag 등 자유 텍스트는 허용되지 않으며, 이 경우 취약점 매핑이 불가능해 반려됩니다.

형식이 유효해 보여도 매칭에 실패하는 PURL이 있습니다. 아래 세 규칙은 스키마 검사로는 걸러지지 않으므로 특히 주의하시기 바랍니다.

3.1 규격에 정의된 타입

타입 자리에는 Package URL 규격이 정의한 타입만 쓸 수 있습니다. maven, npm, pypi, rpm처럼 생태계와 조회할 저장소를 특정하는 이름이며, 전체 목록은 규격 저장소의 purl-types-index.json에서 확인할 수 있습니다.

규격에 없는 이름을 임의로 넣으면(예: pkg:applications/java@11.0.25) 형식 검사는 통과하지만 어느 저장소를 조회해야 할지 판단할 수 없어 매칭이 실패합니다. 생태계를 특정하지 못하는 pkg:generic/도 같은 이유로 허용되지 않습니다.

3.2 네임스페이스가 필수인 타입

네임스페이스는 타입과 패키지 이름 사이의 자리입니다. 규격이 이 자리를 필수로 정한 타입은 다음과 같습니다.

alpm apk bitbucket composer deb git github golang huggingface maven qpkg rpm swift vscode-extension

이 자리가 비면 형식은 유효해 보여도 패키지를 특정할 수 없어 매칭이 되지 않고 반려됩니다. 실제 접수에서 가장 많이 발견되는 유형은 다음 두 가지입니다.

  • Maven: groupId가 네임스페이스에 와야 합니다. pkg:maven/org.slf4j/jcl-over-slf4j@2.0.15가 올바른 형태이고, groupId와 artifactId를 점으로 이어 붙인 pkg:maven/org.slf4j.jcl-over-slf4j@2.0.15는 저장소에 존재하지 않는 좌표라 반려됩니다.
  • OS 패키지(rpm, deb, apk): 배포판이 네임스페이스에 와야 합니다(pkg:rpm/rhel/bind@9.11.36-16.el8_10.6).

배포판 값은 반드시 이 위치(네임스페이스)에 있어야 인식됩니다. 물음표 뒤 쿼리 파라미터(예: ?distro=rhel-8.10)에 넣는 것은 인정되지 않습니다. 이 값은 부가 정보로만 취급되어 매칭에 쓰이지 않으며, 네임스페이스가 비어 있으면 위와 똑같이 반려됩니다.

3.3 네임스페이스에 들어갈 값

네임스페이스에는 저장소가 실제로 쓰는 식별자를 그대로 넣어야 합니다. 사람이 읽는 회사 이름이나 URL은 식별자가 아닙니다. 생성 도구가 매니페스트의 벤더 문자열을 groupId 자리에 그대로 옮기면 pkg:maven/The%2BApache%2BSoftware%2BFoundation/poi@5.4.1이나 pkg:maven/http%3A/www.jboss.org/jbossxts@1.1 같은 형태가 되는데, 둘 다 저장소에 없는 좌표라 매칭되지 않습니다. Maven이라면 pkg:maven/org.apache.poi/poi@5.4.1처럼 실제 groupId를 기재해야 합니다.

3.4 언어별 PURL 예시

생태계PURL 형식 예시
Java (Maven)pkg:maven/org.springframework/spring-core@5.3.20
JavaScript (NPM)pkg:npm/express@4.18.2
Python (PyPI)pkg:pypi/django@4.1.0
Gopkg:golang/github.com/gin-gonic/gin@v1.8.1
.NET (NuGet)pkg:nuget/Newtonsoft.Json@13.0.1
Ruby (RubyGems)pkg:gem/rails@7.0.4
GitHub (Actions·소스 호스팅)pkg:github/actions/checkout@v3
OS 패키지 (RPM)pkg:rpm/centos/glibc@2.17-317.el7?arch=x86_64

3.5 올바른 / 잘못된 PURL 예시

잘못된 예올바른 예
commons-lang3:3.12.0pkg:maven/org.apache.commons/commons-lang3@3.12.0
actions/checkout:v3pkg:github/actions/checkout@v3
lodash@4.17.21pkg:npm/lodash@4.17.21
pkg:generic/foo@1.0(생태계에 맞는 타입으로 변경)
pkg:applications/java@11.0.25(규격에 정의된 타입으로 변경)
pkg:maven/org.slf4j.jcl-over-slf4j@2.0.15pkg:maven/org.slf4j/jcl-over-slf4j@2.0.15
pkg:maven/The%2BApache%2BSoftware%2BFoundation/poi@5.4.1pkg:maven/org.apache.poi/poi@5.4.1
pkg:rpm/bind@9.11.36-16.el8_10.6pkg:rpm/rhel/bind@9.11.36-16.el8_10.6
pkg:rpm/bind@9.11.36-16.el8_10.6?distro=rhel-8.10pkg:rpm/rhel/bind@9.11.36-16.el8_10.6

PURL에 대한 자세한 사양은 Package URL 공식 스펙을 참고하시기 바랍니다.

4. 샘플 문서

CycloneDX 샘플

{
  "bomFormat": "CycloneDX",
  "specVersion": "1.6",
  "version": 1,
  "metadata": {
    "timestamp": "2026-04-06T10:30:00Z",
    "tools": [{
      "vendor": "Example Corp",
      "name": "cyclonedx-maven-plugin",
      "version": "2.7.9"
    }],
    "component": {
      "type": "application",
      "name": "PaymentModule",
      "version": "2.1.0",
      "purl": "pkg:maven/com.example/payment-module@2.1.0"
    }
  },
  "components": [{
    "type": "library",
    "name": "spring-core",
    "version": "5.3.20",
    "purl": "pkg:maven/org.springframework/spring-core@5.3.20",
    "licenses": [{
      "license": {
        "id": "Apache-2.0"
      }
    }]
  }]
}

참고 자료

관련 문서

2 - BomLens

BomLens로 SK텔레콤 정책에 맞는 SBOM을 생성하는 방법을 안내합니다.

BomLens

BomLens는 공급사가 Docker 환경에서 SK텔레콤 정책에 맞는 산출물을 생성할 수 있는 오픈소스 도구입니다. 로컬에 언어별 도구를 따로 설치하지 않아도 여러 언어를 분석해 CycloneDX(JSON) 산출물을 만듭니다.

이 페이지는 빠른 시작만 다룹니다. 설치, 전체 옵션, 언어별 가이드, 입력 시나리오, 웹 UI 등 자세한 내용은 공식 저장소 문서를 참고하세요.

github.com/sktelecom/bomlens

버그 제보, 기능 제안, Pull Request 기여를 환영합니다.

생성되는 산출물

한 번의 실행으로 다음 네 가지가 함께 {프로젝트}_{버전}/ 하위 폴더에 생성됩니다(--all 옵션). 오픈소스위험분석보고서는 --no-report로 끌 수 있으며, 적합성 리포트는 항상 생성됩니다(현재 끄는 옵션 없음).

산출물파일용도
SBOM{프로젝트}_{버전}_bom.jsonCycloneDX 1.6 구성요소 명세 (납품 기준 산출물)
오픈소스 고지문{프로젝트}_{버전}_NOTICE.{txt,html}라이선스 의무 이행을 위한 고지문
오픈소스위험분석보고서{프로젝트}_{버전}_risk-report.{md,html}라이선스와 취약점 위험 집계
적합성 리포트{프로젝트}_{버전}_conformance.{json,md,html}제출 품질 기준 충족 여부와 누락 항목

적합성 리포트 파일은 매 실행마다 생성되지만, 웹 UI의 통과/실패 판정 화면은 이미 만들어진 SBOM을 --analyze로 다시 넣었을 때만 나타납니다(방금 생성한 SBOM이 자기 자신을 채점하는 건 대부분의 항목에서 의미 있는 신호가 아니기 때문입니다). 제출 전 점검은 아래처럼 한 단계 더 거치세요.

./scripts/scan-sbom.sh --analyze myserver_1.0.0_bom.json --project myserver --version 1.0.0 --generate-only

사전 준비

BomLens는 Docker 위에서 동작합니다. Docker 엔진 20.10 이상을 설치하고 실행해 두세요. Docker가 없는 Windows에서는 무료인 Rancher Desktop을 권장합니다. 첫 실행 때 스캐너 이미지(약 250MB)를 내려받으며, 보통 1~2분쯤 걸립니다(네트워크 속도에 따라 다름).

명령줄 없이 시작

명령줄이 익숙하지 않다면 설치형 앱이나 웹 UI로 SBOM을 생성할 수 있습니다. 자세한 절차는 명령줄 없이 시작하기를 참고하세요.

  • 설치형 앱: 최신 릴리스에서 Windows는 BomLens-Setup.exe, macOS는 BomLens-Setup.dmg를 내려받아 설치합니다. Windows 실행 파일은 아직 코드 서명이 되어 있지 않아 SmartScreen 경고가 나타나면 “추가 정보"를 누른 뒤 “실행"을 선택합니다.
  • 저장소 ZIP(Windows): 저장소의 Code 버튼에서 Download ZIP을 받아 압축을 풀고 scripts\sbom-ui.bat를 더블클릭하면 브라우저에서 http://localhost:8080이 열립니다.

웹 UI에서는 오른쪽에 진행 로그가 실시간으로 표시되고, 완료되면 산출물을 내려받을 수 있습니다.

BomLens 웹 UI 실행 화면 — 오른쪽에 진행 로그가 실시간으로 표시된다

빠른 시작 (CLI)

macOS와 Linux에서는 최신 릴리스의 bomlens-cli-linux.tar.gz(Windows는 bomlens-cli-windows.zip)를 내려받아 실행합니다. scan-sbom.sh 파일 하나만 따로 받으면 실행되지 않습니다(같은 압축 안의 다른 파일을 함께 사용합니다).

tar -xzf bomlens-cli-linux.tar.gz
cd /path/to/my-project
/path/to/scripts/scan-sbom.sh --project "MyApp" --version "1.0.0" --all --generate-only
  • --generate-only는 제출 없이 로컬에 파일만 생성합니다(제출 전까지 권장).
  • 웹 UI로 쓰려면 ./scripts/scan-sbom.sh --ui를 실행합니다(브라우저에서 http://localhost:8080).
  • Windows에서 명령줄을 쓸 때는 같은 명령을 scripts\scan-sbom.bat로 실행합니다(Git Bash를 거치므로 Git for Windows 필요).
  • GitHub URL, 소스 ZIP, Docker 이미지, 펌웨어, 바이너리 등 다른 입력 형태와 전체 옵션은 CLI 레퍼런스를 참고하세요.

더 알아보기

도구 사용법의 정본은 저장소 문서입니다.

주제문서
설치, 첫 SBOM, 웹 UI시작하기
전체 옵션, 언어별, CI/CDCLI 레퍼런스
입력 형태별 시나리오입력 시나리오
고지문·보안 보고서리포트 가이드
서버(OS + 애플리케이션) 납품서버 납품 가이드

다음 단계

SBOM을 생성한 뒤 검증 체크리스트로 파일을 확인하고 제출 절차에 따라 제출합니다. 필수 데이터 필드는 제출 요구사항, SKT 도구 대신 cdxgen, Syft 등을 직접 쓰는 방법은 오픈소스 도구 활용을 참고하세요.

3 - 오픈소스 도구를 활용한 SBOM 생성

범용 오픈소스 도구를 활용하여 환경별로 SBOM을 생성하는 방법을 안내합니다.

Docker만 설치되어 있으면 BomLens 하나로 소스코드, 컨테이너 이미지, 서버 rootfs, 실행 파일, 펌웨어를 모두 스캔할 수 있습니다. 아래 오픈소스 도구를 개별적으로 설치하고 조합하는 대신 먼저 검토해 보시기 바랍니다.

도구 선택 가이드

graph TD
    A{{"공급 소프트웨어 분류"}}

    subgraph G1["소프트웨어 공급"]
      direction LR
      T1["소스코드·앱<br>(예: OSS/BSS, 관리 포털, 미들웨어)"]
      T2["실행 파일·라이브러리<br>(예: .jar, .dll, .so)"]
      T3["OS 없는 펌웨어<br>(예: 베어메탈·RTOS 단말)"]
    end

    subgraph G2["OS(예: Linux) 포함 공급"]
      direction LR
      T4["컨테이너 이미지<br>(예: CNF, 컨테이너형 네트워크 기능)"]
      T5["서버·VM 이미지<br>(예: VNF, 서버 어플라이언스)"]
      T6["OS 내장 펌웨어<br>(예: 기지국, 라우터, OLT/ONT, 셋톱박스)"]
    end

    %% 좌측: 소스코드 스캔 서브 박스 구조
    subgraph M1["소스코드 스캔"]
      M1_Sub["BomLens 또는 cdxgen"]
    end

    %% 우측: 소스코드 + OS 이미지 스캔 서브 박스 구조 (세로 배치)
    subgraph M2["소스코드 + OS 이미지 스캔"]
      direction TB
      M2_Top["OS (예: Linux) 스캔<br>(BomLens 또는 Syft·Trivy)"]
      M2_Bottom["소스코드 스캔<br>(BomLens 또는 cdxgen)"]
    end

    A --> G1
    A --> G2
    
    %% 그룹 박스 경계로만 연결 (박스당 화살표 1개)
    G1 --> M1
    G2 --> M2
    
    %% 그룹 박스에서 다음 단계로 연결
    M1 --> P(["SBOM 제출"])
    M2 --> P

    classDef start fill:#F2F2F2,stroke:#171717,color:#171717,stroke-width:1.5px
    classDef typebox fill:#ffffff,stroke:#c8c8c8,color:#171717,stroke-width:1px
    classDef submit fill:#F2F2F2,stroke:#171717,color:#171717,stroke-width:1.5px
    
    %% 내부 단일 박스용 흰색 스타일 정의 (좌/우 테두리 색상 구분)
    classDef subwhite_left fill:#ffffff,stroke:#00A651,color:#171717,stroke-width:1px
    classDef subwhite_right fill:#ffffff,stroke:#68127A,color:#171717,stroke-width:1px

    class A start
    class T1,T2,T3,T4,T5,T6 typebox
    class M1_Sub subwhite_left
    class M2_Top,M2_Bottom subwhite_right
    class P submit

    style G1 fill:#F1FAF5,stroke:#00A651,stroke-width:1px,color:#0A5A32
    style G2 fill:#FAF4FB,stroke:#68127A,stroke-width:1px,color:#4A0D57
    
    %% 외곽 박스 스타일 (배경색 및 테두리 유지)
    style M1 fill:#D9F0E4,stroke:#00A651,stroke-width:1px,color:#0A5A32
    style M2 fill:#EEDCF3,stroke:#68127A,stroke-width:1px,color:#4A0D57

소스코드·앱, 실행 파일이나 라이브러리, OS 없는 펌웨어는 모두 자기가 개발한 소스코드를 BomLens 또는 cdxgen으로 스캔합니다. 완성된 바이너리를 그대로 스캔하면 패키지 매니저 메타데이터가 없어 purl이 누락되고 반려됩니다.

OS나 베이스 이미지를 포함해 공급하는 경우(컨테이너 이미지, 서버, OS 내장 펌웨어)는 두 층으로 나눠 각각 스캔해 함께 제출합니다. OS 층은 납품되는 상태의 이미지나 rootfs를 BomLens 또는 Syft·Trivy로, 소스코드(앱 층)는 BomLens 또는 cdxgen으로 스캔합니다. 층별 명령과 파일 이름 규칙은 아래 서버 납품에 있습니다.

타사가 제조한 상용 소프트웨어나 완제품을 공급해 소스코드에 접근할 수 없는 경우는 스캔 대신 제조사로부터 SBOM을 받아 제출합니다. 상용 소프트웨어 공급을 참고하세요.

주요 도구 안내

BomLens (SK텔레콤 제공)

SK텔레콤이 만든 SBOM 생성 도구입니다. 소스코드, 컨테이너 이미지, 서버 rootfs, 실행 파일, 펌웨어를 아래 오픈소스 도구들을 개별적으로 설치하지 않고 하나의 Docker 컨테이너로 스캔합니다. 최상위 컴포넌트 이름 자동 기입, 제출 전 자체 검증(적합성 리포트) 등 SK텔레콤 제출 기준에 맞춘 기능이 포함되어 있습니다.

제출 전에는 --conformance-profile skt-submission 옵션으로 SK텔레콤 심사 기준(PURL 포함률 100% 등)을 미리 확인하시기 바랍니다. 자세한 내용은 검증 체크리스트를 참고하세요. 스캔 중 오류가 나거나 결과가 이상하면 자주 발생하는 반려 사유에서 비슷한 사례를 먼저 확인하시기 바랍니다.

BomLens로 처리되지 않는 경우이거나 오픈소스 도구를 직접 조합해서 쓰려면 아래를 참고하시기 바랍니다.

cdxgen (소스코드 분석)

Java, Python, Node.js, Go 등 다양한 언어 프로젝트를 자동 분석하여 CycloneDX 형식의 SBOM을 생성합니다.

cdxgen은 lockfile이나 매니페스트를 정적으로 해석합니다. 정확한 결과를 얻으려면 의존성이 설치되거나 해결된 상태(lockfile이 있거나 빌드한 뒤)에서 실행하시기 바랍니다. 의존성이 해결되지 않은 순수 소스만 스캔하면 일부 컴포넌트나 purl이 누락될 수 있습니다.

Syft (컨테이너 이미지 및 바이너리 분석)

빌드된 컨테이너 이미지나 패키지 매니저 메타데이터가 포함된 빌드 산출물을 분석하여 OS 패키지와 애플리케이션 라이브러리를 모두 식별합니다. CycloneDX 및 SPDX 형식을 지원합니다.

Trivy (컨테이너 이미지 분석)

컨테이너 이미지 분석과 취약점 스캔을 함께 수행할 수 있는 올인원 도구입니다.

언어별 전용 플러그인

빌드 도구 플러그인을 사용하면 더 정확한 의존성 정보를 추출할 수 있습니다.

언어/빌드 도구플러그인/도구공식 문서
Java (Maven)cyclonedx-maven-plugin링크
Java (Gradle)cyclonedx-gradle-plugin링크
Pythoncyclonedx-bom링크
Node.js@cyclonedx/cyclonedx-npm링크
Gocyclonedx-gomod링크

서버 납품

OS나 베이스 이미지를 포함해 공급하는 경우(서버, 컨테이너 이미지, OS 내장 펌웨어)에 해당합니다. 두 층을 각각 만들어 함께 제출합니다.

층대상누락 시 증상
OS운영체제와 설치된 패키지 전체 (예: RHEL과 rpm 데이터베이스의 모든 패키지)OS 취약점 누락
애플리케이션납품 애플리케이션과 패키지 매니저 의존성(직접·전이)앱 의존성 누락

두 층으로 나눠 스캔

OS 층은 서버의 rootfs(추출한 루트 파일시스템)나 그 컨테이너 이미지를 대상으로 합니다. 패키지 데이터베이스(rpm/dpkg/apk)를 읽어 설치된 패키지를 모두 실제 purl(pkg:rpm/...)로 식별합니다. 대상은 받아온 원본 베이스가 아니라 빌드가 끝나 납품되는 상태여야 합니다. 빌드 과정에서 설치한 OS 패키지까지 포함해야 하기 때문입니다. 설치 파일만 풀어 놓고 패키지 데이터베이스가 없는 폴더를 스캔하면 purl이 비어 반려됩니다.

대상은 rootfs의 루트여야 합니다. 하위 디렉터리만 지정하면 패키지 데이터베이스는 읽혀도 배포판이 판정되지 않습니다. Syft는 대상 안의 /etc/os-release로 배포판을 정하고 그 값을 purl에 넣습니다. 정상이라면 pkg:rpm/rhel/bind@9.11.36-16.el8_10.6처럼 타입과 패키지 이름 사이에 배포판이 들어갑니다. 이 자리가 비면 형식 검증은 통과하지만 SK텔레콤 시스템이 패키지를 식별하지 못해 OS 패키지가 전량 미매칭으로 반려됩니다. 스캔 전에 대상 안에 이 파일이 있는지 확인하시기 바랍니다.

# 대상 안에 배포판 정보가 있는지 먼저 확인
cat /path/to/server-rootfs/etc/os-release

# BomLens로 (rootfs 디렉터리를 그대로 대상으로 지정, 최상위 컴포넌트 이름도 자동 기입)
./scan-sbom.sh --project myserver-os --version 1.0.0 --target /path/to/server-rootfs --generate-only

# 오픈소스 도구를 직접 쓰려면: rootfs 디렉터리를 대상으로
syft dir:/path/to/server-rootfs -o cyclonedx-json=myserver-os_1.0.0_bom.json

# 서버가 컨테이너 이미지로 패키징돼 있다면(BomLens는 이미지 이름을 그대로 대상으로 지정)
./scan-sbom.sh --project myserver-os --version 1.0.0 --target myserver:7 --generate-only
syft myserver:7 -o cyclonedx-json=myserver-os_1.0.0_bom.json

애플리케이션 층은 빌드를 마친 뒤 애플리케이션 소스를 스캔합니다. 패키지 매니저(Maven, npm, pip, Go modules, Conan 등)를 쓰면 전이 의존성까지 자동으로 해석됩니다.

cd /path/to/app-source
cdxgen -o myserver-app_1.0.0_bom.json

# 또는 BomLens로
./scan-sbom.sh --project myserver-app --version 1.0.0 --target /path/to/app-source --generate-only

OS 층 스캔에 파이썬이나 Node.js처럼 파일로 설치된 의존성이 함께 잡히기도 합니다. 그래도 애플리케이션 층은 따로 만드시기 바랍니다. C/C++처럼 소스에 라이브러리를 포함하는 방식은 OS 층 스캔으로 전혀 식별되지 않습니다.

OS 내장 펌웨어(기지국, 라우터 등)

기지국, 라우터, OLT/ONT, 셋톱박스처럼 OS를 내장한 펌웨어도 위와 같은 두 층 구조입니다. OS 층은 펌웨어 이미지 파일 전체를 대상으로 BomLens의 --firmware 옵션을 사용합니다.

./scan-sbom.sh --project mydevice-os --version 1.0.0 --target /path/to/firmware.bin --firmware --generate-only

임베디드 리눅스 위에서 자체 애플리케이션이 별도로 동작한다면, 그 애플리케이션 소스는 위의 “애플리케이션 층” 스캔을 동일하게 적용합니다. 펌웨어 이미지 안에 애플리케이션까지 모두 포함되어 있다면 OS 층 스캔 하나로 끝날 수도 있습니다.

층별로 제출

층별 SBOM은 합치지 않고 그대로 제출합니다. SK텔레콤 시스템은 SBOM 문서 하나를 스캔 단위로 등록하고, 같은 제품 버전에 등록된 문서들을 합쳐 하나의 목록으로 봅니다. 층별로 포맷이 달라도 됩니다.

파일마다 이름이 달라야 하고, 재제출할 때는 같은 이름을 그대로 써야 합니다. SBOM 문서 이름이 스캔의 정체성이라, 이름이 바뀌면 이전 제출분이 지워지지 않고 남아 이미 조치한 취약점이 계속 집계됩니다. 층을 나타내는 접미어는 재제출해도 바뀌지 않으므로 안전하지만, 제출 회차를 나타내는 순번은 붙이지 마시기 바랍니다.

층파일 이름 예
OSmyserver-os_1.0.0_bom.json
애플리케이션myserver-app_1.0.0_bom.json

층 구분은 --project 값에 붙이는 접미어(-os, -app)로 합니다. BomLens는 {프로젝트 이름}_{버전}_bom.json을 자동으로 만들므로, 두 층을 모두 만들 때는 --project를 층마다 다르게 주십시오(예: myserver-os, myserver-app). 같은 이름으로 두 번 실행하면 파일 이름이 같아져 나중에 실행한 쪽이 앞선 산출물을 덮어씁니다. cdxgen이나 Syft로 직접 만들 때도 출력 파일 이름을 같은 규칙(-o myserver-app_1.0.0_bom.json 등)으로 맞추시기 바랍니다.

최상위 컴포넌트 이름(CycloneDX는 metadata.component.name, SPDX는 DocumentName)도 파일 이름 앞부분({이름}_{버전})과 같은 값으로 기재합니다. BomLens는 --project/--version 값을 이 필드에 자동으로 넣으므로 따로 손댈 필요가 없습니다. 이 값이 제출 건 전체에서 고유해야 하는 식별자입니다. 자세한 내용은 제출 요구사항의 메타데이터 절을 참고하세요.

클러스터처럼 노드가 여럿인 제품을 어떤 단위로 묶어 내는지는 제출 절차의 제출 단위 절을 참고하세요.

공통 주의사항

도구를 사용하기 전 아래 사항을 확인하시기 바랍니다.

  • 전이적 의존성 포함 여부: 빌드(패키지 설치)가 완료된 상태에서 생성해야 전이적 의존성까지 포함됩니다. 의존성 누락은 반려 사유가 되며, 언어별 빌드 선행 명령은 제출 요구사항의 의존성 범위 절을 참고하세요.
  • PURL 포함 여부: 생성된 SBOM에 모든 컴포넌트의 purl 필드가 포함되어 있는지 확인합니다. SK텔레콤 시스템은 PURL을 기반으로 취약점을 매핑합니다. 확인 명령과 재생성 절차는 검증 체크리스트를 참고하세요.
  • 출력 포맷: CycloneDX JSON 형식을 권장합니다. (-o cyclonedx-json 또는 동등한 옵션 사용)
  • 프로젝트 정보: 메타데이터에 납품 프로젝트의 이름과 버전이 정확히 기입되었는지 확인합니다.

관련 문서

4 - 상용 소프트웨어·완제품 공급 시 SBOM 제출

타사가 제조한 상용 소프트웨어나 완제품을 공급하는 경우, 제조사로부터 SBOM을 받아 제출하는 방법을 안내합니다.

이 문서는 자사가 개발하지 않은 상용 소프트웨어나 완제품을 SK텔레콤에 공급하는 공급사를 위한 가이드입니다. 이 경우 공급사는 소스코드에 접근할 수 없으므로, SBOM 생성 방법의 소스코드 스캔 방식을 적용할 수 없습니다. 제품을 제조한 원제조사로부터 SBOM을 받아 제출합니다.

납품된 장비나 설치 이미지를 도구로 통째로 스캔하는 방식은 대안이 되지 않습니다. 상용 소프트웨어 부분은 패키지 매니저 메타데이터가 없어 purl이 누락된 컴포넌트로 생성되고, 취약점 매칭이 실패하여 반려됩니다.

적용 대상

다음과 같은 형태로 타사 제품을 공급하는 경우가 해당합니다.

  • 상용 소프트웨어 재판매: 타사가 개발한 패키지 소프트웨어의 라이선스를 공급 (리셀러, 총판)
  • 어플라이언스·완제품 장비: 제조사가 OS와 소프트웨어를 설치해 출하하는 장비 (예: 스토리지, 백업 어플라이언스, 네트워크 장비)
  • 타사 제품이 포함된 시스템: 자체 개발 부분과 타사 상용 제품을 함께 구성해 납품

자체 개발 부분이 함께 있다면, 자체 개발 부분은 SBOM 생성 방법에 따라 직접 생성하고, 상용 부분은 본 문서에 따라 제조사 SBOM을 받아 함께 제출합니다.

제조사 SBOM 수령

원제조사(제조사 또는 개발사)에 CycloneDX 또는 SPDX 형식의 SBOM을 요청합니다. 미국 행정명령 EO 14028, EU Cyber Resilience Act 등 규제 시행에 따라 글로벌 제조사 다수가 제품별 SBOM 제공 체계를 갖추고 있습니다. 요청할 때 다음 사항을 함께 전달하면 회신을 빠르게 받을 수 있습니다.

  • 형식: CycloneDX JSON (권장) 또는 SPDX
  • 대상: 납품하는 제품의 정확한 모델명과 버전
  • 범위: OS를 포함해 출하되는 제품이라면 OS 패키지까지 포함

제조사마다 SBOM 제공 여부와 소요 기간이 다르므로, 납품 일정에 맞추려면 계약 검토 단계에서 미리 요청하시기 바랍니다.

받은 SBOM 점검

제조사에게 받은 SBOM도 자체 생성한 SBOM과 같은 기준으로 검토됩니다. 제출 전에 다음을 확인합니다.

  1. 제출 요구사항 충족 여부: 표준 포맷과 버전, 메타데이터, 컴포넌트 이름과 버전, purl 포함 여부
  2. 검증 체크리스트 점검: purl 보유 수 등 필수 항목
  3. 제품 버전 일치 여부: SBOM의 최상위 컴포넌트가 실제 납품하는 제품의 이름·버전과 일치하는지

점검을 마친 SBOM은 제출 절차에 따라 파일명을 정해 제출합니다.

클러스터로 구성된 제품이라면

여러 대의 노드가 하나의 클러스터를 이루는 제품(예: 분산 스토리지)도 제출 단위는 제품당 SBOM 하나입니다. SBOM 단위를 정하는 기준은 제출 절차의 제출 단위 절을 참고하세요.

제조사가 SBOM을 제공하지 못하는 경우

제조사가 SBOM을 제공하기 어렵다고 회신한 경우, 임의 방식으로 생성해 제출하기 전에 opensource@sktelecom.com으로 먼저 협의해 주시기 바랍니다.

관련 문서

5 - SBOM 제출 전 검증 체크리스트

SBOM 제출 전 필수 확인 사항을 점검하여 반려를 방지합니다.

필수 점검 항목

아래 체크리스트를 통과하지 못한 SBOM은 시스템에서 자동으로 반려될 수 있습니다. 2~4번 항목은 아래 검증 도구의 BomLens 자동 검증으로 한 번에 확인할 수 있습니다.

1. 파일 무결성

  • 파일 확장자가 .json 또는 .xml 인가? (압축 파일 아님)
  • 파일 크기가 1KB 이상이며, 내용이 비어있지 않은가?
  • JSON 문법 오류가 없는가?

아래 명령으로 확인하시기 바랍니다. 오류 없이 종료되면 통과입니다.

jq empty sbom.json && echo "OK: valid JSON"

2. 필수 데이터 필드

  • bomFormat: CycloneDX 또는 SPDX가 명시되었는가?
  • Metadata: 최상위 컴포넌트(납품 프로젝트)의 이름과 버전이 정확한가?
  • Components: 포함된 라이브러리 목록이 실제와 일치하는가?

3. 의존성 완전성 확인

전이적 의존성 누락은 가장 흔한 반려 사유입니다. 아래 항목을 반드시 확인하시기 바랍니다.

  • 직접 의존성(프로젝트가 직접 선언한 라이브러리)이 모두 포함되어 있는가?
  • 전이적 의존성(직접 의존성이 내부적으로 사용하는 라이브러리)이 포함되어 있는가?
  • SBOM 생성 전 빌드(또는 패키지 설치)를 완료하였는가? (예: npm install, mvn package, pip install)
  • 컴포넌트 수가 합리적인가? (직접 의존성만 몇 개인 프로젝트에서 총 컴포넌트 수가 10개 미만이라면 전이적 의존성이 누락되었을 가능성이 높음)
  • Maven·Gradle 프로젝트를 Syft로만 스캔하지 않았는가? Syft는 pom.xml이나 빌드 스크립트의 직접 선언만 읽어 전이 의존성이 빠집니다. cdxgen이나 언어별 CycloneDX 플러그인을 사용하시기 바랍니다.
  • npm 개발 의존성을 포함해야 하는데 빠지지 않았는가? Syft는 기본값으로 제외하므로 SYFT_JAVASCRIPT_INCLUDE_DEV_DEPENDENCIES=true를 지정해야 포함됩니다.
  • 서버 납품인 경우 OS 패키지가 포함되어 있는가? 애플리케이션 소스만 스캔하면 설치된 rpm/dpkg 패키지가 통째로 빠집니다. 절차는 SBOM 생성 방법의 서버 납품 절을 참고하세요.

4. 식별자 (PURL) 확인

SK텔레콤 시스템은 PURL로 취약점을 매핑합니다. 가장 중요한 항목입니다.

  • 모든 컴포넌트(components) 객체 안에 purl 필드가 존재하는가?
  • purl 보유 컴포넌트 수가 전체 컴포넌트 수와 일치(또는 근접)하는가?
  • PURL 형식이 표준(pkg:type/namespace/name@version)을 따르는가?
  • PURL 타입이 Package URL 규격에 정의된 것인가? 도구가 지어낸 타입(예: pkg:applications/)은 형식 검사를 통과해도 조회할 저장소를 특정할 수 없어 매칭에 실패합니다.
  • 네임스페이스가 필수인 타입(maven, golang, github, composer, swift, rpm, deb, apk 등)에서 그 자리가 비어 있지 않은가? Maven이라면 groupId가 pkg:maven/org.slf4j/jcl-over-slf4j@2.0.15처럼 별도 자리에 있어야 하며, pkg:maven/org.slf4j.jcl-over-slf4j@2.0.15처럼 이름과 이어 붙으면 반려됩니다.
  • 네임스페이스에 회사 이름이나 웹사이트 주소가 들어가지 않았는가? pkg:maven/The%2BApache%2BSoftware%2BFoundation/poi@5.4.1처럼 벤더 문자열이 groupId 자리에 들어가면 저장소에 없는 좌표가 됩니다.
  • PURL 내에 특수문자 등이 올바르게 인코딩되었는가?
  • PURL이 실제 설치된 것과 같은 배포판·버전을 가리키는가? 예를 들어 RHEL 서버인데 pkg:deb/debian/...으로 선언되어 있으면, 형식은 올바르므로 매칭은 성공하지만 실제와 무관한 컴포넌트의 취약점이 보고됩니다.
  • rpm/deb/apk 패키지의 배포판이 네임스페이스(타입과 패키지 이름 사이)에 있는가? 물음표 뒤 쿼리 파라미터(?distro=...)에만 있으면 인식되지 않아 네임스페이스가 빈 것과 동일하게 반려됩니다.
  • 바이너리 스캔에서 purl 없는 항목이 생기지 않았는가? Syft의 바이너리 카탈로거는 생태계를 특정하지 못한 항목을 purl 없이 남길 수 있습니다. 해당 항목은 제거하거나 실제 컴포넌트로 보완합니다.

아래 명령으로 purl 개수를 직접 확인하시기 바랍니다. 전체 컴포넌트 수와 purl 보유 수가 같아야 합니다.

# CycloneDX — 두 값이 같아야 한다
jq '.components | length' sbom.json                      # 전체 컴포넌트 수
jq '[.components[] | select(.purl)] | length' sbom.json  # purl 보유 수

# SPDX — purl(externalRef) 보유 패키지 수
jq '[.packages[] | select(.externalRefs[]?.referenceType == "purl")] | length' sbom.json

# CycloneDX: 네임스페이스가 필수인 타입인데 그 자리가 빈 개수 (0이어야 한다)
#   rpm/deb/apk의 배포판 누락과 maven의 groupId 누락이 함께 잡힌다
jq '[.components[] | (.purl // "")
     | select(test("^pkg:(alpm|apk|bitbucket|composer|deb|git|github|golang|huggingface|maven|qpkg|rpm|swift|vscode-extension)/[^/@?#]+([@?#]|$)"))
    ] | length' sbom.json

# CycloneDX: 규격에 없는 타입을 쓴 경우 그 타입 이름을 출력한다 (아무것도 나오지 않아야 한다)
curl -sO https://raw.githubusercontent.com/package-url/purl-spec/main/purl-types-index.json
jq -r --slurpfile ok purl-types-index.json '
  [.components[] | (.purl // "") | select(startswith("pkg:")) | capture("^pkg:(?<t>[^/@?#]+)").t]
  | unique - $ok[0] | .[]' sbom.json

purl 보유 수가 0이거나 전체 컴포넌트 수보다 현저히 적으면 제출하지 마십시오. 원인과 재생성 방법은 자주 발생하는 반려 사유를 참고하십시오.

검증 도구

BomLens 자동 검증 (권장)

BomLens의 SBOM 분석 기능은 위 체크리스트의 2~4번을 포함해 제출 요구사항을 자동으로 점검합니다. v1.8.0 이상이 필요합니다.

./scripts/scan-sbom.sh --project my-app --version 1.0.0 \
  --analyze "./sbom.json" \
  --lang ko \
  --generate-only

실행하면 my-app_1.0.0/ 폴더에 적합성 리포트(my-app_1.0.0_conformance.html)가 생성됩니다. 리포트가 자동으로 확인하는 항목은 다음과 같습니다.

BomLens로 SBOM을 직접 생성한 경우에도 이 명령으로 한 번 더 점검하시기 바랍니다. 방금 만든 SBOM을 그대로 --analyze에 넣으면 됩니다 — 생성과 검증을 한 번에 하지 않는 이유는, 갓 만든 SBOM이 자기 자신을 채점하는 것보다 별도 단계로 재확인하는 편이 실수를 더 잘 잡아내기 때문입니다.

검사 항목체크리스트 대응
스펙 버전 범위 (CycloneDX 1.31.6, SPDX 2.22.3)2. 필수 데이터 필드
생성 일시, 생성 도구, 최상위 컴포넌트 이름·버전2. 필수 데이터 필드
모든 컴포넌트의 이름·버전2. 필수 데이터 필드
직접·전이적 의존성 포함 여부3. 의존성 완전성 확인
PURL 보유율, 표준 형식(pkg:type/name@version), pkg:generic 금지, OS 패키지 배포판 네임스페이스4. 식별자 (PURL) 확인
라이선스·해시 보유율 (권장 항목)—

BomLens v1.8.x의 자동 검증은 아직 CycloneDX 1.7을 지원 범위 밖으로 표시하고, 네임스페이스 검사도 OS 패키지(rpm, deb, apk)까지만 수행합니다. CycloneDX 1.7로 생성했거나 maven 등 다른 타입을 쓰는 경우에는 위 jq 명령으로 함께 확인하시기 바랍니다.

결과가 fail이면 어떤 컴포넌트가 어느 항목에 미달하는지 목록으로 표시되므로, 해당 부분을 보완해 SBOM을 다시 생성한 뒤 재검증하면 됩니다. 웹 UI(--ui 실행 후 SBOM 업로드)에서도 같은 검증을 할 수 있습니다.

제출 전에는 위 명령에 --conformance-profile skt-submission을 추가해서, SK텔레콤 심사와 같은 기준(PURL 포함률 100%, pkg:generic 식별자 없음)으로 확인하시기 바랍니다. 웹 UI의 제출 검토 화면은 이 기준을 이미 기본값으로 적용하므로, 이 옵션은 CLI를 직접 실행할 때만 필요합니다.

CycloneDX Validator (스키마 검사)

CycloneDX 파일이 표준 스키마에 맞는지 확인하는 온라인 도구입니다. JSON 문법과 형식 오류(체크리스트 1번)를 설치 없이 빠르게 확인할 때 유용합니다. 다만 스키마 검사만 수행하므로, 통과하더라도 2~4번(필수 필드, 의존성 완전성, PURL)을 충족한다는 뜻은 아닙니다. SPDX 파일은 이 도구로 검사할 수 없습니다.

관련 문서

6 - SBOM 제출 절차

작성된 SBOM 파일의 제출 채널과 이메일 양식, 제출 후 프로세스를 안내합니다.

1. 제출 단위

제출 단위는 납품 제품 하나입니다. 여러 대의 노드가 하나의 클러스터를 이루는 제품도 마찬가지이며, 노드 대수만큼 만들 필요는 없습니다.

  • 모든 노드가 동일 구성이라면, 대표 노드 1대를 기준으로 생성해 제출합니다.
  • 노드 역할에 따라 설치된 소프트웨어가 다르다면(예: 관리 노드와 스토리지 노드), 역할별로 만들어 함께 제출합니다.

제품 하나에 SBOM 파일이 여럿일 수 있습니다. 서버처럼 층을 나눠 생성한 경우 파일을 합치지 않고 그대로 함께 제출하며, SK텔레콤 시스템이 같은 제품 버전에 등록된 문서들을 합쳐 하나의 목록으로 봅니다. 이때 파일마다 이름이 달라야 하고 재제출 시에는 같은 이름을 유지해야 합니다. 이름 규칙은 SBOM 생성 방법의 층별로 제출 절을 참고하세요.

2. 제출 시기

  • 소프트웨어 계약 체결 후 초기 납품 시
  • 소프트웨어의 주요 버전(Major/Minor) 업데이트 시
  • 계약서에 명시된 정기 제출 일정 도래 시

3. 제출 방법

SBOM 파일은 SK텔레콤 사업부서 및 보안부서 담당자에게 이메일(또는 담당자가 지정한 채널)로 제출합니다.

  • 이메일 제목: [SBOM 제출] 공급사명_프로젝트명_버전
  • 첨부파일: 생성된 SBOM 파일 (비밀번호 걸린 압축 파일 금지)

본문 필수 기재 사항:

  1. 납품 계약 번호
  2. 담당자 정보 (성명, 부서, 연락처)
  3. 프로젝트 정보 (시스템명, 상세 버전)
  4. 사용 도구 및 버전 (예: BomLens, cdxgen)

4. 제출 후 검증 및 조치

제출된 SBOM은 사내 오픈소스 & SBOM 관리 시스템(TOSCA)에 등록된 후 아래 절차에 따라 검증됩니다. TOSCA는 사내 시스템이므로 공급사가 접근할 필요는 없습니다.

단계내용처리 기한
형식 검증필수 필드 누락 여부 확인. 미충족 시 반려 통보접수 후 3일 이내
보안 취약점 분석Critical/High 등급 취약점 탐지 여부 자동 분석-
조치 요청심각한 취약점 발견 시 패치 계획 또는 소명서 요청Critical: 7일 / High: 30일

검증 결과와 조치 요청 사항은 사업부서 담당자를 통해 공급사 및 보안부서 담당자에게 통보됩니다.

관련 문서

7 - 자주 발생하는 반려 사유

제출된 SBOM이 반려되는 대표 사유와 원인, 해결 방법을 안내합니다.

제출된 SBOM은 형식 검증과 취약점 분석을 거치며, 기준에 미달하면 반려됩니다. 아래는 실제 접수 과정에서 반복적으로 발생하는 반려 사유입니다. 제출 전에 검증 체크리스트와 함께 확인하시기 바랍니다.

반려는 SBOM의 형식이나 완전성 문제일 뿐이며, 아래 해결 방법대로 보완해 다시 제출하면 됩니다.

반려 사유 한눈에 보기

반려 사유주요 원인해결 방법
PURL 전량 누락패키지 매니저 메타데이터가 없는 설치 디렉터리나 원시 파일을 스캔 (syft dir: 등)빌드된 이미지나 소스코드를 스캔 대상으로 변경. SBOM 생성 방법
전이 의존성 누락빌드(패키지 설치) 전에 소스만 스캔빌드 완료 후 재생성. 제출 요구사항의 의존성 범위 절
pkg:generic/ PURL도구가 생태계를 식별하지 못함생태계를 명시하는 타입으로 재생성. 제출 요구사항의 PURL 절
규격에 없는 PURL 타입도구가 규격에 정의되지 않은 타입을 임의로 기재(예: pkg:applications/)규격에 정의된 타입으로 재생성. 제출 요구사항의 PURL 절
maven 등 네임스페이스 필수 타입에 네임스페이스 누락도구가 groupId와 artifactId를 점으로 이어 붙여 한 자리에 기재groupId를 네임스페이스 자리로 분리해 재생성. 제출 요구사항의 PURL 절
네임스페이스에 공급사 이름이나 URL 기재생성 도구가 매니페스트의 벤더 문자열을 groupId 자리에 그대로 옮김저장소가 쓰는 실제 식별자로 수정. 제출 요구사항의 PURL 절
컴포넌트 버전 누락매니페스트 불완전 또는 도구 설정 문제version 필드 필수 기재. 제출 요구사항
서버인데 OS 패키지 미포함애플리케이션 소스만 스캔납품 상태의 rootfs나 이미지를 스캔. SBOM 생성 방법
OS 패키지 PURL에 배포판 누락스캔 대상에 /etc/os-release가 없어 도구가 배포판을 판정하지 못함rootfs의 루트나 이미지를 대상으로 재생성. SBOM 생성 방법
OS 패키지 PURL의 배포판이 네임스페이스가 아닌 쿼리 파라미터에 표기도구가 배포판을 ?distro=...처럼 부가 정보로만 기재배포판을 경로(네임스페이스)로 옮겨 재생성. 제출 요구사항의 PURL 절
실제와 다른 배포판·버전의 PURL도구가 파일 이름으로 무관한 배포판 패키지를 추정실제 설치된 패키지를 기준으로 재생성. SBOM 생성 방법
허용되지 않는 포맷·버전지원 범위 밖의 포맷으로 생성CycloneDX JSON 권장. 제출 요구사항
최상위 컴포넌트 정보 누락메타데이터에 납품 제품명과 버전 미기재metadata의 component에 제품명과 버전 기재. 제출 요구사항
최상위 컴포넌트 이름이 다른 제출 건과 충돌생성 도구가 제품명 대신 고정값을 채움(예: 빈 값, ., /scan)metadata의 component 이름을 장비·제품을 특정할 수 있는 고유한 값으로 수정 후 재제출. 제출 요구사항

대표 사례

사례 1: 설치 디렉터리 스캔으로 PURL이 전량 누락

한 공급사가 syft dir:<설치 디렉터리>로 패키지 매니저 메타데이터가 없는 위치를 스캔해 제출한 SBOM은 대부분의 컴포넌트에 purl이 하나도 없어, 취약점 매칭이 전량 실패하고 반려되었습니다. 패키지 매니저 메타데이터(package.json, go.mod, RPM/DEB 패키지 DB 등)가 없는 위치를 스캔하면 도구가 생태계를 식별하지 못합니다.

스캔 대상을 빌드된 이미지나 소스코드로 바꾸고, 생성 직후 purl 개수를 확인하십시오. 확인 명령은 검증 체크리스트에 있습니다.

사례 2: 빌드 전 스캔으로 전이 의존성 누락

직접 의존성이 수 개인 프로젝트인데 총 컴포넌트가 10개 미만이라면 전이 의존성 누락을 의심해야 합니다. 일반적인 웹 애플리케이션은 전이 의존성까지 포함하면 수십에서 수백 개의 컴포넌트가 나옵니다. npm install, mvn package 같은 빌드를 완료한 뒤 생성하면 해결됩니다.

사례 3: 생성 도구가 최상위 컴포넌트 이름을 고정값으로 채워 다른 제출 건과 충돌

한 공급사가 제조사 제공 SBOM 생성 도구로 만든 CycloneDX SBOM을 제출했는데, 이미 등록된 다른 장비의 SBOM과 이름이 겹쳐 반려되었습니다. 확인 결과 이 도구는 스캔한 장비와 무관하게 metadata.component.name을 항상 같은 고정값으로 채우고 있었습니다. 같은 도구로 다른 장비의 SBOM을 만들어도 이름이 매번 똑같이 나오기 때문에, 먼저 등록된 건과 계속 충돌합니다.

이런 도구를 사용하는 경우 SBOM을 텍스트 편집기로 열어 metadata.component.name(CycloneDX) 또는 최상단 name(SPDX) 값을 장비를 식별할 수 있는 값으로 직접 수정한 뒤 제출해야 합니다.

사례 4: OS 패키지가 빠지고 실제와 다른 배포판 PURL로 선언

RHEL 서버 제품의 SBOM이 애플리케이션 소스 트리만 대상으로 생성되어, 설치된 rpm 패키지가 하나도 포함되지 않은 채 제출되었습니다. 여기에 더해 소스에 포함된 라이브러리가 pkg:deb/debian/libpcap@1.1.1-2+squeeze1처럼 데비안 소스 패키지로 선언되어 있었습니다. 생성 도구가 소스 파일 이름을 단서로 그 파일을 담고 있는 데비안 패키지를 추정해 붙인 결과입니다.

이 유형은 형식 검증을 통과합니다. purl이 실재하는 패키지를 가리키므로 매칭도 정상 성공하고 화면에도 오류가 보이지 않습니다. 그러나 실제 서버에 설치된 것과 무관한 컴포넌트의 취약점이 보고되고, OS를 업그레이드해도 결과가 달라지지 않습니다.

납품 상태의 rootfs나 이미지를 스캔해 OS 패키지를 포함시키고, 소스에 포함된 라이브러리는 실제 버전으로 선언해야 합니다. 절차는 SBOM 생성 방법의 서버 납품 절을 참고하십시오.

사례 5: 배포판 정보가 네임스페이스가 아니라 쿼리 파라미터에 표기됨

자체 빌드 리눅스 배포판을 쓰는 한 서버 제품의 SBOM에서, rpm 패키지 PURL에 배포판 값이 물음표 뒤 쿼리 파라미터로 붙어 있었습니다(예: pkg:rpm/bind@9.11.36?distro=customdistro-1.0). 도구가 배포판 자체는 식별했지만, 이를 요구되는 네임스페이스 자리가 아니라 부가 정보 자리에 기재한 경우입니다.

이 값은 취약점 매칭에 쓰이지 않아 해당 서버의 rpm 패키지 전량이 매칭 실패로 반려되었습니다. 배포판 값을 경로(타입과 패키지 이름 사이)로 옮겨 pkg:rpm/<배포판>/bind@9.11.36처럼 재생성해야 합니다.

사례 6: 형식 검사를 모두 통과했는데 purl 642건이 매칭 실패

한 공급사가 컴포넌트 8,129개짜리 CycloneDX SBOM을 제출했습니다. 모든 컴포넌트에 purl이 있어 보유율은 100%였고, pkg:generic도 없었으며, OS 패키지 배포판 누락도 0건이었습니다. 당시 체크리스트와 자동 검증 기준을 모두 통과한 파일입니다. 그런데 고유 purl 2,785건 가운데 642건이 실제 저장소 조회에서 매칭되지 않았습니다.

원인은 세 가지가 섞여 있었습니다.

  • 네임스페이스 누락 663건: pkg:maven/org.slf4j.jcl-over-slf4j@2.0.15처럼 groupId와 artifactId가 점으로 이어 붙어 한 자리에 들어갔습니다. 형식은 유효하고 스키마 검사도 통과하지만 저장소에 없는 좌표입니다.
  • 규격에 없는 타입: pkg:applications/java@11.0.25처럼 applications라는 임의 타입이 쓰였습니다. generic이 아니므로 기존 금지 규칙에 걸리지 않았습니다.
  • 네임스페이스에 벤더 문자열: pkg:maven/The%2BApache%2BSoftware%2BFoundation/poi@5.4.1, pkg:maven/http%3A/www.jboss.org/jbossxts@1.1처럼 회사 이름이나 URL이 groupId 자리에 들어갔습니다.

세 유형 모두 스키마 검사로는 걸러지지 않으므로, 검증 체크리스트의 PURL 확인 명령으로 직접 점검한 뒤 제출해야 합니다.

같은 파일에서 pkg:maven/org.drools/org.drools.drools-core-dynamic@7.67.2.Final-redhat-00054처럼 artifactId 앞에 groupId가 한 번 더 붙은 경우도 나왔습니다. 실제 좌표는 org.drools:drools-core-dynamic입니다. 이 유형은 위 세 가지와 달리 형식으로 판정할 수 없습니다. org.drools:org.drools.updatesite나 org.apache.felix:org.apache.felix.http.jetty처럼 artifactId가 groupId로 시작하는 것이 정상인 좌표도 많기 때문입니다. Eclipse 플러그인과 OSGi 번들은 artifactId에 번들 심볼릭 이름을 그대로 쓰는 관례가 있습니다. 그래서 체크리스트에는 점검 항목을 두지 않았고, 확인하려면 해당 좌표가 저장소에 실제로 있는지 조회해야 합니다.

반려되지 않는 SBOM의 모습

합격 기준을 충족하는 예시 파일을 내려받아 구조를 비교해 보십시오. 모든 컴포넌트에 purl과 버전이 있고, dependencies 배열이 직접·전이 의존 관계를 담고 있습니다.

관련 문서