1P by GN⁺ 2시간전 | ★ favorite | 댓글 1개
  • 공식 GitHub Action이 태그 강제 업데이트로 변조되어 악성코드가 배포된 공급망 공격 발생
  • 공격자는 76개 중 75개 태그를 악성 커밋으로 교체, 약 1만 개 이상의 워크플로가 영향을 받음
  • 변조된 스크립트는 비밀정보 수집·암호화·유출의 3단계로 동작하며, TeamPCP Cloud stealer 코드가 포함됨
  • 감염된 태그는 여전히 활성 상태로, @0.35.0 또는 특정 commit SHA만 안전한 것으로 확인됨
  • 모든 자격 증명 교체와 commit SHA 고정 사용이 필수이며, Docker Hub 이미지도 동일한 오염이 확인됨

Trivy GitHub Actions 공급망 공격 개요

  • Trivy의 공식 GitHub Action(aquasecurity/trivy-action)이 공격자에 의해 태그 강제 업데이트(force-push) 방식으로 변조되어 악성코드가 배포된 사건
  • 공격자는 76개 버전 태그 중 75개를 악성 커밋으로 교체, CI/CD 파이프라인에서 자동 실행되도록 조작
  • 10,000개 이상의 GitHub 워크플로 파일이 해당 액션을 참조하고 있어 피해 범위가 광범위함
  • 감염된 태그는 여전히 활성 상태이며, @0.35.0만이 유일하게 안전한 버전으로 확인됨
  • Socket은 19:15 UTC부터 실시간으로 182건의 악성 GitHub Action 이벤트를 탐지, Backdoor, Infostealer, Reconnaissance 유형으로 분류

공격의 원인과 진행 방식

  • Trivy 유지관리자에 따르면, 이번 공격은 쓰기 권한이 있는 자격 증명 탈취로 인해 발생
    • 3월 초 발생한 이전 침해에서 CI 환경의 비밀이 유출되었으며, 회전(rotating) 과정이 완전하지 않아 새 자격 증명 일부가 공격자에게 남음
    • 공격자는 이 자격 증명을 이용해 GitHub 자체 취약점 없이 인증된 태그 업데이트를 수행
  • 공격자는 브랜치 푸시나 릴리스 생성 대신, 기존 태그를 강제로 새 커밋으로 덮어씀
    • 각 태그는 원래 커밋의 메타데이터(작성자, 이메일, 타임스탬프, 커밋 메시지)를 복제해 정상처럼 보이게 위조
    • 단, 원본 커밋은 GPG 서명되어 있었으나 공격자의 커밋은 서명 누락, 부모 커밋 날짜가 2026년으로 불일치
  • GitHub의 Immutable Release 표시가 있더라도, 공격자가 악성 상태로 게시 후 잠금 처리했을 가능성 있음
    • 따라서 “Immutable” 배지에 의존하지 말고 commit SHA 고정(pinning) 방식만이 안전한 소비 방법임

태그 변조 구조

  • 공격자는 master 브랜치의 최신 커밋(57a97c7e)을 기반으로 새 커밋을 생성
    • entrypoint.sh 파일만 악성 버전으로 교체하고 나머지 파일은 그대로 유지
    • 각 태그는 원래의 PR 번호, 커밋 메시지, 작성자 정보를 그대로 복제해 위조
  • GitHub 릴리스 페이지에서 “0 commits to master since this release”로 표시되는 경우, 변조된 태그의 시각적 지표로 확인 가능
  • 0.35.0 태그만 변조되지 않은 이유는 이미 master HEAD를 가리키고 있었기 때문

