본문으로 건너뛰기

SBOM

포털은 가장 최근 성공 스캔으로부터 Software Bill of Materials(SBOM) 산출물을 생성합니다. 4가지 교환 포맷과 attribution NOTICE 파일을 지원합니다.

내보내기 vs 업로드

이 페이지는 TRUSCA가 스캔으로부터 생성한 SBOM을 내보내는(export) 방법을 다룹니다. 반대로 고객 도구가 이미 만든 SBOM(CycloneDX 또는 SPDX)을 업로드해 TRUSCA가 CVE를 매칭하고 적합성을 채점하게 하려면 SBOM 업로드스캔 → SBOM 업로드을 참고하세요.

프로젝트 상세 — 포맷 선택기와 마지막 스캔 요약이 있는 SBOM 탭

대상 독자

릴리스를 출고하는 엔지니어, 산출물을 제출하는 컴플라이언스 리드, EO 14028에 따라 SBOM 요청을 처리하는 고객. 팀 멤버십 기반 읽기 권한.

지원 포맷

포맷쿼리 값 (format=)MIME사용 사례
CycloneDX 1.6 (JSON)cyclonedx-jsonapplication/vnd.cyclonedx+jsonSCA 도구의 사실상 표준. VEX 포함.
CycloneDX 1.6 (XML)cyclonedx-xmlapplication/vnd.cyclonedx+xml동일 데이터; 레거시 도구를 위한 XML.
SPDX 2.3 (JSON)spdx-jsonapplication/spdx+jsonNTIA 최소 요소; 규제 산업에서 폭넓게 수용.
SPDX 2.3 (Tag-Value)spdx-tvtext/spdx원래의 SPDX 라인 기반 포맷.

두 포맷 모두 동일한 내부 모델에서 생성되므로 컴포넌트 목록은 (포맷별 필드 제외) 동일합니다.

컴포넌트별 포함 내용

각 컴포넌트는 이름, 버전, 패키지 URL(PURL), 그리고 탐지된 라이선스를 담습니다.

  • 라이선스 — 스캔의 라이선스 finding에서 채웁니다. CycloneDX는 컴포넌트 licenses 배열을 사용하고(concludeddeclareddetected 우선순위), SPDX는 licenseDeclared·licenseConcluded를 SPDX license expression으로 채웁니다. 탐지된 라이선스가 없거나 SPDX 식별자가 없는 라이선스(ORT LicenseRef-*)는 SPDX에서 스펙 sentinel NOASSERTION으로 출력됩니다 (CycloneDX는 라이선스 이름을 그대로 담음). copyrightText는 현재 항상 NOASSERTION입니다.
  • 최상위 버전metadata.component.version은 스캔된 릴리스를 반영합니다. 스캔 제출 시 release 라벨(예: v1.2.3)이 지정됐으면 그 값을, 없으면 스캔 id를 안정적 fallback으로 사용합니다.

Byte-stable 출력

4가지 내보내기 모두 byte-stable입니다 — 같은 스캔을 다시 내보내면 동일 바이트가 생성됩니다. diff·서명·캐싱이 단순해집니다.

byte-stability 달성 방법:

  • 컴포넌트를 purl(사전식)로 정렬.
  • 각 컴포넌트 내 라이선스 표현을 알파벳순 정렬.
  • serialNumber(CycloneDX) / documentNamespace(SPDX)를 (project_id, scan_id) 기반 결정적 값으로 고정.
  • 본문에서 타임스탬프를 제외(SBOM 메타데이터에는 스캔 종료 시각이 기록되며 스캔당 안정적).

UI에서 다운로드

  1. 프로젝트 열기.
  2. SBOM 탭 클릭.
  3. 4개 포맷 버튼 중 하나(CycloneDX JSON, CycloneDX XML, SPDX JSON, SPDX Tag-Value)를 클릭하여 다운로드.

SBOM 탭 — 4개 포맷 다운로드 버튼(CycloneDX JSON/XML, SPDX JSON/Tag-Value)

파일명은 sbom-<project-slug>.<ext>.

API에서 다운로드

API는 SBOM을 CycloneDX JSON으로 제공합니다:

…그리고 SPDX JSON으로도 제공합니다(같은 엔드포인트, format만 다름):

# CycloneDX JSON
curl -sS -L -OJ \
-H "Authorization: Bearer ${TRUSTEDOSS_API_KEY}" \
"https://trustedoss.example.com/v1/projects/${PROJECT_ID}/sbom?format=cyclonedx-json"

# SPDX JSON
curl -sS -L -OJ \
-H "Authorization: Bearer ${TRUSTEDOSS_API_KEY}" \
"https://trustedoss.example.com/v1/projects/${PROJECT_ID}/sbom?format=spdx-json"

