2P by GN⁺ 2일전 | ★ favorite | 댓글 2개
  • GitHub Actions는 워크플로 파일의 uses: 구문을 통해 패키지 의존성을 선언하고 실행하는 구조를 가지며, 이는 사실상 패키지 관리자 역할을 수행
  • 그러나 락파일(lockfile), 무결성 해시, 전이 의존성 고정, 의존성 트리 가시성 등 다른 패키지 관리자들이 기본으로 제공하는 기능이 전혀 없음
  • 연구 결과, 대부분의 GitHub Actions 사용자가 검증되지 않은 외부 코드를 실행하며, 코드 주입 취약점이 수천 개 워크플로에서 발견됨
  • GitHub이 일부 완화책(불변 릴리스, SHA 고정 정책 등)을 도입했지만, 전이 의존성이나 재현성 문제는 여전히 해결되지 않음
  • 이러한 구조적 결함은 소프트웨어 공급망 보안 전반에 영향을 미치며, GitHub Actions를 기반으로 한 다른 CI 시스템에도 동일한 문제가 전파됨

GitHub Actions의 패키지 관리 구조와 문제점

  • uses: actions/checkout@v4 같은 구문은 의존성 선언이며, GitHub이 이를 해석해 다운로드 및 실행함
    • 이는 일반적인 패키지 관리 동작과 동일하지만, 락파일이 없어 실행마다 다른 버전이 선택될 수 있음
  • 다른 패키지 관리자(npm, Cargo, NuGet 등)와 비교했을 때, Actions는 락파일, 전이 핀닝, 무결성 검증, 의존성 트리 가시성, 해석 명세 모두 결여
  • 락파일 부재가 핵심 문제로, 실행 시마다 의존성 해석이 달라져 비결정적 빌드가 발생

보안 연구 결과와 취약성

  • USENIX Security 2022 연구에 따르면, 99.7%의 리포지토리가 외부 개발자의 Actions를 실행하고, 97%는 검증되지 않은 제작자, 18%는 보안 업데이트 누락 상태
  • 후속 연구에서는 2.7백만 워크플로 중 4,300개 이상에서 코드 주입 취약점이 발견됨
  • GitHub Actions는 admittance control, execution control, code control, secrets 접근 제어 등 CI/CD 필수 보안 속성을 충분히 제공하지 않음

주요 기술적 결함

  • 가변 버전 문제: @v4 같은 태그는 유지자가 새 커밋으로 재태깅할 수 있어, 코드가 조용히 변경
    • 락파일이 있다면 해당 태그가 어떤 SHA로 해석되었는지 기록 가능
  • 전이 의존성 불투명성: Composite Action 내부에서 호출하는 다른 Action은 보이지 않으며 제어 불가
    • 연구에 따르면 JavaScript Actions의 54%가 보안 약점을 포함하며, 대부분이 간접 의존성에서 발생
    • tj-actions/changed-files 사건에서는 전이 의존성 업데이트를 통해 비밀 유출 공격이 발생
  • 무결성 검증 부재: npm이나 Cargo는 해시를 기록해 다운로드 검증을 수행하지만, Actions는 SHA 기반 신뢰에만 의존
  • 재실행 비재현성: GitHub 측이 “버전이 강제 푸시되면 최신 버전을 가져온다”고 명시, 같은 워크플로라도 다른 코드 실행 가능
  • 의존성 트리 비가시성: npm의 npm ls나 Cargo의 cargo tree 같은 기능이 없어, 전체 의존성 구조를 확인할 방법 없음
  • 해석 규칙 비공개: Actions의 의존성 해석은 문서화되지 않았으며, ActionManager.cs 코드에 단순한 재귀 다운로드 로직만 존재

추가 구조적 한계

  • 중앙 레지스트리 부재: Actions는 Git 리포지토리에 존재하며, 보안 스캔·악성 탐지·타이포스쿼팅 방지 기능이 없음
  • 공유 환경 문제: 여러 Action이 동일한 $PATH를 수정해 실행 순서에 따라 결과가 달라짐
  • 오프라인 실행 불가: GitHub에서 매번 다운로드해야 하며, 네트워크 없이 실행 불가능
  • 네임스페이스 취약성: GitHub 사용자명이 곧 네임스페이스로, 계정 탈취나 오타 공격에 노출
    • 락파일과 무결성 해시가 있다면 코드 변경 시 빌드 실패로 탐지 가능