악성 페이로드 구조

  • 변조된 entrypoint.sh는 총 204줄이며, 4~105줄에 Infostealer 코드, 이후 정상 Trivy 스캔 코드 포함
  • 악성코드는 세 단계로 구성됨
    • 1단계: 수집(Collection) — 런너 프로세스 메모리 및 파일시스템에서 비밀정보 추출
    • 2단계: 암호화(Encryption) — AES-256-CBC 및 RSA-4096으로 수집 데이터 암호화
    • 3단계: 유출(Exfiltration) — 공격자 제어 도메인 또는 피해자 GitHub 계정으로 전송
  • 1단계: 비밀정보 수집

    • GitHub Actions 런너 프로세스(Runner.Worker, Runner.Listener, runsvc, run.sh)의 환경변수를 /proc/<pid>/environ에서 읽어 env, ssh 키워드 포함 항목을 추출
    • GitHub 호스팅 런너에서는 Python 기반 메모리 덤프 스크립트sudo로 실행, Runner.Worker 프로세스 메모리에서 "isSecret":true 패턴을 검색
    • 자체 호스팅 런너에서는 TeamPCP Cloud stealer로 식별되는 파일시스템 크리덴셜 수집기 실행
      • SSH 키, AWS/GCP/Azure 자격 증명, Kubernetes 토큰, Docker 설정, DB 비밀번호, 환경파일, TLS 키, VPN 설정, Webhook URL, 지갑 키 등 광범위한 대상 포함
  • 2단계: 암호화

    • openssl rand로 32바이트 세션 키 생성 후, AES-256-CBC로 데이터 암호화
    • 세션 키는 RSA-4096 공개키로 OAEP 패딩을 적용해 암호화
    • 암호화된 데이터(payload.enc)와 세션 키(session.key.enc)를 tpcp.tar.gz로 묶음
  • 3단계: 데이터 유출

    • 1차 채널: https://scan[.]aquasecurtiy[.]org로 HTTPS POST 전송 (aquasecurity 오타 도메인 사용)
    • 2차 채널: 실패 시 피해자의 GitHub Personal Access Token을 이용해 tpcp-docs라는 공개 저장소 생성
      • 릴리스 자산으로 tpcp.tar.gz 업로드 → 공격자는 GitHub 검색으로 해당 저장소를 찾아 데이터 수집
    • GitHub 인프라를 이용해 방화벽 우회를 시도, 탐지 회피 가능성 높음
    • 마지막으로 임시 파일 삭제, 흔적 최소화

공격자 및 배후

  • 악성 코드 내 주석에 “TeamPCP Cloud stealer” 명시
    • TeamPCP(DeadCatx3, PCPcat, ShellForce)는 클라우드 네이티브 환경 공격 그룹으로, Docker API·Kubernetes·Redis·Ray 대시보드 취약점 악용 사례 존재
    • 2026년 2월 Flare와 The Hacker News에서 랜섬웨어·데이터 탈취·암호화폐 채굴 캠페인으로 보고된 바 있음
  • Solana 검증자 키 및 암호화폐 지갑 수집 기능은 재정적 동기와 일치

대응 및 권고

  • 모든 Trivy Action 버전 태그 사용 중단, 오직 commit SHA 57a97c7e7821a5776cebc9bb87c984fa69cba8f1 또는 태그 0.35.0 만 사용
  • 감염된 파이프라인은 완전한 비밀 유출로 간주, 모든 클라우드 자격 증명·SSH 키·API 토큰·DB 비밀번호·Docker 토큰 즉시 교체 필요
  • GitHub 조직 내 tpcp-docs 저장소 존재 여부 점검 및 3월 19일 19:00 UTC 이후 실행된 trivy-action 로그 검토 권장

침해 지표 (IOCs)

  • 네트워크 지표: scan[.]aquasecurtiy[.]org
  • 파일 해시: 18a24f83e807479438dcab7a1804c51a00dafc1d526698a66e0640d1e5dd671a (entrypoint.sh)
  • 감염된 GitHub Actions: aquasecurity/trivy-action@0.0.1 ~ @0.34.2 전 버전 포함 (총 75개 태그)

추가 업데이트 (3월 22일)

  • Docker Hub에서도 Trivy 이미지(0.69.4, 0.69.5, 0.69.6, latest) 가 동일한 Infostealer 페이로드로 오염된 사실 확인
  • latest 태그가 악성 이미지로 지정되어 노출 기간 동안 사용자에게 배포됨
  • 관련 상세 내용은 Socket의 별도 보고서 *“Trivy Docker Images Compromised”*에서 확인 가능
