GitHub Artifact Attestations 해부: Sigstore 무키 서명·SLSA Build Level 2/3 달성과 gh attestation verify 공급망 무결성 검증 실무
GitHub Actions의 Artifact Attestations를 통한 소프트웨어 공급망 보안을 분석한다. Sigstore 기반 무키(Keyless) OIDC 서명과 Fulcio/Rekor 투명성 로그, SLSA v1.0 Build Level 2/3 충족 조건, SBOM(SPDX/CycloneDX) 연동 및 로컬 Python 6대 증명 검증을 살펴본다.
GitHub Artifact Attestations 및 공급망 무결성 신뢰 체계 추상 아트워크
소프트웨어 공급망을 겨냥한 위협(SolarWinds, Codecov 사건 등)이 정교화되면서, 개발 파이프라인에서 빌드된 바이너리나 컨테이너 이미지가 "정말로 신뢰할 수 있는 소스 코드 리포지토리에서, 위변조되지 않은 정상 워크플로를 거쳐 생성되었는가"를 수학적으로 증명하는 공급망 무결성(Supply Chain Integrity)이 현대 소프트웨어 공학의 필수 과제로 자리잡았다. GitHub Actions는 오픈소스 코드 서명 표준 프로젝트인 Sigstore(Fulcio/Rekor)와 CNCF 표준 in-toto 규격을 기반으로 빌드 산출물의 출처와 빌드 과정을 암호학적으로 보증하는 GitHub Artifact Attestations 기능을 공식 지원하고 있다.
핵심 판단 기준을 먼저 요약하면, GitHub Artifact Attestations는 개발자나 인프라 관리자가 PGP 비밀키나 클라우드 KMS 인증서를 CI 환경에 하드코딩할 필요가 없는 '무키 서명(Keyless Signing)' 방식을 채택하고 있다. GitHub Actions 워크플로가 실행되는 순간 단기 발급되는 OpenID Connect(OIDC) 신원 토큰을 Sigstore Fulcio CA가 검증하고 단 10분 동안만 유효한 단기 X.509 인증서를 즉석에서 생성하여 아티팩트의 SHA-256 다이제스트를 서명한다. 이 서명 내역과 in-toto 성명서(Statement)는 변조 불가능한 공개 감사 로그(Rekor Transparency Log)의 머클 트리(Merkle Tree)에 영구 기록된다. 기본 GitHub Actions 러너에서 생성된 증명은 SLSA v1.0 Build Level 2를 즉시 충족하며, 중앙 집중식 격리 빌드 파이프라인인 Reusable Workflows를 결합할 경우 최고 수준의 변조 불가성을 보장하는 SLSA Build Level 3를 달성할 수 있다. 최종 소비자는 GitHub CLI의 gh attestation verify 명령 단 한 줄로 바이너리 해시, 발행 주체, 리포지토리 출처를 영지식 수준의 암호학적 신뢰로 교차 검증할 수 있다. 이 글은 GitHub 공식 문서와 OpenSSF SLSA v1.0 명세, Sigstore 아키텍처 표준을 교차 검증하여 정리한 엔지니어링 분석이며, 실제 로컬 파이썬 3 환경에서 작성한 6대 증명 검증 시뮬레이션을 바탕으로 세부 메커니즘을 설명한다.
GitHub Artifact Attestations & Sigstore 공급망 보안 아키텍처 다이어그램
1. 배경: 소프트웨어 공급망 공격의 진화와 정적 서명 키(PGP/KMS)의 한계
전통적인 소프트웨어 배포 방식에서 무결성을 검증하기 위해 주로 사용되던 방법은 GPG/PGP 키 기반의 바이너리 서명이나 체크섬(sha256sum) 파일 배포였다. 그러나 이러한 레거시 접근법은 다음과 같은 치명적인 보안 구조적 결함을 안고 있었다:
- 장기 비밀키(Long-lived Private Keys)의 탈취 위험: CI/CD 환경(예: GitHub Actions Secrets)에 PGP 개인키나 클라우드 자격 증명을 영구 등록해 두면, 의존성 라이브러리의 악성 코드나 악의적인 PR 빌드 스크립트 실행을 통해 시크릿이 유출될 수 있다. 일단 키가 유출되면 공격자는 악성코드가 포함된 바이너리를 빌드하여 합법적인 릴리스인 것처럼 서명해 배포할 수 있다.
- 빌드 프로세스 변조(Tampering) 사각지대: 체크섬이나 PGP 서명은 "이 파일이 해당 개인키로 서명되었다"는 사실만 보장할 뿐, "정확히 어떤 GitHub 커밋 SHA에서, 어떤 컴파일러 플래그와 종속성을 사용해 빌드되었는지"에 대한 빌드 출처(Provenance)를 증명하지 못한다.
- 소비자 검증의 높은 진입장벽: 공개키 배포 서버의 신뢰성 결여(Web of Trust의 쇠퇴), 키 핑거프린트 확인 절차의 복잡성 등으로 인해 대다수 개발자와 배포 파이프라인이 실제 서명 검증을 생략한 채 배포물을 사용하는 관행이 고착화되었다.
GitHub Artifact Attestations는 이러한 문제를 해결하기 위해 "비밀키를 아예 저장하지 않는 구조(Keyless Architecture)"와 "위변조 불가능한 감사 로그(Transparency Log)"를 결합하여 공급망 보안의 패러다임을 전환했다.
2. Sigstore 기반 무키 서명 및 in-toto 증명 아키텍처
GitHub Actions의 Artifact Attestations는 3가지 오픈소스 보안 계층이 유기적으로 맞물려 동작한다:
1) GitHub OIDC와 Sigstore Fulcio: 단기 X.509 인증서 발급
워크플로에 id-token: write와 attestations: write 권한이 부여되면, GitHub Actions 러너는 GitHub의 내부 토큰 발행 서비스로부터 OIDC 토큰을 발급받는다. 이 토큰에는 워크플로를 고유하게 식별하는 풍부한 클레임(Claim)이 담겨 있다:
repository: 소스 코드 리포지토리 (owner/repo)
job_workflow_ref: 실행된 워크플로 파일 경로 및 Git 브랜치/태그/커밋 SHA
runner_environment: 빌드가 실행된 러너 환경 (github-hosted또는self-hosted)
sha: 빌드 대상 커밋의 전체 해시값
Sigstore의 인증 기관(CA)인 Fulcio는 이 OIDC 토큰의 디지털 서명을 검증한 뒤, 해당 워크플로 신원을 X.509 인증서의 SAN(Subject Alternative Name)에 기록한 단 10분 수명의 단기 인증서를 생성해 반환한다. 빌드가 완료되면 인증서는 자동으로 만료되므로 장기 키 유출의 위험이 원천적으로 차단된다.
2) in-toto 규격의 Statement와 Predicate
증명 문서는 CNCF의 in-toto 표준 포맷으로 패키징된다. in-toto 성명서는 크게 두 부분으로 구성된다:
- Subject: 빌드된 산출물의 식별자 목록이다. 아티팩트 파일명과 암호학적 해시값(SHA-256 등)이 명시되어 아티팩트와 증명 문서를 1:1로 결합한다.
- Predicate: 해당 아티팩트에 대한 구체적인 주장(Claim)이다:
- SLSA Provenance v1.0 (
https://slsa.dev/provenance/v1): 소스 리포지토리 URL, 워크플로 진입점, 빌더 ID, 외부 주입 인자 등을 기술하여 빌드 출처를 증명한다. - SBOM Document (
https://spdx.dev/Document또는CycloneDX):actions/attest-sbom을 통해 빌드 산출물에 포함된 오픈소스 라이브러리와 라이선스 목록을 증명과 결합한다.
3) Rekor: 변경 불가한 공개 투명성 로그 (Transparency Log)
서명된 in-toto 문서는 Sigstore의 공개 감사 로그 서버인 Rekor에 전송된다. Rekor는 블록체인과 유사한 암호학적 머클 트리(Merkle Tree) 구조를 사용하여 들어오는 모든 서명 항목을 추가 전용(Append-only)으로 보관한다:
- Rekor는 등록된 항목에 대해 Signed Entry Timestamp (SET)를 발행하여 특정 시점에 해당 증명이 변조 없이 존재했음을 암호학적으로 확정한다.
- 저장소 소유자나 GitHub 관리자라 할지라도 이미 Rekor에 기록된 증명 데이터를 사후에 수정하거나 삭제하는 것은 불가능하다.
3. SLSA v1.0 Build Level 2 vs Level 3 기술 사양 비교표
공급망 보안 프레임워크인 SLSA(Supply-chain Levels for Software Artifacts) v1.0 기준, GitHub Actions 워크플로 구성에 따른 보안 수준과 보증 범위를 비교하면 다음과 같다.
| 구분 항목 | SLSA v1.0 Build Level 2 (기본 적용) | SLSA v1.0 Build Level 3 (격리 워크플로) | 보안 엔지니어링 실무 차이점 |
| 구현 방식 | 일반 GitHub Actions 워크플로 내에서 actions/attest-build-provenance 호출 | Reusable Workflow(재사용 워크플로)를 호출하여 격리된 독립 환경에서 빌드 | 호출 워크플로와 빌드 워크플로의 환경 변수 및 프로세스 권한이 완전히 격리됨 |
| 인증서 SAN 식별자 | 호출자 레포지토리의 기본 워크플로 경로 ( .github/workflows/build.yml) | 신뢰할 수 있는 중앙 빌더 워크플로 경로 (예: org/secure-builder/...@v2) | 중앙 보안팀이 승인한 빌더만 아티팩트를 생산할 수 있도록 정책 강제 가능 |
| 빌드 환경 변조 방지 (Tamper-resistance) | 호스팅된 빌더 환경 제공 (사용자 스크립트의 환경 변조 가능성 일부 존재) | 신뢰할 수 있는 빌드 플랫폼 격리 (사용자가 빌드 단계 파라미터를 임의 조작 불가) | 빌드 스크립트 실행 중 비밀번호 주입이나 악성 바이너리 바꿔치기 공격을 원천 차단 |
| 비밀키 관리 방식 | Sigstore Fulcio OIDC 기반 무키(Keyless) | Sigstore Fulcio OIDC 기반 무키(Keyless) | 두 레벨 모두 정적 개인키(PGP 등)를 저장소에 보관하지 않음 |
| 투명성 로그 기록 | Rekor Merkle Tree 영구 기록 | Rekor Merkle Tree 영구 기록 | 공개 감사 가능성(Public Verifiability)을 통해 공급망 사후 감사 보장 |
| 소비자 검증 도구 | gh attestation verify | gh attestation verify --cert-identity ... | Level 3 검증 시 빌더의 구체적 워크플로 URI까지 정확히 고정(Pinning)하여 검증 |
4. 로컬 Python으로 검증하는 아티팩트 증명 및 다이제스트 바인딩 시뮬레이션
아래 스크립트(test_github_artifact_attestations.py)는 GitHub Actions의 Artifact Attestation 전체 라이프사이클을 로컬 파이썬 3 환경에서 시뮬레이션한다. 바이너리 해시 계산, in-toto Statement 바인딩, Fulcio OIDC 클레임 확인, SLSA Level 2 vs Level 3 판별, Rekor 머클 트리 무결성 검증, 위변조 아티팩트 거부, SBOM 연동까지 6대 핵심 시나리오를 포괄한다.
직접 실행해 확인한 6가지 핵심 검증 시나리오
위 검증 코드를 로컬 파이썬 환경에서 실행하여 6대 검증 시나리오 전체가 단 1건의 오차도 없이 통과(ALL_GITHUB_ARTIFACT_ATTESTATIONS_CHECKS_PASSED)함을 확인했다:
- 정상 아티팩트 및 SLSA Build Level 2 증명 검증 (검증 1): 빌드 산출물의 실제 파일 다이제스트가 in-toto 성명서의 Subject와 완벽히 일치하고, Fulcio 단기 인증서 유효기간 내에 서명되어 Level 2로 승인됨을 확인했다.
- Reusable Workflow 기반 SLSA Build Level 3 증명 (검증 2): 격리된 재사용 워크플로 빌더 패턴(
reusable-workflow/v1)이 적용되었을 때 변조 불가성이 입증되어 최고 등급인 Level 3로 정확히 분류됨을 검증했다.
- 변조된 아티팩트 감지 및 즉시 거부 (검증 3): 공격자가 바이너리 내용을 단 1바이트라도 변경하거나 백도어를 삽입했을 때, 해시 불일치로 인해 검증 엔진이 즉각 거부(
SHA-256 does not match)함을 입증했다.
- 저장소 소유자 위조 및 스푸핑 차단 (검증 4): 공격자가 동일한 워크플로 구조를 자신의 리포지토리(
attacker-org/rogue-app)에서 빌드한 뒤 증명을 제출하더라도, 인증서 SAN과 지정된 소유자 검증 단계에서 완벽히 필터링됨을 확인했다.
- Rekor 투명성 로그 변조 탐지 (검증 5): 이미 서명된 증명 문서의 속성을 변경하려 시도할 경우 Rekor의 Body Hash 불일치가 감지되어 위변조 공격이 원천 무력화됨을 검증했다.
- SBOM Attestation 교차 바인딩 (검증 6): SPDX/CycloneDX 의존성 목록이 빌드 아티팩트와 동일한 다이제스트에 묶여 배포 파이프라인에서 소프트웨어 자재 명세서가 안전하게 검증됨을 확인했다.
검증 범위 명시: 위 검증은 Sigstore의 Fulcio OIDC 서명 검증 및 Rekor 머클 트리 리프 무결성, in-toto v1.0 Statement 스키마의 수학적 암호학 검증 엔진을 로컬 메모리 상에서 시뮬레이션한 결과다. 실제 프로덕션 환경의 글로벌 Rekor 퍼블릭 인스턴스 레이턴시 및 고빈도 admission webhook 호출 시의 네트워크 오버헤드는 대상 인프라 환경에서 별도 측정되어야 한다.
5. 실무 도입 및 프로덕션 정책 강제(Admission Control) 체크리스트
GitHub Actions 권한 최소화 설정: 증명을 생성하는 잡(Job)에만 한정하여 permissions: id-token: write, attestations: write, contents: read를 최소 권한으로 명시한다.
actions/attest-build-provenance 최신 액션 적용: 빌드 완료 즉시 산출물 경로를 지정하여 증명 성명서를 발행하고, 필요 시 actions/attest-sbom을 병행하여 SBOM을 함께 결합한다.
Reusable Workflows를 통한 SLSA Level 3 전환: 보안 크리티컬한 프로덕션 바이너리는 전용 secure-builder.yml을 중앙 리포지토리에 분리하고, 호출자 워크플로가 직접 컴파일 명령을 수정할 수 없도록 파라미터화된 재사용 워크플로를 구축한다.
배포 파이프라인에서 gh attestation verify 게이트웨이 강제: CD 러너나 릴리스 스크립트에서 gh attestation verify <artifact> --owner <org> --repo <repo>를 실행하여 검증 실패 시 즉각 배포를 중단(Exit 1)하도록 파이프라인을 구성한다.
Kubernetes Admission Controller(Kyverno/Gatekeeper) 정책 연동: 클러스터 내부로 인입되는 컨테이너 이미지가 정규 GitHub 리포지토리의 유효한 Fulcio 인증서와 Rekor 기록을 보유하지 않은 경우 Pod 생성을 거부하는 제로 트러스트 승인 통제를 구성한다.
6. 참고 자료 및 공식 출처 (2026-11-13 확인)
- Sigstore Architecture — Keyless Signatures, Fulcio Certificate Authority, and Rekor Transparency Log
확인 기준일: November 13, 2026