설계 배경과 파급 효과

  • Actions 러너는 원래 Azure DevOps 기반으로, 내부 신뢰 환경을 전제로 설계됨
    • GitHub이 이를 공용 마켓플레이스로 확장하면서 신뢰 모델을 재설계하지 않음
  • 이로 인해 락파일, 무결성 검증, 전이 핀닝, 의존성 가시성 같은 기본 기능이 누락
  • OIDC 기반 패키지 자동 배포 기능이 확산되면서, Actions의 보안 결함이 패키지 레지스트리 전체 공급망 보안에 영향
  • GitLab CI는 integrity 키워드를 도입해 해시 검증을 지원하지만, GitHub은 동일 요청을 “계획 없음”으로 종료
  • Forgejo Actions 등 GitHub 호환 CI 시스템도 동일한 구조를 유지해야 하므로, 결함이 생태계 전반으로 확산

개선 제안과 현황

  • 커뮤니티는 락파일 지원(issue #2195) 을 요청했으나, GitHub은 2022년에 “계획 없음”으로 닫음
  • Palo Alto 연구는 SHA 고정만으로는 전이 의존성 보호 불가함을 입증
  • 일부 팀은 Dependabot 업데이트, 자체 리포지토리 벤더링, zizmor 보안 스캐너 등으로 보완
  • 근본적 해결책은 모든 Action과 전이 의존성의 SHA 및 무결성 해시를 기록하는 락파일 도입
  • GitHub이 이를 채택하지 않는 한, CI/CD 공급망의 신뢰성 확보는 불가능

털려봐야 정신 차리겠죠 뭐

Hacker News 의견
  • GHA(GitHub Actions)를 옹호하고 싶진 않지만, 문서에는 안정성과 보안을 위해 커밋 SHA 고정을 권장한다고 명시되어 있음
    직접 lock 파일처럼 구현할 수는 있지만, transitive dependency는 제어 불가능하므로 완전하지 않음
    결국 보안 패치 추적과 해시 갱신의 부담이 생기며, 이런 이유로 해시 기반 고정이 널리 쓰이지 않는 듯함

    • GitHub은 Actions 출시 직후부터 이 문제를 알고 있었음에도, 버전 고정 기능을 실질적으로 개선하지 않았음
      대부분의 사용자는 문제를 인식하지 못하고, 인식한 사람도 SHA를 거의 사용하지 않음
      나는 개인적으로 Actions를 좋아하고 몇 가지를 유지보수하지만, 공개 저장소를 보면 90%가 @v1, 9%가 @v1.2, 1%만 커밋 SHA를 씀
      GitHub이 조금만 투자해도 lock 파일 솔루션을 만들 수 있었을 것임
    • 문서의 전략은 transitive dependency 문제를 해결하지 못하므로, 실제로는 근본적인 해결책이 아님
    • 커밋 SHA 고정이 안정적이라는 말은 현실적으로 틀림
      종종 특정 Node 버전이나 API 버전에 의존하기 때문에, 오히려 @main을 쓰는 게 더 나았던 경험이 있음
    • SHA를 쓰는 건 오히려 안티 패턴이라고 생각함
      “고정된 버전”을 얻는다고 착각하지만 실제로는 그렇지 않음
      두 번이나 문제를 겪고 나서 깨달았음 — lock 파일이 있거나 없거나 둘 중 하나임
  • GitHub이 자체 Actions를 거의 유지보수하지 않고, 기본 기능조차 비공식 포크에 의존하게 됨
    생태계 전체가 임시방편으로 유지되는 느낌임

    • 이런 상황은 당분간 나아지지 않을 듯함
      GitHub이 기능 개발보다 Azure 마이그레이션을 우선시한다고 발표했기 때문임
      관련 기사
    • 흥미로운 점은 GitHub이 꽤 비싼 서비스라는 것임
      우리 소규모 회사도 매달 200달러 이상을 지불함
      Windows보다 GitHub 구독이 더 중요한 신규 수익원으로 여겨지는 듯함
    • setup- actions*의 품질이 눈에 띄게 떨어졌고, 이상한 결정이 많아짐
      아마 원 저자들이 이미 회사를 떠난 듯함
    • 이런 얘기는 처음 들었는데, 혹시 구체적인 예시가 있는지 궁금함
    • 최근 GitHub이 AI 개발에 집중하기 위해 일반 기능 개발 속도를 늦춘다고 발표하지 않았는지?
  • 혹시 ArgoCD를 CI 파이프라인으로 써본 사람이 있는지 궁금함

  • GHA는 ‘less is more’ 철학의 실패 사례라고 생각함
    업계 표준이 된 게 가장 큰 문제임
    조금만 투자해도 훨씬 나은 CI를 만들 수 있었는데, MS가 IE6 시절의 실수를 반복한 느낌임
    이제는 비교 경험이 없는 젊은 엔지니어 세대가 그 한계를 인식하지 못함

    • GHA가 정말 형편없다는 데 모두 동의하지만, 무료 컴퓨팅 리소스가 제공된다는 점 때문에 다들 계속 씀
      나는 은퇴한 노트북을 Woodpecker 서버로 돌려볼 생각임. 사람들이 싫어하지 않는 CI가 어떤지 궁금함
    • 예전에는 VSS를 써야 했던 세대라서, 지금의 GitHub조차 그때보단 훨씬 나은 환경이라고 느낌
    • 나는 대부분의 작업을 로컬에서 직접 수행하는 편임
      GHA는 그에 비해 별다른 가치가 없는 것 같음
  • 회사가 Jenkins/Ansible에서 GHA로 옮기려 했을 때 반대했는데, 지금 보니 잘한 선택 같음
    CI는 항상 유지보수 부담이 크고, 특히 Mac 환경은 여전히 다루기 까다로움

  • “GitHub이 올바른 SHA 코드를 제공한다고 믿는가?”라는 질문에,
    대부분이 GitHub 호스팅 러너를 쓰는 현실을 보면, 그걸 믿지 못한다면 이미 더 큰 문제가 있는 셈임

  • 만약 GitHub Actions가 로컬 우선(local-first) 구조로, Nix 기반 잠금(locking) 을 지원한다면 어떨까 하는 생각이 듦
    cachix/cloud.devenv.sh

    • 아이러니하게도 그 코드조차 GitHub에 호스팅되어 있음
  • 많은 서드파티 Actions가 문서나 예제에서 master 브랜치를 직접 참조함
    악의적인 푸시 한 번이면 수많은 저장소에서 데이터 유출이 가능함
    태그를 써도 이동 가능하므로 완전한 방어는 아님

  • 연구자들이 말한 CI/CD의 네 가지 핵심 보안 속성(인증, 실행, 코드, 비밀 접근)을 보며 의문이 생김
    CI/CD가 정말 비밀(secrets) 에 접근할 필요가 있을까?
    API 호출 권한만 있으면 충분하다고 생각함
    이상적인 시스템은 비밀을 직접 다루지 않고, 보안 엔클레이브 같은 어댑터를 통해 간접적으로 처리해야 함

    • “좋은 CI는 비밀을 지원하지 않아야 한다”는 말은 결국 복잡한 비밀 관리 방식을 제안하는 셈임
      현실적으로 고객 대부분은 여전히 비밀을 필요로 함
    • 이론적으로는 맞지만, 실제로 사람들은 CI/CD에 비밀을 넣을 수밖에 없음
      플랫폼이 최소한 안전한 비밀 관리 메커니즘을 제공해야 함
      특히 오픈소스 프로젝트는 CI에서 직접 배포를 원하기 때문임
    • 우리 회사는 QNX 컴파일러나 Coverity 같은 상용 도구를 쓰는데, 이들은 라이선스 서버 접근을 위해 비밀이 필요함
      “보안 엔클레이브 방식”이 구체적으로 어떻게 다른지 궁금함
    • CI/CD가 인프라와 완전히 통합되어 있다면 비밀 없이도 배포가 가능하겠지만,
      현실적으로는 환경마다 다르고 구현 비용이 커서 대부분은 컨테이너 + 환경변수 방식으로 정착됨
    • 여러 클라우드 DB와 호환성을 테스트하려면 각 DB에 접근할 자격 증명이 필요함
      이런 테스트를 자동화하려면 비밀이 불가피함
  • lock 파일을 저장소에 커밋해야 한다면, 처음 생성 시점에 부트스트래핑 문제가 생김
    이를 해결하려면 Actions를 로컬에서 실행할 수 있는 기능이 필요함
    nektos/act 같은 도구가 있지만, 이는 주로 디버깅용임
    아마도 정적 분석 기반의 별도 메커니즘이 필요할 것임