Trivy GitHub Actions 태그 대규모 침해: CI/CD 시크릿 탈취 공격
Trivy under attack again: Widespread GitHub Actions tag compromise secrets
TL;DR Highlight
취약점 스캐너 Trivy의 공식 GitHub Action 태그 75개가 악성 코드로 교체되어, 이를 참조하는 1만 개 이상의 CI/CD 파이프라인이 AWS/GCP/Azure 자격증명과 SSH 키를 탈취당할 위험에 노출됐다.
Who Should Read
GitHub Actions로 CI/CD 파이프라인을 운영 중이며 Trivy 같은 보안 스캐너를 사용하는 DevOps/백엔드 개발자. 특히 aquasecurity/trivy-action을 버전 태그로 참조하고 있는 팀이라면 즉시 확인해야 한다.
Core Mechanics
- 공격자가 aquasecurity/trivy-action 레포지토리의 76개 버전 태그 중 75개를 force-push로 악성 커밋으로 교체했다. @0.34.2, @0.33.0, @0.18.0 등 흔히 쓰는 태그가 모두 영향을 받았고, 현재 유일하게 안전한 태그는 @0.35.0뿐이다.
- 악성 페이로드는 GitHub Actions 러너 환경에서 실행되며, 러너 프로세스 메모리를 덤프해 시크릿을 추출하고, SSH 키를 수집하고, AWS/GCP/Azure 자격증명과 Kubernetes 서비스 어카운트 토큰을 외부로 유출한다.
- 이번 공격의 교묘한 점은 브랜치 push나 새 릴리즈 생성이 아닌 기존 태그의 force-push 방식을 사용했다는 것이다. 이 방법은 커밋 히스토리에 잘 남지 않고 알림도 트리거하지 않아 탐지가 어렵다.
- 공격의 근본 원인은 3월 초 OpenVSX VS Code 익스텐션 침해 사건 때 탈취된 CI/CD 자격증명이다. Trivy 팀이 시크릿을 교체했지만 교체 과정이 원자적(atomic)으로 이루어지지 않아, 공격자가 새로 발급된 토큰에도 접근권을 유지한 것으로 추정된다.
- GitHub에서 이 Action을 참조하는 워크플로우 파일이 10,000개 이상이며, 악성 코드는 정상적인 Trivy 스캔이 실행되기 전에 먼저 실행되어 사용자가 이상을 눈치채기 어렵게 설계됐다.
- Docker Hub에서도 추가 피해가 확인됐다. 3월 22일에 악성 Trivy 이미지 태그 0.69.4, 0.69.5, 0.69.6이 발견됐고, latest 태그도 노출 기간 동안 악성 이미지를 가리켰다.
- Socket의 AI 스캐너는 3월 20일 19:15 UTC부터 실시간으로 이 캠페인을 감지해 182개의 위협 피드 항목을 생성했고, 모두 Backdoor/Infostealer/Reconnaissance 악성코드로 정확히 분류했다.
- 이번 사건은 같은 달 3월에 발생한 Trivy 생태계의 두 번째 공급망 침해 사고다. 첫 번째 침해로 탈취된 자격증명이 완전히 무력화되지 않은 채로 두 번째 공격에 재활용됐다.
Evidence
- GitHub의 공식 보안 가이드라인은 Actions를 버전 태그가 아닌 전체 커밋 SHA로 고정(pin)하는 것을 권고하고 있다는 언급이 있었다. 이에 대해 'GitHub이 아예 Actions에 불변(immutable) 버전 정책을 강제하면 이 문제를 원천 차단할 수 있는데 왜 안 하냐'는 의견이 제기됐다.
- 자격증명 교체 과정의 구체적 실패 원인에 대해 커뮤니티 내 의문이 많았다. '3월 22일 두 번째 침해가 발생한 것을 보면 공격자가 두 번의 자격증명 교체를 뚫고 접근권을 유지한 것 같다'는 분석이 나왔고, GitHub의 다양한 토큰 종류(PAT, OAuth, GitHub App 토큰 등)에 따라 교체 절차가 다르기 때문에 어떤 유형의 자격증명이 문제였는지 불분명하다는 지적도 있었다.
- 보안 스캐너에 과도한 권한을 부여하는 관행에 대한 비판이 나왔다. 실제로 근무 중인 한 개발자는 '보안팀이 매달 새 스캐너를 도입하면서 전체 코드베이스나 클라우드 접근 권한을 요구하는데, 내가 요구사항의 10%라도 들어줬으면 이미 여러 번 털렸을 것'이라며 보안 도구 자체의 공급망 리스크를 경고했다.
- 이번 사고로 직접적인 피해를 입은 것으로 보이는 개발자가 '앞으로 몇 주 동안 수십 개의 보고서를 작성하고 수없이 많은 미팅을 해야 할 것 같다'며 실무 차원의 여파를 공유했다. Trivy가 두 번이나 침해당했다는 사실에 대한 좌절감도 표현했다.
- '항상 이런 도구들은 샌드박스 안에서 실행해서 피해 범위를 제한한다'는 실용적인 대응책을 공유한 댓글도 있었다. 또한 npm만 공급망 공격의 표적이 된다고 생각했던 사람들에게 경각심을 주는 사례라는 빈정섞인 지적도 있었다.
How to Apply
- aquasecurity/trivy-action을 버전 태그(@0.34.2 등)로 참조하고 있다면, 지금 당장 워크플로우 파일을 검토해야 한다. 태그 대신 신뢰할 수 있는 특정 커밋의 전체 SHA(예: uses: aquasecurity/trivy-action@커밋SHA)로 고정하면, 태그가 force-push로 교체되더라도 영향을 받지 않는다.
- 3월 20일 19:15 UTC 이후 aquasecurity/trivy-action을 사용한 워크플로우가 실행됐다면, 해당 파이프라인에서 사용된 모든 시크릿(AWS 키, GCP 서비스 어카운트, Azure 자격증명, SSH 키, Kubernetes 토큰 등)을 즉시 교체해야 한다. 단순 교체가 아니라 이전 자격증명으로 접근 가능한 리소스의 접근 로그도 감사(audit)해야 한다.
- CI/CD 파이프라인에서 보안 스캐너나 서드파티 Actions에 부여하는 권한을 최소화해야 한다. GitHub Actions의 GITHUB_TOKEN 권한을 워크플로우 레벨에서 read-only로 제한하고, 클라우드 자격증명은 OIDC(임시 토큰 방식)를 사용하면 탈취된 자격증명의 유효 시간을 단축할 수 있다.
- Socket, Dependabot, Renovate 같은 도구를 활용해 GitHub Actions 의존성을 모니터링하면, 이번처럼 태그가 악성 커밋으로 교체되는 것을 실시간으로 감지할 수 있다. Socket의 경우 이번 공격을 실시간으로 탐지해 Backdoor/Infostealer로 분류했다.
Code Example
snippet
# 취약한 방식: 버전 태그 참조 (force-push로 교체 가능)
- name: Run Trivy vulnerability scanner
uses: aquasecurity/trivy-action@0.34.2 # ❌ 위험
# 안전한 방식: 전체 커밋 SHA로 고정 (불변)
- name: Run Trivy vulnerability scanner
uses: aquasecurity/trivy-action@a20de5420d57c4102547773ee84a9575c8d547ea # ✅ 안전
# GitHub Actions 권한 최소화 설정 예시
permissions:
contents: read # 최소 권한만 부여
security-events: write # Trivy SARIF 업로드에 필요한 경우만
# OIDC를 사용한 AWS 임시 자격증명 (탈취 시 피해 최소화)
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@커밋SHA
with:
role-to-assume: arn:aws:iam::ACCOUNT:role/ROLE
aws-region: ap-northeast-2
# access-key-id/secret-access-key 하드코딩 금지Terminology
force-pushGit에서 원격 저장소의 히스토리를 강제로 덮어쓰는 것. 일반 push는 새 커밋을 추가하지만, force-push는 기존 히스토리를 아예 교체하기 때문에 태그가 가리키던 커밋을 몰래 바꿀 수 있다.
공급망 공격 (Supply Chain Attack)내가 만든 코드가 아니라, 내가 믿고 가져다 쓰는 도구/라이브러리/서비스를 공격하는 방식. 유통망(공급망)을 오염시켜 최종 사용자를 노린다.
Infostealer감염된 환경에서 비밀번호, API 키, 쿠키, SSH 키 같은 민감한 정보를 몰래 수집해 공격자 서버로 전송하는 악성코드 유형.
원자적(Atomic) 교체여러 단계의 작업이 '전부 성공하거나 전부 실패하거나' 둘 중 하나인 것. 자격증명 교체 시 원자적이지 않으면 일부만 교체된 상태에서 공격자가 새 자격증명을 가로챌 수 있는 틈이 생긴다.
OIDC (OpenID Connect)클라우드 서비스(AWS, GCP 등)에 접근할 때 장기 유효한 API 키 대신 일시적인 토큰을 발급받는 방식. 토큰이 탈취되더라도 유효 시간이 짧아 피해를 줄일 수 있다.
blast radius보안 사고나 시스템 장애가 발생했을 때 영향을 받는 범위. 마치 폭발 반경처럼, 이 범위를 최소화하는 것이 보안 설계의 핵심 목표 중 하나다.