콤퓨타수선집은 문체부지정 공식
저작권대리중개업체 육하원칙과 함께합니다.

콤퓨타지식 소프트웨어 공급망 보안: SBOM·서명·출처 증명의 차이

npm 패키지 검증부터 홈페이지 유지보수까지, 외부 코드를 확인하는 기준과 실무 적용법

페이지 정보

본문

작성일

중앙 소프트웨어 패키지 앞에 서명 카드, 제작 경로 기록, 구성요소 트레이를 배치한 개념 이미지
서명은 정체성을, 출처 증명은 제작 경로를, SBOM은 구성요소를 확인하는 근거다.

소프트웨어 공급망 보안에서 서명, 배포 출처 증명, 소프트웨어 구성요소 목록은 서로 다른 질문에 답한다. 서명은 파일과 서명자의 관계를, 출처 증명은 소스·빌드 경로와 배포물의 연결을, 구성요소 목록은 포함된 부품과 관계를 확인하는 데 쓰인다. 이 자료들을 연결하고 기대한 조건과 대조해야 외부 코드를 채택한 근거를 설명할 수 있다.

홈페이지는 직접 작성한 코드만으로 움직이지 않는다. 화면을 만드는 라이브러리, 이미지 처리 도구, 서버 모듈, 플러그인, 배포 자동화가 함께 작동한다. 외부 코드가 어디에서 왔는지 묻는 일은 최종 화면에 보이는 기능뿐 아니라 그 화면을 만드는 과정까지 살펴보는 일이다. 이 글은 공식 기술 문서를 바탕으로 각 검증 수단의 범위를 정리하고, 홈페이지 개발·유지보수에 적용할 수 있는 기록 방식을 제안한다.

먼저 구분할 세 가지 판단
① 서명과 파일의 연결이 유효한가?
② 소스·빌드 경로가 기대한 조건과 일치하는가?
③ 해당 코드의 동작을 서비스에서 허용할 수 있는가?
앞의 검증에 성공했다고 뒤의 판단까지 자동으로 끝나는 것은 아니다.

1. 소프트웨어 공급망 보안은 무엇을 확인하는가?

소프트웨어 공급망(Software Supply Chain)은 소스, 의존성, 빌드 도구, 배포 과정, 최종 파일이 연결되는 경로다. 공급망 보안은 이 경로에서 의도하지 않은 변경이 들어오는 위험을 줄이고, 채택한 배포물이 기대한 과정에서 나왔는지 확인하는 활동이다. 공급망 무결성 수준 체계(Supply-chain Levels for Software Artifacts, SLSA)의 빌드 검증 지침도 파일과 출처 증명의 연결, 신뢰하는 빌더, 기대한 소스와 입력값의 일치를 다룬다. [1]

소스 코드와 배포물(Artifact)은 구분해야 한다. 개발자는 저장소의 TypeScript 파일을 읽지만, 사용자는 변환된 JavaScript와 압축 패키지를 설치할 수 있다. 빌드 과정에서는 파일 생성, 코드 변환, 외부 자료 다운로드가 일어날 수 있다. 저장소를 확인한 사실과 최종 설치 파일을 확인한 사실은 같은 기록이 아니다.

예를 들어 홈페이지의 이미지 처리 도구를 검토했다고 가정하자. 저장소의 함수에는 문제가 없어 보이더라도 패키징 과정에서 추가된 파일이나 실행 절차는 별도 확인 대상이다. 이 사례는 이해를 위한 가상 상황이다. 공급망 검증에서는 검토한 소스, 사용한 빌드 경로, 실제 채택한 파일을 연결하는 근거가 필요하다.

2. 해시·서명·출처 증명·SBOM의 차이는 무엇인가?

해시는 파일의 일치 여부, 서명은 서명자와 파일의 연결, 출처 증명은 제작 경로, SBOM은 구성요소를 다룬다. 각 수단은 확인 대상이 다르므로 하나의 ‘안전 인증’으로 묶어 이해하면 검증 범위를 놓치기 쉽다. 다음 표의 한계 설명은 공식 문서의 기능 범위를 바탕으로 정리한 기술적 해석이다. [1] [2] [3] [4] [5]