format 허용값: cyclonedx-json, cyclonedx-xml, spdx-json, spdx-tv.

엔드포인트는 항상 가장 최근에 성공한 스캔(latest succeeded) 의 SBOM을 내보냅니다. 특정 과거 스캔 ID로 고정하는 기능은 로드맵 항목입니다.

감사 증거 — 스캔을 외부에서 고정하세요

SBOM 내보내기는 항상 최신 성공 스캔을 반영합니다. 외부 감사관은 보통 특정 릴리스 시점의 SBOM 을 요청합니다(예: "2026-01-15 에 출고된 것은 무엇인가?"). 과거 스캔 고정() 이 적용되기 전까지는 각 릴리스 경계에서 SBOM 산출물을 캡처하여 릴리스 아카이브에 보관하세요. 포털은 현재 SBOM 으로 다루되 과거 SBOM 의 출처로 보지 마세요.

정책 프로파일

기본 내보내기는 가공하지 않은 컴포넌트 목록입니다. 선택적 정책 프로파일은 팀의 라이선스 정책을 내보내기에 적용해, 배포용 SBOM이 조직의 기준을 반영하게 합니다.

  • 정책 주석(policy annotated) — 위반 컴포넌트를 제거하지 않고 그 자리에 표시합니다. CycloneDX 컴포넌트에는 trusca:policy:category / trusca:policy:spdx properties가, SPDX 패키지에는 REVIEW annotation이 추가됩니다. 금지뿐 아니라 조건부 컴포넌트도 함께 표시되므로, 검토자가 SBOM 안에서 각 컴포넌트가 왜 문제인지 바로 볼 수 있습니다.
  • 정책 필터(policy filtered) — 금지 컴포넌트를 내보내기에서 제외하고 (그 컴포넌트를 참조하던 취약점 항목도 함께 제거), 제외한 개수를 문서에 기록합니다(trusca:policy:excluded_count 또는 문서 annotation).

팀·조직 정책이 설정돼 있지 않으면 내장 분류 카탈로그로 대체 판정하므로, 금지 GPL은 그래도 표시됩니다.

SBOM 탭에서 프로파일을 선택하거나 API에 profile을 전달합니다.

curl -sS -L -OJ \
-H "Authorization: Bearer ${TRUSTEDOSS_API_KEY}" \
"https://trustedoss.example.com/v1/projects/${PROJECT_ID}/sbom?format=cyclonedx-json&profile=policy-annotated"

profile 허용값: policy-annotated, policy-filtered. 프로파일 내보내기는 파일명이 구분되게 지정되어(sbom-<project>-<profile>.<ext>) 표준 내보내기와 혼동되지 않습니다.

프로파일 내보내기에는 서명이 붙지 않습니다

cosign 서명기본 SBOM — 스캔 시점에 생성된 정확한 바이트 — 에만 적용됩니다. 정책 프로파일은 요청 시점에 생성되므로 서명이 없으며, 프로파일 내보내기에 대해 cosign verify-blob을 실행하면 실패합니다. 검증 가능한 서명 산출물이 필요하면 기본 내보내기를 쓰고, 프로파일 내보내기는 검토·배포용 편의로 취급하십시오.

NOTICE 파일

Apache-2.0 §4(d)와 유사한 attribution 의무 이행을 위해 포털은 프로젝트 최신 스캔으로부터 NOTICE attribution 본문을 자동 생성합니다.

파일 내용:

  • 프로젝트 이름과 생성 타임스탬프 헤더.
  • 검출된 라이선스별 섹션 하나씩 — 해당 라이선스의 컴포넌트(name @ version) 목록과 컴포넌트별 저작권 라인 포함.
  • 각 라이선스 섹션의 attribution 의무(예: attribution, no-endorsement)와 짧은 설명, 정책 참조 링크.
  • 문서 말미의 License Texts 섹션 — 프로젝트에 등장한 모든 라이선스의 전문 수록.
  • 라이선스에 AI 특화 제약 플래그(행동 사용 또는 비상업)가 붙은 컴포넌트를 나열하는 License review needed 섹션 — AI 라이선스 검토 플래그 참고.

저작권 라인

각 컴포넌트 항목에는 스캔 SBOM에 기록된 저작권 문구가 표시됩니다(cdxgen이 패키지 메타데이터에서 읽어 옵니다). SBOM에 저작권자가 기록되지 않았으면 라인을 공란으로 두지 않고, 저작권자가 수록되지 않았다는 안내와 함께 컴포넌트의 레지스트리 URL을 대신 표시합니다 — 원 소스에서 저작권 문구를 확인할 수 있습니다. 컴포넌트 드로어의 수동 오버라이드는 로드맵에 있습니다.

라이선스 전문