Hacker News 의견들
  • GitHub이 Actions의 불변 버전 관리(immutable versioning) 를 강제하지 않는 이유가 궁금함
    보안 가이드는 커밋 SHA로 고정(pin)하라고 하지만, 아예 고정하지 않으면 Action을 게시할 수 없게 만들면 이런 문제를 줄일 수 있을 것 같음

    • 이런 논의에는 항상 양면성이 있음
      보안팀 입장에서는 고정 버전이 안전하지만, 동시에 보안 업데이트 자동 반영이 안 되면 위험함
      결국 생산성을 해치지 않으면서 두 가지를 모두 만족시키는 해법이 필요함
      이걸 “Pinning의 역설”이라 부르고 싶음
    • GitHub Actions가 git 태그 모델을 따르고 있어서 지금 구조를 바꾸기 어렵다고 생각함
      그래도 언젠가는 바꾸는 작업을 시작해야 함
    • 만약 고정한 버전이 이미 오염된 상태였다면 어떨까?
      업데이트를 허용해야 오히려 보안이 강화될 수도 있음
      이건 정적 링크 vs 동적 링크 논쟁과 비슷한 문제임
      게다가 Trivy Action은 어차피 최신 버전을 가져오도록 되어 있었음
  • 이번 사건은 “공급망 보안(supply chain security)” 제품들이 실제로는 자신들이 보호하려는 스택만큼이나 취약할 수 있음을 보여주는 경고임
    특히 “모든 곳에서 실행되는(run us everywhere)” 보안 도구들은 한 번의 공격으로 수많은 사용자를 동시에 위험에 빠뜨릴 수 있는 새로운 공격 벡터를 제공함

  • 처음엔 Trivy가 자격 증명 회전(rotation) 을 제대로 하지 않은 줄 알았음
    하지만 그들은 “비원자적(non-atomic) 회전 과정에서 공격자가 새 토큰을 알아냈을 수도 있다”고 설명함
    GitHub은 발급 후 토큰을 다시 보여주지 않는데, 어떤 인증 방식을 썼는지에 따라 다를 수 있음

    • OpenClaw 제작자도 비슷한 경험을 했다고 함
      새 GitHub 조직을 만들자마자 이름이 탈취되어, GitHub 측에 원자적 생성 처리를 요청해야 했다고 함
  • 취약점을 스캔해야지, 취약점이 되면 안 된다”는 말이 절묘하게 들어맞는 사건임

    • 취약점을 들여다보면, 취약점도 너를 들여다본다”는 농담이 나올 정도임
  • 관련 사건으로 Trivy 공급망 일시적 침해 가 있었음

    • “일시적”이라는 표현은 너무 완곡한 표현 같음
  • 3월 22일 공격자는 탈취된 자격 증명으로 악성 Trivy v0.69.5, v0.69.6 DockerHub 이미지를 게시함
    (보안 공지 링크)
    3월 19일과 22일 두 번의 사건이 있었고, 공격자는 두 차례의 자격 증명 회전에도 불구하고 지속적으로 접근 권한을 유지한 것으로 보임

    • 실제로는 2월부터 이미 전체 리포지토리 침해가 있었고, 이번이 같은 공격자에 의한 세 번째 성공적인 공격임
  • “지난 2주가 최악이었음”
    Trivy가 털린 탓에 수많은 보안 보고서와 회의를 처리해야 하는 상황임

  • “보안 소프트웨어를 만든다고 해서 반드시 유능한 건 아니다”는 교훈임
    우리 보안팀도 매달 새로운 스캐너를 도입하려고 하지만, 그들이 요구하는 광범위한 접근 권한을 허용했다면 이미 여러 번 털렸을 것임

    • 예전에 Trivy의 GitHub Actions를 감사(audit) 해봤는데, setup-trivy Action이 메인 브랜치를 그대로 클론하고 쉘 스크립트를 실행하는 구조였음
      즉, 모든 CI 워크플로에서 임의 코드 실행이 가능했음
      Aqua는 이달 초 침해를 당했고, 두 번이나 격리 실패 후 Docker Hub 계정까지 뚫림
      이제는 외부 전문가의 도움이 필요하다고 생각함
    • “보안 도구”에 광범위한 접근 권한을 주는 건 위험 감소가 아니라 위험 확산임
      대부분은 시끄러운 리포트 생성기일 뿐이고, 공격자가 내부에 들어오면 아무런 방어도 못 함
      새로운 스캐너는 격리된 샌드박스에서 읽기 전용 데이터만 접근하게 하고, 충분히 검증될 때까지 프로덕션 권한을 주지 말아야 함
      그렇지 않으면 비밀키를 pastebin에 올리는 것과 다를 바 없음
    • 요즘 기업 보안은 모든 장비에 엔드포인트 보안 솔루션을 깔고, 모든 로그를 AI 대시보드로 보내는 식임
      “빠르게 움직이며 모든 걸 부수는” 보안 문화가 되어버림
    • 보안 부서에는 “시장에 쓸 만한 제품이 없으니 아무것도 쓰지 않겠다”는 선택지가 사실상 없음
      그래서 품질이 낮은 보안 소프트웨어라도 무조건 도입하는 문화가 생김
      Trivy 자체는 나쁘지 않다고 생각하고, 우리 회사도 사용 중임
      다만 우리는 Nix로 버전을 고정하고 직접 Actions 워크플로를 작성해서 이번 침해 영향을 받지 않았음
  • 공격자가 인증된 상태로 태그 강제 업데이트(force-update) 를 수행할 수 있었음
    GitHub의 오래된 설정인 “태그 덮어쓰기 금지”만 켜놨어도 막을 수 있었던 일임
    이런 사건이 반복될수록 소프트웨어 건축법(Software Building Code) 같은 표준이 필요하다는 생각이 강해짐
    2026년에 이런 이유가 몇 개나 더 생길지 궁금함