소프트웨어 공급망 검증 수단 비교
수단확인하는 대상이것만으로 판단할 수 없는 것
해시·무결성 값기대한 값과 받은 파일의 바이트가 일치하는지기대한 값의 출처와 파일의 무해성
디지털 서명신뢰하는 키·정체성과 서명 대상의 연결, 대상의 변조 여부서명자가 승인한 코드의 안전성
배포 출처 증명소스·빌드 정보와 특정 배포물의 연결기록된 과정이 적절한지, 코드에 악성 동작이 없는지
SBOM명시된 범위의 구성요소·버전·관계목록의 완전성, 모든 파일의 무해성
취약점 검사의존성과 알려진 취약점 정보의 대응미공개 취약점이나 아직 분류되지 않은 악성 행위 전체

패키지를 받으며 ‘기대한 파일이 맞다’는 결과를 얻었더라도, 그 기대값을 처음부터 잘못된 배포물에서 가져왔다면 채택 판단은 여전히 잘못될 수 있다. 검증은 비교 대상이 신뢰할 만한지 정하는 일까지 포함한다. 파일의 일치 여부와 코드의 동작 적합성은 따로 설명해야 한다.

3. 디지털 서명은 무엇을 증명하는가?

디지털 서명(Digital Signature)은 대상 데이터와 서명 키의 관계를 검증하고, 서명 대상의 변경을 탐지하는 수단이다. 정체성 기반 검증에서는 키를 인증서의 정체성과 연결해 확인할 수 있다. 시그스토어(Sigstore)의 Cosign 문서는 키 없는 서명 검증에서 기대하는 인증서 정체성과 개방형 인증 연결(OpenID Connect, OIDC) 발급자를 지정하는 방법을 제공한다. [2]

따라서 ‘서명 검증 성공’이라는 문장을 읽을 때는 어떤 키나 정체성을 신뢰하도록 설정했는지 함께 물어야 한다. 정상적으로 서명된 파일이라도 그 서명자가 서비스 운영자가 채택하려던 공급자인지는 별도의 대조가 필요하다. 서명자가 해당 내용을 승인했다는 사실도 코드의 모든 동작을 허용할 이유가 되지는 않는다.

또한 npm 레지스트리 서명과 제작 과정의 출처 증명 서명은 구분해야 한다. npm의 npm audit signatures는 다운로드한 패키지의 레지스트리 서명을 검사하고 출처 증명도 검증한다. 이 결과를 설명할 때는 어떤 패키지와 증명을 확인했는지 기록해야 한다. ‘모든 개발자가 직접 서명한 코드’라고 일반화해서는 안 된다. [5]

기준 기록의 원형과 실제 기록의 육각형을 나란히 대조하는 출처 검증 개념 이미지
유효한 증명도 기대한 소스와 빌드 조건에 맞는지 대조해야 한다.

4. 배포 출처 증명은 어떻게 검증하는가?

배포 출처 증명(Provenance)은 특정 배포물과 소스·빌드 과정 사이의 검증 가능한 정보를 제공한다. npm은 출처 증명과 게시 증명(Publish Attestation)을 구분한다. 전자는 소스와 빌드 지침을 연결하고, 후자는 레지스트리가 권한 있는 게시자의 배포를 기록한다. npm 문서는 출처 증명이 악성 코드의 부재를 보장하지 않는다고 명시한다. [3]

검증은 증명 문서가 존재하는지 확인하는 데서 끝나지 않는다. SLSA 지침을 바탕으로 보면 다음 항목을 나누어 살펴볼 수 있다. 실제 구현에서는 사용한 증명 형식과 검증 도구가 제공하는 필드를 확인해야 한다. [1]

  1. 대상 연결: 증명 문서의 대상이 지금 받은 파일의 해시와 일치하는가?
  2. 증명의 신뢰: 증명 서명이 유효하고, 생성한 빌더를 신뢰할 근거가 있는가?
  3. 소스의 일치: 공식적으로 채택한 소스 저장소에서 만들어졌는가?
  4. 빌드 조건의 일치: 빌드 유형과 외부 입력값이 허용한 조건에 맞는가?

가상의 패키지 A가 평소에는 공식 저장소에서 만들어졌는데 새 버전은 다른 저장소에서 만들어졌다고 하자. 새 증명이 유효하게 서명돼 있더라도 저장소 변경을 승인하지 않았다면 채택을 보류할 이유가 생긴다. 반대로 승인된 저장소의 코드 자체에 문제가 있다면 출처 대조만으로 그 문제를 찾을 수는 없다.