문서는 프로젝트에 등장한 각 라이선스의 정식 전문을 담은 License Texts 섹션으로 끝납니다. 포털은 잘 알려진 32종 라이선스의 SPDX(Software Package Data Exchange) 전문을 번들로 포함합니다 — MIT, Apache-2.0, 그리고 BSD·GPL·LGPL·AGPL·MPL·EPL·CDDL 계열 등. 전문이 번들에 없는 라이선스는 조용히 누락되지 않고 정식 전문으로 연결되는 reference URL 링크로 대체됩니다. 이 섹션 덕분에 NOTICE 산출물 자체가 카탈로그의 license_text_inclusion_required 의무를 충족합니다 — 의무사항 카탈로그 참고.

지원 포맷

NOTICE 엔드포인트는 format 쿼리 값을 받습니다(기본 text).

포맷쿼리 값 (format=)MIME확장자사용 사례
일반 텍스트texttext/plain.txt릴리스 tarball의 NOTICE 파일로 그대로 사용. 기본값.
Markdownmarkdowntext/markdown.md문서 사이트나 PR 설명에 렌더링.
HTMLhtmltext/html.htmlattribution 페이지용 self-contained 문서(인라인 <style>, 스크립트 없음).

출력은 동일 스캔·동일 포맷에 대해 내보내기 간 byte-stable이며 릴리스 간 diff가 가능합니다.

다운로드

  • UI: 프로젝트 → Obligations 탭 → 포맷 선택(text 또는 HTML) → Download NOTICE. 브라우저가 NOTICE-<project>.<ext>로 저장합니다. markdown 변형은 API에서 제공됩니다.

  • API:

    # 일반 텍스트(기본)
    curl -sS -L -OJ \
    -H "Authorization: Bearer ${TRUSTEDOSS_API_KEY}" \
    "https://trustedoss.example.com/v1/projects/${PROJECT_ID}/notice?format=text&download=true"

    # HTML
    curl -sS -L -OJ \
    -H "Authorization: Bearer ${TRUSTEDOSS_API_KEY}" \
    "https://trustedoss.example.com/v1/projects/${PROJECT_ID}/notice?format=html&download=true"

    format 허용값: text, markdown, html. download=true를 전달하면 응답에 Content-Disposition: attachment가 설정되고 -OJ가 서버 제공 파일명(NOTICE-<project>.<ext>)으로 저장합니다. 생략하면 본문을 인라인으로 스트리밍합니다.

VEX 내보내기

CycloneDX SBOM은 모든 결과의 프로젝트 VEX 상태를 포함합니다. SPDX는 native VEX 표현이 없으므로 SPDX 내보내기는 결과별 상태를 생략합니다. 다운스트림 소비자가 기대하면 SPDX 내보내기와 별도 CycloneDX VEX 문서를 함께 제공하세요.

SBOM의 vulnerabilities[] 배열 각 항목은 CVE id, 출처 데이터베이스, VEX 분석, 그리고 같은 문서 안에서 영향받는 컴포넌트의 bom-ref를 가리키는 affects[].ref를 담습니다(소비자가 PURL을 파싱하지 않고도 결과와 컴포넌트를 연결할 수 있습니다).

VEX 상태는 CycloneDX analysis.state로 매핑되고, 분석가의 자유 텍스트 노트(있는 경우)는 analysis.detail에 담깁니다:

포털 상태CycloneDX VEX stateanalysis.detail
Newin_triage(없음)
Analyzingin_triage분석가 노트
Exploitableexploitable분석가 노트
Not affectednot_affected분석가 노트
False positivefalse_positive분석가 노트
Suppressednot_affected분석가 노트
Fixedresolved분석가 노트

닫힌 CycloneDX analysis.justification enum(code_not_present 등)은 절대 내보내지 않습니다. 이 enum의 항목은 자유 형식의 분석가 서술로는 추론할 수 없는 정밀한 의미를 가지므로, 노트는 analysis.detail에 유지됩니다.

정상 동작 확인

  1. 다운로드된 SBOM이 검증기를 통과 — CycloneDX는 cyclonedx validate 실행:

    cyclonedx validate --input-file checkout-service.sbom.json
  1. SPDX는 spdx-tools로 검증:

    pyspdxtools -i checkout-service.sbom.json
  1. 같은 스캔을 다시 다운로드하면 byte 동일 파일 생성:

    sha256sum checkout-service.sbom.json checkout-service.sbom.json.again
    # → 동일 해시

트러블슈팅

성공한 스캔이 아직 없을 때의 빈 SBOM

프로젝트에 아직 성공한 스캔이 없는 경우에도 내보내기는 빈 components/packages 리스트를 가진 유효한 SBOM 문서(HTTP 200)를 반환합니다. 다운스트림 도구가 그대로 파싱할 수 있습니다.

/sbom?format=… 호출 시 422

