마이크로소프트의 GitHub 저장소 73개가 비공개 처리되는 데 걸린 시간은 105초였다. 누군가 이슈를 올리기도 전에, 자기 복제형 "Miasma" 웜은 이미 GitHub가 조치에 나서게 만들었고, 오염된 패키지를 단 하나도 설치한 적 없는 개발자들의 CI/CD 파이프라인까지 망가뜨렸다.
GitHub는 어떻게 2분도 안 돼 Microsoft 저장소 73개를 비활성화했나
2026년 6월 5일, GitHub의 자동 악용 탐지 시스템은 Miasma 공급망 웜에 감염된 Microsoft 소유 저장소 73개를 비활성화했다. 조치는 UTC 16:00:50부터 16:02:35까지 두 차례에 걸쳐 약 105초 만에 완료됐다 . 이는 수동 보안 검토가 아니라 기계 속도의 집행이었다. 시스템은 어떤 사람 팀도 분류할 수 있는 속도보다 빠르게 저장소를 오프라인으로 내렸고, 그래서 후속 장애가 그토록 많은 개발자에게 예고 없이 닥친 것이다.
요약 답변: 2026년 6월 5일, Miasma 웜이 Microsoft 소유 저장소들을 감염시킨 뒤 GitHub의 자동 악용 탐지 시스템은 약 105초 만에 네 개 조직에 걸친 저장소 73개를 비활성화했다. 가장 큰 피해를 본 조직은 Azure로, 공식 Azure/functions-action 배포 Action을 포함해 저장소 49개가 영향을 받았다 .
피해는 네 개 조직에 걸쳐 발생했다. Azure가 비활성화된 저장소 49개로 대부분을 차지했고, 그다음은 Azure-Samples(13개), microsoft(10개), MicrosoftDocs(1개) 순이었다 . Azure-Samples 묶음은 특히 누구에게 영향을 주는지가 눈에 띈다. rag-postgres-openai-python, llm-fine-tuning 같은 저장소를 포함해 AI 데모 콘텐츠 쪽으로 크게 치우쳐 있었기 때문이다. 이는 AI 개발자가 검색 증강이나 파인튜닝 스택을 빠르게 시작하려고 그대로 클론할 만한 예제 프로젝트들이다 .
| 조직 | 비활성화된 저장소 | 주요 내용 |
|---|---|---|
| Azure | 49 | Azure/functions-action 및 functions-container-action(공식 배포 Actions), Durable Task 관련 저장소들 |
| Azure-Samples | 13 | AI 데모 프로젝트: rag-postgres-openai-python, llm-fine-tuning |
| microsoft | 10 | Microsoft 조직 도구와 샘플 |
| MicrosoftDocs | 1 | 문서 저장소 |
| 합계 | 73 | 네 개 조직에 걸쳐 약 105초 만에 비활성화 |
Microsoft가 직접 제시한 설명은 연구자들이 집계한 수치보다 좁다. 대변인 Ben Hope는 TechCrunch에 회사가 잠재적 악성 콘텐츠를 조사하는 동안 "일부 저장소를 일시적으로 제거했다"고 밝혔고, 검토 후 일부는 복구됐지만 다른 저장소는 계속 오프라인 상태로 남을 수 있으며, 콘텐츠를 가져갔을 가능성이 있는 "소수" 고객에게 알렸다고 말했다 . "일부 저장소", "소수"라는 표현은 StepSecurity와 devops.com이 문서화한 저장소 73개, 네 개 조직이라는 정확한 집계보다 유난히 모호하다. 또한 조사 당시 Microsoft는 비활성화된 모든 저장소가 Miasma에 감염됐는지, 아니면 일부가 GitHub의 자동 집행 과정에서 함께 걸러졌는지를 확인하는 근본 원인 보고서를 공개하지 않았다 .
일부 독자가 접한 "다른 저장소 72개"라는 표현은 functions-action에 72개를 더한 것이다. 총 73개로 같은 수치지만, 운영상 가장 아픈 피해 사례를 기준으로 잡은 표현이다. 아래 섹션에서는 왜 이 단일 Action이 비공개 처리되자 전 세계 배포가 깨졌는지 추적한다.
패키지 매니저 없이: Miasma는 프로젝트 파일에 어떻게 도화선을 숨겼나