신뢰 기반 배포와 출처 증명은 같은 기능인가?

신뢰 기반 배포(Trusted Publishing)는 OIDC를 사용해 승인된 자동화 실행 정체성에 배포 권한을 부여하는 방식이다. 장기간 보관하는 쓰기 토큰에 대한 의존을 줄인다. 출처 증명은 배포물의 제작 경로를 검증하기 위한 자료이므로 두 기능의 목적은 다르다. npm에서 출처 증명의 자동 생성에는 CI 제공자와 공개 저장소·패키지 여부 등의 조건이 있다. [6]

실무적으로는 배포 인증을 개선한 뒤에도 자동화가 실행하는 내용을 관리해야 한다. GitHub는 워크플로 토큰에 최소 권한을 부여하고 외부 액션을 전체 커밋 SHA로 고정하는 방법 등을 안내한다. 누구의 실행인가를 확인하는 작업과 그 실행이 어떤 파일을 만들어내는지 검토하는 작업을 연결해야 한다. [7]

5. SBOM은 무엇이며 사고 대응에 어떻게 쓰이는가?

소프트웨어 구성요소 목록(Software Bill of Materials, SBOM)은 소프트웨어에 포함된 구성요소와 관계를 구조화한 자료다. CycloneDX는 이를 통해 구성요소와 의존 관계 등을 표현한다. SBOM은 ‘무엇을 사용하고 있는가’를 추적할 근거가 되지만 생성 도구와 대상 범위에 따라 포함되는 정보가 달라질 수 있다. [8]

npm은 npm sbom으로 프로젝트의 의존성 목록을 SPDX 또는 CycloneDX 형식으로 출력할 수 있다. --package-lock-only를 쓰면 잠금 파일의 정보만 읽고 node_modules를 무시한다. 의존 패키지의 package.json에서 가져오는 설명·홈페이지·엔진 정보 등도 결과에서 빠질 수 있다. [4]

따라서 잠금 파일 기반 SBOM을 만들었다는 사실을 실제 설치 디렉터리의 모든 파일을 검사했다는 뜻으로 설명하면 안 된다. 홈페이지의 외부 CDN 스크립트, 별도 설치 플러그인, 서버 운영체제까지 이 명령 하나가 자동으로 포괄한다고 가정할 수도 없다. 생성한 목록의 대상과 실제 서비스의 전체 구성을 구분해야 한다.

세 서비스 중 첫 번째와 세 번째의 구성요소 트레이에 같은 네이비 부품이 포함된 모습
구성요소 기록을 서비스별로 연결하면 조사 대상 배포를 좁힐 수 있다.

가상 사례: 특정 버전의 문제가 발표됐을 때

가상의 이미지 처리 패키지 example-image-kit 2.4.1에 문제가 발표됐다고 가정하자. 유지보수자는 먼저 서비스별 구성요소 기록에서 해당 이름과 버전을 찾는다. 직접 설치한 패키지뿐 아니라 다른 패키지를 통해 들어온 간접 의존성도 확인한다. 이후 해당 서비스의 배포 이력과 실행 위치를 대조하고, 실제 영향과 조치 방법을 판단한다.

목록에 이름이 있다는 사실은 조사 대상이라는 뜻이다. 실제 악용 가능성과 노출 범위는 실행 환경·호출 경로·권한 등을 더 살펴봐야 한다. 반대로 목록에서 찾지 못했어도 목록의 생성 범위가 불완전했다면 사용하지 않았다고 단정할 수 없다.

이 글에서 제안하는 운영 방식은 SBOM과 함께 생성 날짜, 서비스 식별자, 소스 커밋, 배포 버전, 생성 도구 버전, 개발 의존성 포함 여부, 잠금 파일 기준인지 여부를 남기는 것이다. 이런 메타데이터가 있어야 서로 다른 시점의 목록을 비교하고 조사 대상 배포를 좁힐 수 있다.

6. 잠금 파일과 npm 명령은 어디까지 확인해주는가?

