ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 서명된 빌드면 안전한 프로그램일까: artifact attestation 읽는 법
    Programming 2026. 9. 27. 01:07
    728x90
    반응형

    무늬가 찍힌 밀랍 봉인으로 닫은 소포와 옆에 놓인 도장
    산출물과 그 출처를 확인할 증거를 함께 살피는 상황을 표현한 생성 이미지입니다.

    서명된 빌드는 어떤 소스와 과정에서 만들어졌는지 검증하고, 코드 자체의 안전성은 별도 기준으로 판단하세요.

    다운로드 페이지에 서명과 attestation이 있습니다. 파일이 안전하다는 표시처럼 보이지만, 무엇에 대한 서명인지 확인하지 않으면 중요한 차이를 놓칩니다. 예상한 저장소의 빌드인지, 지금 받은 파일과 연결되는지, 그 빌드의 소스 자체를 신뢰할 수 있는지는 서로 다른 질문입니다.

    이 글은 2026년 9월 13일 GitHub·GitHub CLI·SLSA 공식 문서 기준으로 artifact attestation을 읽는 순서를 설명합니다. 실제 바이너리를 다운로드하거나 실행하지 않았으며 서명 생성·검증·릴리스·배포도 수행하지 않았습니다.

    attestation은 빌드 출처에 대한 서명된 주장입니다

    Artifact attestation은 산출물이 어디에서 어떤 과정으로 만들어졌는지 나타내는 provenance와 무결성 정보를 검증하는 데 쓰입니다. GitHub의 빌드 attestation에는 관련 워크플로, 저장소와 커밋, 실행 환경·이벤트 같은 정보가 연결될 수 있습니다. GitHub artifact attestations

    여기서 무결성은 받아서 확인하는 산출물이 서명된 주장에 연결된 대상과 같은지에 관한 질문입니다. provenance는 어떤 빌드와 소스에서 나왔는지에 관한 질문입니다. 소스 코드가 버그나 악성 동작이 없는지까지 자동으로 증명하는 것은 아닙니다.

    GitHub도 attestation이 산출물의 보안성을 보장하지 않으며 소비자가 정책 기준을 정하고 내용을 평가해야 한다고 명시합니다. “유효한 서명이 있다”와 “내가 실행해도 되는 프로그램이다”를 같은 결론으로 합치지 않습니다.

    생성만 해 두고 소비자가 검증하지 않는다면 기대한 보호 효과를 얻기 어렵습니다. 릴리스 페이지의 배지가 아니라 실제 받은 파일과 기대한 출처를 검증하는 절차가 필요합니다.

    파일명보다 산출물 digest를 연결합니다

    같은 이름의 tool.tar.gz라도 다시 빌드하거나 교체하면 바이트가 달라질 수 있습니다. 파일명이 같다는 이유로 어제의 검증 결과를 오늘 받은 파일에 재사용하지 않습니다.

    SLSA provenance는 빌드의 입력과 실행 정보를 설명하고, 산출물은 attestation의 subject와 연결됩니다. 이 구조를 통해 어떤 파일에 대한 주장인지와 그 파일을 만든 과정을 분리해 읽을 수 있습니다. SLSA provenance 구조

    검증 전에는 받은 파일, 다운로드 출처, 비교할 소스 리비전과 빌드 정책을 정합니다. 산출물 digest와 소스 커밋 digest도 같은 값이 아닙니다. 하나는 결과 파일의 바이트를, 다른 하나는 소스 저장소의 특정 상태를 식별합니다.

    파일이 바뀌면 산출물 검증을 다시 해야 합니다. 소스나 워크플로 조건을 바꿨다면 정책 대조도 다시 해야 합니다. 검증 결과가 있다는 사실보다 그 결과가 지금의 대상과 조건에 연결돼 있는지가 중요합니다.

    기대한 저장소와 서명 워크플로를 먼저 정합니다

    GitHub CLI의 gh attestation verify는 최소한 --repo 또는 --owner로 기대한 출처 범위를 지정하도록 합니다. 조직 전체보다 특정 저장소를 지정하면 검증할 신원 범위를 더 좁힐 수 있습니다. GitHub CLI 검증 기준

    하지만 특정 저장소라는 조건만으로 그 안의 모든 워크플로를 같은 수준으로 신뢰해야 하는 것은 아닙니다. 공개 릴리스용 워크플로인지, 테스트 목적으로 임의 입력을 받아 빌드한 경로인지 구분할 필요가 있습니다.

    CLI 문서는 서명한 워크플로를 --signer-workflow 등으로 확인하는 방법도 안내합니다. 재사용 워크플로에서 attestation을 만들었다면 실제 서명자는 그 재사용 워크플로일 수 있으므로 호출한 저장소의 파일만 보고 조건을 정하지 않습니다.

    같은 이유로 태그 이름 하나도 충분한 고정값인지 검토해야 합니다. 릴리스가 어떤 소스 커밋에서 만들어졌는지 확인하고, 필요하다면 검증 정책에서 그 커밋을 직접 제한합니다. 이름이 같다는 이유로 다른 소스 상태를 허용하지 않습니다.

    가상 배포 파일의 검증 조건을 명령으로 표현합니다

    예시에서는 ./downloads/tool.tar.gz라는 파일을 검토하려고 한다고 하겠습니다. 기대한 출처는 example-org/example-repo이고, 서명 워크플로는 그 저장소의 release.yml이라는 가정입니다. 모두 설명용 이름이며 실제 파일·저장소의 검증 결과가 아닙니다.

    다음 명령은 EXPECTED_SOURCE_SHA에 독립적으로 확인한 소스 커밋을 먼저 지정해야 진행되도록 합니다. 이 변수에 받은 attestation의 값을 무조건 복사해 넣는 것이 아니라, 사용하려던 릴리스의 기대값을 확인해야 합니다.

    : "${EXPECTED_SOURCE_SHA:?검토한 소스 커밋을 먼저 지정하세요}"
    
    gh attestation verify ./downloads/tool.tar.gz \
      --repo example-org/example-repo \
      --signer-workflow example-org/example-repo/.github/workflows/release.yml \
      --source-digest "$EXPECTED_SOURCE_SHA"
    

    --source-digest는 소스 저장소에 연결된 digest를 제한하는 옵션입니다. 산출물 파일의 해시를 넣는 옵션으로 혼동하지 않습니다. --signer-digest 같은 별도 옵션도 있으므로 각각 무엇을 고정하는지 CLI 문서를 읽어야 합니다. 검증 옵션의 의미

    이 명령은 기본적으로 GitHub API에서 관련 attestation을 가져오려고 합니다. 완전히 오프라인인 파일 검사라고 가정하지 않습니다. 비공개 저장소나 컨테이너 레지스트리의 자료라면 접근 권한과 검증 자료를 가져오는 경로도 별도 조건입니다.

    실제 실행에서는 명령의 성공·실패와 검증 결과를 확인해야 합니다. 여기에는 성공 출력이나 서명된 digest를 임의로 채우지 않았습니다. 명령 형태를 설명한 것과 실제 산출물을 검증한 것은 다릅니다.

    성공 결과에서도 어떤 주장을 검증했는지 봅니다

    GitHub CLI의 기본 검증 대상 predicate type은 SLSA provenance입니다. SBOM처럼 다른 종류의 attestation을 검증하려면 유형과 정책을 따로 확인해야 합니다. 의존성 목록에 대한 서명을 빌드 출처에 대한 서명과 같은 것으로 읽지 않습니다. 검증 대상의 predicate type

    성공 결과를 읽을 때는 산출물 대상, 저장소·서명자, 소스 커밋과 워크플로, 기대한 주장 유형이 모두 맞는지 확인합니다. 검증 과정이 통과했다는 한 줄만 잘라 보관하면 나중에 어떤 조건으로 통과했는지 알기 어렵습니다.

    예시에서 기대한 release.yml이 아닌 다른 워크플로의 산출물이라면 정책 위반으로 볼 수 있습니다. 반대로 실제로 승인한 재사용 빌더가 다른 저장소에 있다면 그 구조를 반영해 기대한 서명자 조건을 정해야 합니다.

    중요한 것은 실패를 없애려고 출처 조건을 계속 넓히지 않는 것입니다. 검증 대상이 잘못됐는지, 필요한 attestation이 없는지, 기대한 정책과 실제 빌드가 다른지부터 구분합니다.

    서명자가 신뢰할 수 있어도 소스가 무해하다는 보장은 없습니다

    정상 워크플로가 악성 변경이 들어간 소스를 빌드하면 그 결과에도 유효한 attestation이 생길 수 있습니다. 빌드 출처가 올바르다는 사실은 그 소스 변경을 사람이 검토했다는 뜻이 아닙니다.

    빌드 실행 환경이 공격자의 영향을 받는 경우에는 주장 내용의 신뢰도도 따져야 합니다. GitHub CLI 문서는 워크플로 실행 맥락을 공격자가 제어하면 predicate 내용을 위조할 수 있는 위험과 신뢰된 빌더의 필요를 설명합니다. 검증 결과를 정책에 사용할 때의 주의

    따라서 저장소 리뷰와 브랜치 보호, 워크플로·의존성의 고정과 검토, 빌더의 격리와 권한 같은 조건이 함께 필요합니다. 서명 검증을 추가했다고 코드 검토나 취약점 검토를 생략하지 않습니다.

    또한 attestation이 있다는 사실만으로 같은 소스를 다시 빌드했을 때 바이트가 같은 재현 가능한 빌드라고 결론 내릴 수는 없습니다. 재현성은 입력과 도구·환경을 맞춰 실제로 비교할 별도 성질입니다.

    서명은 누가 어떤 주장을 했는지 확인하는 데 도움을 줍니다. 그 주장이 어떤 신뢰 경계에서 만들어졌고 내가 요구하는 안전 기준을 충족하는지는 소비자의 평가가 남습니다.

    사용 전 정책과 배포 승인을 별도로 둡니다

    검증 정책에는 허용한 저장소와 서명 워크플로, 소스 리비전, 필요한 attestation 유형과 빌더 조건 등을 적을 수 있습니다. 모든 프로젝트가 같은 조건을 요구하는 것은 아니므로 위험과 배포 목적에 맞춰 정합니다.

    그다음 소스와 의존성 검토, 기능 테스트와 운영 권한 검토를 연결합니다. 출처가 확인된 파일이라도 운영 환경에서 실행할지, 어떤 권한을 줄지는 다른 결정입니다.

    검증에 실패했다고 곧바로 악성 파일이라고 단정하지 않습니다. 네트워크·인증 문제나 누락된 자료, 정책의 기대값 불일치가 원인일 수도 있습니다. 원인을 확인하기 전에는 검증되지 않은 상태로 남기고, 성공으로 바꾸기 위해 보호 조건을 제거하지 않습니다.

    반대로 검증이 성공했더라도 파일이 그 뒤 교체되면 이전 결과의 대상이 아닙니다. 검토·검증한 digest와 실제 실행·배포한 digest를 연결해야 최종 사용까지 같은 산출물이라는 근거가 이어집니다.

    배지보다 파일과 정책의 연결이 중요합니다

    Artifact attestation을 읽을 때는 “서명이 있다”에서 멈추지 않습니다. 지금 받은 파일과 연결되는지, 예상한 저장소·워크플로·소스에서 나온 주장인지, 그 빌드 경계를 신뢰할 수 있는지 확인합니다.

    이 검증은 출처와 무결성 판단을 돕지만 프로그램의 무해함이나 기능·운영 안전성을 모두 보장하지는 않습니다. 실제 실행 여부는 남은 코드·의존성·기능·권한 검토와 함께 결정해야 합니다.

    서명된 빌드를 안전하게 소비하려면 받은 파일, 검증한 조건과 결과, 실제 사용한 산출물을 같은 기록으로 연결하세요. 그 연결이 있어야 출처 증명이 실제 사용 단계의 판단에 도움이 됩니다.

    728x90
    반응형
Designed by Tistory.