Miasma가 기존 공급망 웜과 갈라서는 지점은 트리거다. 패키지 매니저 설치 훅을 완전히 버리고, 대신 AI 코딩 에이전트와 에디터가 프로젝트를 열 때 읽는 자동 실행 설정 파일을 무기화했다. 이전에 침해된 기여자 계정을 통해 Azure의 durabletask 저장소에 악성 커밋 하나가 푸시됐고, 그 안에는 모두 같은 드로퍼인 .github/setup.js를 가리키는 다섯 개의 병렬 시작 트리거가 심어져 있었다 . 페이로드는 개발자가 복제한 폴더를 여는 순간 실행되며, 수동 명령을 하나도 입력하기 전부터 작동한다.
그중 두 트리거는 세션 시작 훅을 악용한다. Claude Code는 커밋된 .claude/settings.json에서 SessionStart 훅을 읽고, Gemini CLI는 .gemini/settings.json에서 같은 역할의 설정을 읽는다. 둘 다 프로젝트가 열리면 참조된 명령을 자동으로 실행한다 . 이런 동작 자체는 의도된 기능이다. 훅은 에이전트가 진입 시 환경을 준비하게 해준다. 하지만 설정이 버전 관리 안에 있기 때문에, 감염된 저장소를 복제한 사람은 공격자의 훅을 자기 설정처럼 그대로 물려받게 된다.
나머지 트리거는 에디터와 툴체인 표면을 겨냥한다. .cursor/rules/setup.mdc의 Cursor 프로젝트 규칙은 alwaysApply: true를 설정하고, .vscode/tasks.json의 VS Code 작업은 runOn: "folderOpen"을 사용하며, SafeDep는 다섯 번째 경로로 표준 CI 호출에서 실행되는 npm 테스트 스크립트 탈취를 문서화했다 . 이렇게 겹겹이 심어둔 것이 핵심이다. 피해자가 저장소를 살펴보려고 어떤 도구를 쓰든, 그 도구가 점화원이 된다.
| 트리거 | 설정 경로 | 실행 조건 | 영향받는 도구 |
|---|---|---|---|
| SessionStart 훅 | .claude/settings.json | 프로젝트를 열 때 자동 실행 | Claude Code |
| SessionStart 훅 | .gemini/settings.json | 프로젝트를 열 때 자동 실행 | Gemini CLI |
| 프로젝트 규칙 | .cursor/rules/setup.mdc | alwaysApply: true | Cursor |
| 에디터 작업 | .vscode/tasks.json | runOn: "folderOpen" | VS Code |
| 테스트 스크립트 탈취 | package.json (npm) | npm test / CI에서 실행 | npm / CI 러너 |
이 모든 경로는 .github/setup.js로 해석되므로, 다섯 진입점은 하나의 폭발 경로를 공유한다. 여러 공격 파동에 걸친 캠페인의 계보를 추적한 SafeDep는 이를 "the same worm with a different mouth"라고 표현했다. 설치 훅 전달 방식을 설정 주입으로 바꿨지만 핵심은 그대로 유지한 페이로드에 잘 들어맞는 설명이다 .
실무적으로는 위협 모델이 바뀐다. 개발자가 npm install이나 pip install을 전혀 실행하지 않아도, 에이전트가 활성화된 에디터에서 감염된 클론을 여는 즉시 노출된다 . 이제 에이전트와 에디터 설정 파일인 .claude/, .gemini/, .cursor/, .vscode/tasks.json은 실행 가능한 코드처럼 읽어야 하며, 폴더를 열기 전에 먼저 검토해야 한다.
페이로드 내부: 4.6MB Bun 드로퍼와 90개 이상의 클라우드 대상
이 트리거들이 가리키는 파일은 작은 스크립트가 아니다. StepSecurity는 커밋된 .github/setup.js 드로퍼의 크기를 4,643,745바이트, 약 4.6MB의 난독화된 JavaScript로 측정했다. SafeDep의 분석에 따르면 이는 단계형 로더다. 드로퍼는 런타임으로 Bun v1.3.13을 고정한 뒤, 첫 실행 시 부트스트랩 설치 프로그램과 약 667KB 크기의 자격 증명 수집기를 복호화한다 . 4.6MB의 대부분은 스테이징과 난독화에 쓰이며, 실제로 압축 해제되어 동작하는 수집기는 그보다 훨씬 작다.
실행이 시작되면 수집기는 호스트를 훑어 비밀값을 찾는다. SafeDep은 이 수집기가 AWS, Azure, GCP, HashiCorp Vault, Kubernetes, npm, GitHub 토큰을 스캔한다고 기록했고, StepSecurity는 90개 이상의 개발자 도구를 겨냥한 자격 증명 수집기를 집계했다. 수집된 자료는 프라이빗 명령제어 서버로 유출되는 대신, 공격자가 제어하는 공개 GitHub 저장소에 기록되는 방식으로 데드 드롭된다 . GitHub를 투하 지점으로 쓰면 트래픽이 일반적인 개발자 활동과 구분되기 어렵다.
단일 오염 커밋이 조직 전체 사건으로 번진 핵심은 자기 전파였다. 웜은 토큰을 수집한 뒤 이를 재사용해, 침해된 계정이 쓰기 권한을 가진 모든 저장소에 자기 복사본을 커밋한다 . 이 메커니즘은 감염이 저장소 하나씩 순차적으로 번진 것이 아니라, 같은 시간대에 Durable Task 계열 저장소와 Functions 액션까지 도달한 이유를 설명한다. 수집된 자격 증명 묶음마다 다음 파동의 출발점이 된 것이다.
Cloudsmith는 시그니처 기반 방어를 취약하게 만드는 세부 사항을 짚는다. Miasma는 감염마다 고유하게 암호화된 페이로드를 생성하며, 파동 사이에서 AES 키와 암호 시프트를 바꾼다 . 복호화 하네스와 Bun 고정은 그대로지만 디스크에 남는 바이트는 매번 달라지므로, 해시 기반 침해 지표는 새 변종이 배포되는 순간 효력을 잃는다. SafeDep도 추적한 암호 회전에서 같은 패턴을 관찰했다.
"입만 다른 같은 웜이다. AES-128-GCM 복호화 하네스와 Bun 고정은 동일하지만, 회전된 Caesar 암호와 AES 키는 복사-붙여넣기가 아니라 파동별 재컴파일을 가리킨다." — SafeDep 연구팀 (source: SafeDep 분석).
방어자에게 실무적으로 중요한 결론은 이렇다. 드로퍼의 알려진 SHA-256과 대조하면 어제의 파동은 잡을 수 있지만 오늘의 파동은 놓친다. 탐지는 정적 지문이 아니라 동작과 구조를 기준으로 해야 한다. 즉, 수 MB 규모의 .github/setup.js, 고정된 Bun 런타임, 낯선 공개 저장소로의 외부 쓰기를 봐야 한다.
TeamPCP의 흔적: 일치하는 Bun 고정 버전과 유출 도메인