잠금 파일(Lockfile)은 해결된 의존성 트리를 기록하고, 서명 검사와 취약점 검사는 각각 별도의 검증을 수행한다. npm의 package-lock.json은 생성된 정확한 트리를 설명하며, 저장소에 포함해 의존성 변경을 확인하도록 설계돼 있다. 직접 의존성의 버전만 확인하면 간접 의존성의 변화를 놓칠 수 있으므로 전체 트리의 차이도 검토해야 한다. [9]

npm ci는 기존 잠금 파일을 요구하고, package.json과 잠금 파일의 의존성이 맞지 않으면 실패한다. 기존 node_modules를 제거한 뒤 설치하고 잠금 파일을 갱신하지 않는다. 이는 설치 일관성을 위한 동작이다. 잠긴 버전 자체가 문제가 있다면 일관되게 설치한다는 사실만으로 위험이 사라지지는 않는다. [10]

npm 검증·목록 생성 명령과 해석
명령주요 목적결과를 읽을 때의 기준
npm ci --ignore-scripts잠금 파일 기준 설치, package.json 스크립트 실행 억제설치 환경을 바꾼다. 이후 import되는 코드의 동작을 검사하는 기능은 아니다.
npm audit알려진 취약점 보고설정된 레지스트리에 의존성 설명을 보낸다. 결과의 검사 시점과 범위를 기록한다.
npm audit signatures다운로드한 패키지의 레지스트리 서명·출처 증명 검증증명 존재 여부와 검증 결과를 구분한다. 조직이 기대한 출처 정책까지 모두 구현했다고 가정하지 않는다.
npm sbom --sbom-format=cyclonedx --package-lock-only잠금 파일 기준 SBOM 출력실제 설치 파일의 실물 검사와 다르다. 생성 범위와 누락 메타데이터를 확인한다.

명령 설명의 근거는 npm 공식 문서다. --ignore-scripts를 설정해도 사용자가 명시적으로 요청한 npm run이나 npm test 등의 대상 스크립트는 실행될 수 있다. 정상 빌드에 필요한 설치 스크립트가 빠질 수도 있다. 또한 npm audit fix는 내부적으로 설치를 수행하므로 단순한 조회 명령으로 취급하면 안 된다. [4] [5] [10]

위 명령은 기능 설명을 위한 예시이며 고객 프로젝트에서 실행한 결과가 아니다. 설치 후 검사했다는 사실을 설치 시점의 실행 위험까지 사전에 차단했다는 의미로 해석하지 않는다. 프로젝트의 Node·npm 버전과 필요한 스크립트를 확인해 검증 절차를 설계한다.

7. 홈페이지 유지보수에서는 어떤 기록을 남겨야 하는가?

유지보수에서는 채택한 구성요소, 배포물, 검증 결과, 승인 이유를 서비스별로 연결해 남기는 것이 유용하다. 다음은 앞선 기술적 구분을 홈페이지 운영에 적용한 실무 제안이다. 특정 조직이 이미 시행 중인 절차나 모든 프로젝트에 적용되는 의무를 뜻하지 않는다.

서비스별 공급망 검증 기록의 예
단계남길 자료답할 수 있는 질문
의존성 채택잠금 파일, 직접·간접 버전 변경, 검토 이유무엇이 추가·변경됐는가?
빌드소스 커밋, 워크플로 변경, 실행 환경어떤 입력과 절차로 만들었는가?
배포물 확인최종 파일 식별자·해시, 제공되는 서명·증명검증한 파일과 배포한 파일이 연결되는가?
채택 승인검사 결과, 예외 사유, 승인자와 날짜어떤 범위를 확인하고 왜 허용했는가?
운영 추적서비스별 SBOM·구성 목록, 배포 이력, 담당자문제가 있는 부품을 어느 서비스에서 쓰는가?

빌드에만 쓰는 도구와 운영 서버에서 실행되는 코드는 목록을 구분하는 편이 좋다. 전자는 최종 파일을 만드는 과정에 영향을 줄 수 있고, 후자는 운영 중 실행 권한을 가진다. 한쪽 목록만으로 서비스의 전체 위험을 판단하기 어려운 이유다.