쿼리 문자열이 API가 받지 않는 값을 사용했습니다. 위 표의 4가지 정식 쿼리 값 중 하나를 사용하세요 — 특히 SPDX Tag-Value 포맷의 값은 spdx-tv(이며 spdx-tag-value가 아닙니다).

접근 권한이 없는 프로젝트에서 404

SBOM·NOTICE 엔드포인트는 존재를 은폐합니다 — 프로젝트 소속 팀의 멤버가 아닌 호출자는 존재하지 않는 프로젝트 id와 동일하게 403이 아니라 404를 받습니다. 이는 의도된 동작입니다 — 403을 반환하는 project-detail 엔드포인트와 달리 SBOM·NOTICE 본문은 구조적 세부(컴포넌트 이름·버전)를 노출하므로, 비멤버에게는 프로젝트의 존재 자체를 확인해 주지 않습니다. 접근하려면 소속 팀에 합류하세요.

저작권 라인에 저작권자 대신 레지스트리 링크가 표시됨

스캔 SBOM에 해당 컴포넌트의 저작권자가 기록되지 않은 경우입니다 — cdxgen이 패키지 메타데이터에서 저작권 문구를 찾지 못했습니다. NOTICE는 라인을 공란으로 두지 않고 저작권자 미수록 안내와 함께 컴포넌트의 레지스트리 URL을 표시하므로, 상위 소스에서 저작권 문구를 직접 확인해 이행하세요. 컴포넌트 드로어의 수동 오버라이드는 로드맵에 있습니다. SPDX 내보내기는 별도 표면이며 여전히 copyrightText: NOASSERTION을 출력합니다.

컴플라이언스 증거 체인

외부 감사관이 포털 운영자에게 묻는 전형적인 다섯 가지 질문입니다. 오늘 답할 수 있는 것과 우회가 필요한 것을 정리한 표입니다.

감사관 질문v0.10.0 답변 소스한계
"릴리스 X 시점의 SBOM 을 보여달라"수동 아카이브; 포털은 최신본만 보존과거 스캔 고정은 로드맵
"지난 분기에 누가 SBOM / NOTICE 를 다운로드했나?"structlog(Loki / journald) — audit_logs 아님감사 행 승격은 로드맵
"프로젝트 X 에서 GPL 이 처음 탐지된 시점은?"scans.createaudit_logs + 스캔별 vulnerability_findings.create가능 — 전체 증거 체인 보유
"2026 Q1 의 모든 승인 결정을 보여달라"component_approvals.updateaudit_logs + decision_note가능 — 전체 증거 체인 보유
"감사 행이 변조되지 않았음을 증명하라"append-only 트리거(마이그레이션 0012)super-admin 우회 잔존 — 감사 로그 강화 검토 필요

공급사 제출 호환성

이 내보내기는 일반적인 기업 공급사 SBOM 요구사항(예: SK텔레콤 공급사 가이드)을 충족합니다: 표준 포맷/버전(CycloneDX, SPDX 2.3), ISO-8601 타임스탬프, 도구 메타데이터, 컴포넌트별 이름·버전·PURL, 라이선스, 그리고 전이적 의존성(스캔 대상 소스에 lockfile이 포함되거나 생성 가능할 때).

제출 전 유의할 두 가지:

  • pkg:generic/ PURL은 일부 프로그램에서 반려됩니다. generic PURL은 스캐너가 컴포넌트의 생태계를 분류하지 못했다는 뜻입니다. cdxgen이 생태계별 타입을 부여하도록 lockfile / 빌드 산출물을 함께 제공하세요.
  • SPDX 식별자가 없는 라이선스는 SPDX expression에서 NOASSERTION으로 나타납니다(CycloneDX license.name에는 라벨이 남습니다).

로드맵

매뉴얼이 이전에 약속했으나 v0.10.0에 포함되지 않은 항목.

  • 취약점 보고서는 _이미 구현_되어 있습니다 — PDF로, v0.13.0부터는 Excel(.xlsx) 로도 제공됩니다. 취약점 → 보고서 다운로드 (PDF 또는 Excel)(GET /v1/projects/{id}/vulnerability-report.pdf / .xlsx) 참고. 아직 구현되지 않은 것은 독립형 컴포넌트 Excel 내보내기와 컴플라이언스 PDF이며 향후 릴리스에서 제공됩니다. 컴포넌트 표가 즉시 필요한 이해관계자는 SBOM(CycloneDX JSON)을 선호 도구로 소비하십시오.
  • NOTICE 조립을 위한 컴포넌트 드로어의 수동 저작권 오버라이드 — 예정.
  • SBOM·NOTICE 내보내기의 과거 스캔 고정 — 예정.
  • SBOM / NOTICE 다운로드를 structlog 이벤트에서 audit_logs 행으로 승격 — 예정.

함께 보기