이런 구조적 특징 덕분에 연구자들은 Miasma의 배후도 추적할 수 있다. SafeDep는 이 웜을 위협 그룹 TeamPCP와 연결하며, 완전히 새로운 코드베이스가 아니라 앞선 Mini Shai-Hulud 캠페인의 진화형으로 본다. 이미 검증된 엔진을 같은 운영자가 다시 쓴 셈이다. 근거는 여러 공격 차수에서 드러나는 내부 일관성이다. 동일한 AES-128-GCM 복호화 하네스와 v1.3.13으로 고정된 Bun 런타임 , 그리고 서로 별개로 보이는 침입을 한 행위자에게 묶어 주는 공통 유출 인프라가 함께 확인됐다.
"입만 달라진 같은 웜," — SafeDep 연구팀, Miasma와 Mini Shai-Hulud의 관계를 설명하며 (source: SafeDep teardown).
탐지 관점에서는 이 "달라진 입"이 중요하다. SafeDep는 복호화 하네스와 Bun 고정 버전은 그대로 유지됐지만, 겉으로 보이는 층은 공격 차수마다 바뀌었다고 밝혔다. Caesar 암호는 ROT-9에서 ROT-4로 바뀌었고 AES 키도 교체됐다. 이는 단순 복사·붙여넣기 재사용이 아니라 차수별로 적극적인 재컴파일이 이뤄졌음을 시사한다 . 반대로 인프라는 오래 남는 실마리다. 공통 유출 도메인인 check.git-service[.]com과 t.m-kosche[.]com이 여러 감염에서 반복적으로 등장하며, 이 캠페인을 TeamPCP에 고정해 준다 . 방어자 입장에서는 일반적인 우선순위가 뒤집힌다. 파일 해시보다 네트워크 지표가 더 오래 살아남는다.
이 그룹의 플레이북은 Microsoft 공격 이전부터 존재했다. Cloudsmith에 따르면 Miasma는 먼저 @redhat-cloud-services npm 네임스페이스에서 모습을 드러냈고, 손상된 Red Hat 직원 GitHub 계정을 통해 유입됐다. 공격자는 GitHub OIDC 토큰을 요청하는 최소한의 워크플로를 삽입한 뒤, 악성 npm 패키지 버전 32개를 게시했다. 각각에는 유효한 SLSA 출처 증명이 포함돼 있었다 . 이 마지막 대목이 기법의 핵심이다. 릴리스는 합법적이고 신뢰받는 계정으로 서명됐기 때문에 출처 증명 자체는 진짜였다. SLSA 증명을 긍정적인 신뢰 신호로 취급하는 스캐너들은 해당 패키지를 그대로 통과시켰다.
이는 출처 증명 악용을 의도적인 전략으로 삼은 사례이며, TeamPCP의 알려진 이력과도 맞아떨어진다. 이 그룹이 공격한 것으로 알려진 이전 대상은 다음과 같다.
- TanStack — React와 TypeScript 앱에서 널리 쓰이는 오픈소스 데이터/상태 라이브러리 .
- Mistral AI — AI 도구 공급망에서 가치가 높은 신원인 LLM 벤더 .
- @antv 생태계 — 해당 npm 스코프 아래에서 유지관리되는 시각화 라이브러리들 .
- LiteLLM — 여러 에이전트 스택에서 쓰이는 인기 LLM 게이트웨이 프록시 .
- Checkmarx — 특히 애플리케이션 보안 벤더라는 점에서 눈에 띈다 .
공통점은 하나의 취약점이 아니라 패턴이다. 합법적인 유지관리자 자격 증명을 탈취하고, 올바르게 서명된 릴리스를 만든 다음, 신뢰 체계가 배포를 대신하게 한다. 재컴파일된 페이로드와 교체된 키는 정적 시그니처를 금세 낡게 만들고, OIDC와 출처 증명을 이용한 경로는 아티팩트를 평범한 배포처럼 보이게 만든다. 재사용된 엔진 위에 새 바이너리를 얹고, 진짜 증명을 타고 퍼지는 이 조합 때문에 TeamPCP는 대부분의 팀이 이미 쓰는 도구만으로는 지문을 잡아내기 더 어렵다.
패키지 오염에서 저장소 장악까지: 17일 만의 확산
Miasma가 Microsoft의 Durable Task 프로젝트를 파고든 것은 한 번의 사건이 아니라 약 17일 간격으로 반복된 공격이었고, 두 차례의 공격은 이 캠페인이 패키지 대체에서 직접적인 저장소 장악으로 확대됐음을 보여준다. 첫 타격은 2026년 5월 19일에 발생했다. 침해된 Azure/durabletask 기여자 계정이 탈취된 배포 토큰을 사용해 약 35분 동안 악성 PyPI 버전 세 개, 즉 1.4.1, 1.4.2, 1.4.3을 업로드했다 . 문제의 릴리스들은 몇 시간 안에 yank 처리됐다 .
현재 PyPI의 durabletask 페이지도 그 정리 작업을 반영한다. Microsoft가 검증된 유지관리자로 표시된 상태에서 1.4.0(2026년 4월 8일), 1.5.0(2026년 6월 5일), 1.6.0(2026년 6월 18일)을 나열하고 있으며, 1.4.1부터 1.4.3까지는 더 이상 눈에 띄게 표시되지 않는다. 이는 yank와 부합하지만, 보이지 않는다는 사실만으로 증명되는 것은 아니다 . durabletask를 고정해 쓰던 개발자 입장에서 실무적 해석은 간단하다. 5월 19일부터 yank 전까지 1.4.1~1.4.3을 받아온 resolve는 노출된 것으로 취급해야 한다.
6월 5일의 사건은 새로운 침투라기보다 재침해에 가까워 보인다. 연구자들은 공격 범위가 PyPI 패키지 대체에서 직접적인 저장소 침해로 넓어졌다고 설명했고, GitHub의 일괄 조치로 Functions 저장소들과 함께 Durable Task 계열 전체가 비활성화됐다. durabletask-dotnet, -go, -java, -js, -mssql, -netherite가 모두 동시에 내려갔다 . 형제 저장소가 한꺼번에 비활성화된 이 패턴은 알려진 악성 파일만 정밀하게 제거했다기보다, 하나의 침해된 계정이 쓰기 권한을 가진 전체 저장소 집합에 자동 집행이 적용됐을 때 예상되는 모습이다.
귀속 관계도 두 사건을 하나로 묶는다. OpenSourceMalware는 Wiz, Endor Labs, StepSecurity가 5월 사건을 탈취된 GitHub Actions 시크릿 및 TeamPCP 위협 그룹과 연결했다고 전했다 . 같은 계정 또는 관련된 탈취 계정으로 이어진 6월 재발은 불편한 대목이다. 5월 이후 초기 자격 증명 교체가 불완전했거나 우회됐음을 시사하기 때문이다. 해당 기여자 신원에 연결된 모든 토큰이 폐기되고 재발급됐다면, 같은 접근 권한을 통한 두 번째 푸시는 가능하지 않았어야 한다.
유지관리자가 얻어야 할 교훈은 오염된 아티팩트를 yank하는 것만으로는 증상을 닫을 뿐 침해 자체를 닫지 못한다는 점이다. 침해된 신원, 그 배포 토큰, 그리고 수집됐을 수 있는 CI/CD 시크릿을 모두 교체하고 접근 경로를 감사하기 전까지 같은 문은 계속 열려 있다. 거의 동일한 공격이 17일 간격으로 반복됐다는 사실이 바로 그것을 보여준다.
Azure/functions-action이 내려갔을 때: 전 세계 CI/CD에 미친 영향