외부 코드의 모든 줄을 매번 전수 검토하기는 어렵다. 대신 예상과 다른 변경을 찾아 검토할 수 있도록 기록을 연결해야 한다. 잠금 파일이 크게 바뀌었는지, 빌드 경로가 달라졌는지, 새 실행 스크립트가 들어왔는지, 증명이 사라졌는지 등을 검토 항목으로 정할 수 있다. 증명이 없다는 사실 자체로 악성을 단정하지 않고 추가 검토나 예외 승인 기준을 마련하는 방식이다.

고객에게도 ‘보안 검사 완료’라는 한 문장보다 어떤 버전을 사용했고 어떤 검사를 언제 했으며 어떤 예외를 허용했는지 설명하는 편이 구체적이다. 공급망 신뢰는 이렇게 남긴 근거를 다음 업데이트와 사고 대응에서 다시 활용하는 과정으로 유지된다.

8. 소프트웨어 공급망 검증에 관한 자주 묻는 질문

SBOM이 있으면 취약점이 없는 소프트웨어인가?

아니다. SBOM은 구성요소를 설명하는 자료다. 포함된 버전을 취약점 정보와 대조하는 검사는 별도이며, 목록의 범위와 생성 시점도 확인해야 한다. [8]

서명과 출처 증명이 모두 유효하면 설치해도 안전한가?

그 결과만으로 무해성을 확정할 수는 없다. 서명 대상과 제작 경로를 확인한 뒤에도 코드의 동작과 서비스에서 허용할 권한을 판단해야 한다. npm도 출처 증명이 악성 코드 부재를 보장하지 않는다고 설명한다. [3]

취약점 검사 결과가 0건이면 공급망 문제가 없는가?

해당 검사에서 알려진 취약점을 찾지 못했다는 뜻으로 읽어야 한다. 모든 악성 동작을 심사하거나 미래에 공개될 취약점까지 배제한 결과가 아니다. [5]

잠금 파일이 있으면 재현 가능한 빌드인가?

잠금 파일만으로 충분하지 않다. 재현 가능한 빌드(Reproducible Build)는 같은 소스, 빌드 환경, 지침으로 누구나 바이트 단위로 동일한 결과를 만들 수 있는 성질이다. 의존성 고정 외에도 빌드 도구·환경·입력의 관리가 필요하다. 동일하게 재현되는 코드도 안전성 판단은 별도로 해야 한다. [11]

설치 스크립트를 막으면 악성 코드 실행을 모두 막을 수 있는가?

아니다. 설치 스크립트 제한은 특정 실행 경로를 줄이는 조치다. 이후 애플리케이션이 패키지를 불러 실행하는 경로까지 코드의 안전성을 검증해주는 기능은 아니다. [10]

용어 정리

직접 의존성·간접 의존성
프로젝트가 직접 선언한 패키지와, 그 패키지 등을 통해 추가로 필요한 패키지. 전체 의존성 트리를 함께 추적해야 한다.
배포물(Artifact)
빌드·패키징을 거쳐 배포하거나 설치하는 파일 또는 묶음.
증명 문서(Attestation)
특정 대상에 관한 주장을 담은 구조화된 자료. 출처 증명과 SBOM 등 서로 다른 내용을 담을 수 있으며, 주장 유형과 서명 여부를 구분해 읽는다.
빌더(Builder)
소스를 입력받아 배포물을 만드는 빌드 시스템. 검증에서는 해당 빌더를 신뢰할 기준이 필요하다.
CI/CD
지속적 통합·배포(Continuous Integration / Continuous Delivery). 코드 통합, 빌드, 검사, 배포 등의 절차를 자동화하는 체계.

참고 자료

기술적 사실은 아래 공식 문서를 근거로 정리했다. 가상 사례와 유지보수 기록 방식은 이를 적용한 설명·제안이다. 명령의 옵션과 지원 조건은 사용하는 도구 버전의 문서를 함께 확인한다.

  1. SLSA 1.2 — Build: Verifying artifacts
  2. Sigstore — Verifying Signatures
  3. npm — Generating provenance statements
  4. npm CLI 12 — npm sbom
  5. npm CLI 12 — npm audit
  6. npm — Trusted publishing for npm packages
  7. GitHub Actions — Secure use reference
  8. CycloneDX — Software Bill of Materials
  9. npm CLI 12 — package-lock.json
  10. npm CLI 12 — npm ci
  11. Reproducible Builds — Definitions