6월 5일 비활성화 조치에서 운영상 가장 큰 피해를 준 것은 페이로드가 아니었다. 그것은 부재였다. Azure/functions-action은 패키징된 코드를 Azure Function Apps에 배포하기 위한 Microsoft의 공식 GitHub Action이다. 전 세계 엔터프라이즈와 개인 개발자의 CI/CD 파이프라인에서 널리 참조된다. GitHub의 악용 탐지가 2026년 6월 5일 이 저장소를 다른 Microsoft 저장소 72개와 함께 비활성화하자, 변경 가능한 @v1 태그를 가리키던 모든 워크플로가 갑자기 resolve에 실패했다. 악성 npm 패키지를 설치한 적도, 침해된 clone을 연 적도 없는 개발자들의 배포가 전 세계적으로 깨진 것이다 .
이 지점은 곱씹어볼 만하다. harvester는 그것을 실행한 머신에서만 자격 증명을 긁어갔다. 그러나 functions-action 장애는 훨씬 더 넓은 반경을 때렸다. 파이프라인에 uses: Azure/functions-action@v1이 들어 있던 누구든, 자신의 보안 위생과 무관하게 다음 배포에서 하드 실패를 맞았다. 형제 저장소인 Azure/functions-container-action도 같은 물결 속에서 내려가며 컨테이너 기반 함수 배포까지 함께 멈췄다 . 지속적으로 배포하는 팀에게 활성 보안 사고 중 릴리스 경로가 깨지는 것은 그 자체로 2차 장애다. 예측할 수도, 직접 패치할 수도 없는 장애였다.
이 글을 쓰는 시점에는 저장소에 다시 접근할 수 있다 . 다만 Microsoft는 모든 것이 해결됐다고 과장하지 않도록 조심했다. 대변인 Ben Hope는 대응을 의도적으로 되돌릴 수 있는 조치로 설명했다.
"잠재적인 악성 콘텐츠를 조사하는 동안 일부 저장소를 일시적으로 제거했습니다. 일부는 검토 후 복원됐지만, 다른 저장소는 오프라인 상태로 남아 있을 수 있습니다." — Ben Hope, Microsoft 대변인 (source: via TechCrunch reporting)
웜과 비활성화 메커니즘을 걷어내고 보면, functions-action 장애는 Miasma 이전부터 존재하던 구조적 결함을 드러낸다. 변경 가능한 태그 참조는 하위 개발자가 전혀 통제할 수 없는 단일 장애 지점이다. @v1이나 @main 같은 태그는 움직이는 포인터다. 업스트림 저장소를 제어하는 사람은 그것을 다시 가리키게 할 수 있고, 그 저장소를 비활성화하는 사람은 그것을 지워버릴 수 있다. Action이 사라지자, 그 태그가 계속 같은 의미를 유지할 것이라고 믿던 모든 파이프라인도 함께 사라졌다. 완화책은 화려하지 않지만 이미 잘 알려져 있다. Actions를 떠다니는 태그가 아니라 불변 commit SHA에 고정해야 한다. 그래야 업스트림 비활성화나 악의적인 retag가 CI에서 실행되는 내용을 조용히 바꿔 쓰지 못한다 .
미아즈마 이후 해야 할 일: 다시 클론하고, 키를 교체하고, SHA로 고정하기
2026년 6월 5일 전후로 영향을 받은 저장소를 클론했다면, 터미널에서 먼저 점검하기 전까지 Claude Code, Gemini CLI, Cursor, VS Code에서 그 폴더를 열지 마세요. 미아즈마가 악용하는 세션 시작 훅과 폴더 열기 작업은 프로젝트를 여는 순간 실행되므로, 안전한 순서는 먼저 grep으로 확인하고 나중에 여는 것입니다. 어떤 클론도 신뢰하기 전에 한 줄짜리 드로퍼 확인을 실행하고, 웜이 심어 둔 에이전트 설정 경로를 스캔하세요.
test -f .github/setup.js && echo DROPPER PRESENT
ls -la .claude/ .gemini/ .cursor/rules/ .vscode/tasks.json 2>/dev/null.github/setup.js가 있거나, 직접 작성하지 않은 저장소에서 .claude/, .gemini/, .cursor/rules/, .vscode/tasks.json가 발견되면 감염 가능성이 있는 것으로 보고 작업 사본을 삭제한 뒤, 제자리에서 패치하지 말고 주입 이전 커밋에서 다시 클론하세요. 연구자들이 바로 이 순서, 즉 grep으로 확인하고 삭제한 다음 주입 전 커밋에서 다시 클론하라고 권고하는 이유는 트리거가 설치된 패키지가 아니라 커밋된 설정 안에 있기 때문입니다 .
그다음에는 6월 초 이후 탈취됐을 가능성이 있는 모든 것을 교체하세요. 이 수집기는 AWS, Azure, Google Cloud, Kubernetes와 90개가 넘는 추가 개발자 도구의 자격 증명을 모으므로, 보수적으로 잡은 초기화 대상에는 다음이 포함됩니다.
- GitHub 개인 액세스 토큰과 SSH 키
- CI/CD 파이프라인 시크릿과 서명 키
- Azure 및 GCP 서비스 주체
- npm 및 PyPI 게시 토큰
미아즈마는 훔친 시크릿을 공격자가 제어하는 공개 GitHub 저장소에 데드 드롭으로 남긴 뒤, 수집한 토큰으로 자가 전파하는 방식으로 유출합니다 . 이것이 동시에 약점이기도 합니다. 증거를 공개하는 웜은 흔적을 남깁니다. 계정과 조직에 직접 만들지 않은 예기치 않은 공개 저장소나 JSON 시크릿 덤프가 있는지 감사하고, 탈취된 자격 증명으로 비정상 커밋이 생성됐는지도 확인하세요.
마지막으로, 이번 캠페인이 악용한 구조적 빈틈을 닫으세요. 모든 GitHub Action을 @v1 같은 변경 가능한 태그가 아니라 전체 커밋 SHA에 고정해, 업스트림 삭제나 악의적인 리태그가 CI에서 실행되는 내용을 조용히 바꾸지 못하게 하세요. 오래 유지되는 게시 토큰 대신 OIDC 기반 PyPI Trusted Publishing을 도입하세요. 이는 도난 토큰으로 벌어진 durabletask PyPI 침해가 필요성을 보여 준 것과 같은 단기 자격 증명 모델입니다 . 악성 커밋이 탈취된 기여자 계정을 통해 Azure/durabletask에 도달했으므로, 게시 권한을 가진 모든 저장소에 필수 PR 리뷰가 포함된 브랜치 보호를 적용하세요 .
핵심은 분명합니다. 이제 AI 에이전트와 에디터 설정 파일도 실행 가능한 공격 표면입니다. 어떤 클론이든 열기 전에 .claude/, .gemini/, .cursor/, .vscode/tasks.json를 검토하고, 6월 초 이후의 자격 증명을 교체하며, 의존성을 변경 불가능한 참조에 고정하세요. 새롭거나 특별한 강화책이 아닙니다. 이 웜은 바로 이런 기본적인 공급망 위생이 빠진 곳을 찾도록 만들어졌습니다 .
자주 묻는 질문
npm이나 PyPI에서 아무것도 설치하지 않았다면, 그래도 노출된 건가요?
그렇습니다. Miasma의 주된 확산 경로는 패키지 설치가 아닙니다. 프로젝트 파일 안에 커밋된 AI 코딩 에이전트의 자동 실행 설정입니다. 감염된 저장소를 클론한 뒤 VS Code, Cursor, Claude Code, Gemini CLI에서 열었던 사람은 명시적으로 npm install이나 pip install을 실행하지 않았더라도 .github/setup.js 드로퍼가 자동 실행됐을 수 있습니다. 그래서 2026년 6월 5일 Microsoft 저장소 73개가 내려가면서 레지스트리를 건드린 적 없는 개발자들의 CI/CD까지 깨졌습니다. 여기서는 “아무것도 설치하지 않았다”는 말이 보호 수단이 되지 않습니다.
Miasma는 어떤 AI 코딩 에이전트 파일을 노리나요?
Miasma는 모두 같은 .github/setup.js 드로퍼를 가리키는 병렬 트리거 5개를 심습니다 :
.claude/settings.json— Claude Code SessionStart 훅.gemini/settings.json— Gemini CLI SessionStart 훅.cursor/rules/setup.mdc—alwaysApply: true가 설정된 Cursor 프로젝트 규칙.vscode/tasks.json—runOn: "folderOpen"이 설정된 VS Code 작업package.json— npm 테스트 스크립트 하이재킹(SafeDep이 지목한 다섯 번째 트리거)
처음 네 가지 중 하나만 있어도 프로젝트 폴더를 여는 순간 실행됩니다. 명령도, 설치도, 프롬프트도 필요 없습니다.
클론한 저장소에 드로퍼가 있는지 어떻게 확인하나요?
저장소 루트에서 어떤 에이전트나 에디터로 폴더를 열기 전에 test -f .github/setup.js && echo DROPPER PRESENT를 실행하세요 . 프로젝트 루트에 예상치 못한 .claude/, .gemini/, .cursor/rules/ 디렉터리가 있는지도 확인하세요. 2026년 6월 5일 무렵 클론한 저장소에서 이런 항목을 발견했다면 해당 클론을 삭제하고 악성 푸시 이전 커밋에서 다시 클론한 다음, 6월 초 이후 노출됐을 수 있는 모든 자격 증명을 교체하세요.
이제 Azure/functions-action을 참조해도 안전한가요?
확인 시점 기준으로 저장소는 복구되어 다시 접근할 수 있습니다 . 오래가는 해결책은 구조적인 조치입니다. 변경 가능한 @v1 태그 대신 특정 커밋 SHA에 액션을 고정하세요. 장애 당시 @v1을 참조하던 모든 워크플로가 해석되지 않아 하위 Azure Function App 배포가 깨졌습니다 . SHA에 고정하면 향후 저장소가 내려가거나 내용이 바뀌더라도 파이프라인이 조용히 변경되거나 깨지는 일을 막을 수 있습니다.
Miasma는 전체 캠페인에서 실제로 몇 개 저장소를 공격했나요?
확인된 Microsoft 관련 수치는 GitHub 조직 4곳에 걸친 저장소 73개입니다. 캠페인 전체 추정치는 집계 기간에 따라 크게 갈립니다. 저장소 113개 이상(StepSecurity 기준에 가까운 수치), 저장소 123개 이상과 월 다운로드 408,000회 이상에 달하는 npm 패키지 50개 이상(SafeDep), 그리고 Wordfence 브이로그에서 언급된 저장소 813개 이상(동영상: Wordfence Security News Clip)까지 다양합니다. 넓은 캠페인 규모는 활발히 확산 중인 웜을 서로 다른 시점에서 잡아낸, 계속 움직이는 미확정 범위로 보고, Microsoft 저장소 73개라는 수치를 확실한 기준점으로 삼는 것이 좋습니다.