본문으로 건너뛰기

© 2026 Molayo

Dev.to헤드라인2026. 05. 20. 23:03

VS Code 확장 프로그램을 통한 GitHub 침해 사고 발생. 다음 타겟은 MCP 서버인가.

요약

GitHub은 악성 VS Code 확장 프로그램을 통해 내부 저장소가 유출된 침해 사고를 탐지하고 격리 조치를 취했습니다. 이번 사건은 개발자 도구와 공급망을 겨냥한 의도적인 공격 캠페인의 일환으로, 로컬 에이전트나 확장 프로그램이 가진 높은 권한이 보안 위협의 핵심 벡터로 작용하고 있음을 보여줍니다.

핵심 포인트

  • GitHub 직원 기기가 독이 든 VS Code 확장 프로그램을 통해 침해되어 약 3,800개의 내부 저장소가 유출되었습니다.
  • 공격자들은 Trivy, Bitwarden CLI, PyTorch Lightning 등 개발자에게 신뢰받는 도구들을 타겟으로 삼는 공급망 공격을 지속하고 있습니다.
  • 로컬 모델이나 에이전트라 할지라도 파일 시스템 및 셸 액세스 권한을 가진 경우 강력한 보안 위협이 될 수 있습니다.
  • npm 패키지 탈취를 통해 GitHub 토큰, AWS 키, SSH 자격 증명 등을 노리는 'Mini Shai-Hulud' 멀웨어 제품군이 발견되었습니다.

어제, GitHub는 독이 든(poisoned) VS Code 확장 프로그램과 관련된 직원 기기의 침해 사고를 탐지하고 격리했다고 밝혔습니다. 회사의 현재 평가에 따르면, 해당 활동은 GitHub 내부 저장소(internal repositories)의 유출에만 국한되었으며, 약 3,800개의 저장소가 유출되었다는 공격자의 주장은 현재까지의 조사 결과와 방향성이 일치합니다. GitHub는 악성 확장 프로그램을 제거하고, 엔드포인트(endpoint)를 격리했으며, 중요한 자격 증명(credentials)의 순환(rotation)을 우선적으로 처리했습니다.

며칠 전, 저는 반대 방향에서 유사한 작업을 수행하고 있었습니다. 저는 제 노트북에서 OpenAI의 Codex Chronicle을 제거하고, 제가 소유한 Mac mini에서 실행되는 로컬 Gemma 4 인스턴스로 교체했습니다. 원래 그것은 비용 결정이었습니다. 하지만 이번 침해 사고는 해당 아키텍처의 보안적 함의를 무시할 수 없게 만들었습니다. 신뢰할 수 있는 제3자 바이너리(binary). 로컬에 설치됨. 당신의 화면, 파일, 토큰에 대한 전체 읽기 권한. 사용자가 직접 설정하여 모든 방화벽에서 허용되는 아웃바운드 네트워크 경로(outbound network path). 공급망(supply chain)의 어느 시점에서든 바이너리를 침해한다면, 플랫폼을 침해할 필요가 없습니다. 플랫폼은 지시받은 대로 수행하고 있을 뿐입니다. 당신이 직접 들어온 것입니다.

이것이 GitHub 침해 사고입니다. 또한 만약 Codex Chronicle과 같은 도구가 빌드 파이프라인(build pipeline)이나 배포 계층(distribution layer)에서 침해된다면 바로 이런 일이 벌어질 것입니다. 이 아키텍처들은 형제 관계입니다. 로컬 모델이 자동으로 안전한 것은 아닙니다. 파일 시스템과 셸(shell) 액세스 권한을 가진 침해된 로컬 에이전트(local agent)는 여전히 권한이 부여된 실행 환경(privileged execution environment)입니다. 차이점은 로컬 아키텍처가 강제적인 외부 신뢰 경계(external trust boundary)를 줄이고 검사를 가능하게 한다는 점입니다.

경고 신호는 이미 도처에 있었습니다. TeamPCP는 단발적인 사건이 아닙니다. 이 그룹은 공개 보고서에서 UNC6780으로 추적되며, 이번 주 이전의 2026년 타겟 목록에는 Trivy, Checkmarx, LiteLLM, Bitwarden CLI, PyTorch Lightning, 그리고 가장 최근에는 일주일 전 Grafana 침해와 연결된 TanStack 및 durabletask npm과 PyPI 침해 사례가 포함되어 있었습니다. 그 목록을 보십시오. Trivy.

Checkmarx. LiteLLM. Bitwarden CLI. PyTorch Lightning. 이들 각각은 개발자 또는 개발자와 밀접한 관련이 있는 도구(tooling)입니다. 신뢰받고, 로컬에 설치되며, 빈번하게 업데이트됩니다. 각각은 개발자의 노트북에서부터 클라우드 계정을 거쳐 프로덕션(production) 환경까지 확장되는 자격 증명 폭발 반경(credential blast radius)을 가진 트로이 목마 벡터(trojan vector)입니다. 동일한 캠페인의 npm 측면은 더 심각합니다. SlowMist 및 기타 연구자들의 공개 분석에 따르면, 공격자들은 atool의 npm 계정을 탈취하여 몇 분 만에 수백 개의 패키지에 걸쳐 수백 개의 악성 패키지 버전을 배포했습니다. Mini Shai-Hulud 멀웨어 제품군은 특히 GitHub 토큰, AWS 키, Kubernetes 비밀(secrets), SSH 자격 증명, 비밀번호 관리자 데이터베이스, 그리고 로컬 암호화폐 지갑 파일을 표적으로 삼습니다. 이것은 단순한 불운의 연속이 아닙니다. 이는 모든 개발자의 ~/.config, ~/.aws, ~/.ssh에서 끝나는 공급망(supply chain)을 겨냥한 의도적이고 지속적인 캠페인입니다. 개발자 엔드포인트(endpoint)가 경계(perimeter)입니다. 약 10년 동안 지배적이었던 보안 모델은 '개발자를 신뢰하고, 플랫폼을 강화하라'는 것이었습니다. 엔지니어링 노트북의 엔드포인트 보안은 보통 기업용 EDR, 어쩌면 DLP 에이전트, 혹은 MDM 정도의 얇은 계층에 불과합니다. 실제 통제 수단은 코드 리뷰, CI/CD 정책, 그리고 프로덕션 접근 권한 주변에 존재합니다. 그 모델은 끝났습니다. 개발자 엔드포인트는 대부분의 환경에서 가장 높은 권한을 가지면서도 가장 적게 모니터링되는 노드(node)입니다. 여기에는 서버로 접속하는 SSH 키가 있습니다. 광범위한 폭발 반경을 가진 클라우드 CLI 토큰이 있습니다. 프로덕션으로 배포되는 리포지토리(repo)에 푸시(push) 권한을 가진 GitHub 자격 증명이 있습니다. 암호화되지 않은 소스 코드가 있습니다. 그리고 점점 더, 보안 팀이 검토한 적 없는 신뢰할 수 있는 제3자 프로세스(third-party processes)들을 대량으로 실행하고 있습니다. VS Code 확장 프로그램(extensions)이 그 한 가지 예입니다. 대부분의 개발 환경에는 수십 개의 확장 프로그램이 있습니다. 각각은 개발자의 완전한 사용자 수준 권한으로 실행됩니다. 각각은 개발자가 읽을 수 있는 모든 파일을 읽을 수 있습니다.

MCP 서버와 AI 코딩 에이전트(AI coding agents)는 거의 그대로 동일한 신뢰 모델(trust model)을 상속받습니다. 즉, 로컬 실행, 광범위한 파일 시스템 가시성, 주변 자격 증명(ambient credentials), 사용자가 승인한 외부 네트워크 액세스, 그리고 대부분의 조직이 검사하지 않는 공급망(supply chain)을 공유합니다. 저는 제 개발 환경에 연결된 30개 이상의 MCP 서버를 실행하고 있습니다. 그중 몇 개는 제가 직접 만들었습니다. 저는 저 자신을 신뢰합니다. 하지만 엄밀한 의미에서, 그 서버들이 가져오는 모든 의존성(dependency)의 공급망을 신뢰하는 것은 아닙니다. 거의 아무도 그렇게 하지 않습니다. 업계는 AI 지원 개발 도구(AI-assisted developer tooling)를 권한이 부여된 인프라(privileged infrastructure)가 아닌, 브라우저 확장 프로그램(browser extensions) 수준의 운영 엄격성으로 채택했습니다. 신뢰 모델링(trust modeling)이 따라잡기 전에 편의성이 더 빠르게 승리한 것입니다.

실질적인 기계적 강제(mechanical enforcement)란 무엇인가
해결책은 개발자에게 주의를 기울이라고 말하는 메모를 보내는 것이 아닙니다. 자정에 지친 엔지니어에게 확장 프로그램 목록을 감사하라고 말하는 것은 통제(control)가 아니라 바람(wish)일 뿐입니다. 해결책은 개발자가 주의를 기울이든 그렇지 않든 실행되는 기계적 강제여야 합니다. 저의 개발 설정에서는 네 가지 계층으로 구성됩니다. 이 중 영리한 것은 하나도 없습니다. 모두 지루합니다. 지루함이 핵심입니다.

첫 번째 계층: 프리 커밋 훅(pre-commit hooks). 모든 저장소(repo)의 모든 커밋은 커밋이 완료되기 전에 Python 스캐너를 실행합니다. 이 스캐너는 OpenAI, Anthropic, Google, GitHub, Slack, Discord 웹훅, AWS 액세스 키(access keys) 및 기타 수십 가지 토큰 형태를 탐지하는 특정 패턴을 가지고 있으며, 가공되지 않은 .env 파일과 인증서/개인 키(certificate/private-key) 파일 탐지 기능도 갖추고 있습니다. 오탐률(false positive rate)을 낮게 유지하기 위해 예시(example)나 자리 표시자(placeholder) 형태는 제외합니다. 실제 비밀 정보(secret)가 스테이징(staged)되면 커밋이 차단됩니다. 이 훅은 개발자가 이를 인지했는지 여부는 상관하지 않습니다.

두 번째 계층: 에이전트 훅(agent hooks). Claude Code와 Codex는 모두 파일 쓰기 및 명령 실행 전에 작동할 수 있는 훅(hooks)을 노출합니다. 저는 제안된 수정 사항에 대해 동일한 스캐너를 실행합니다. 에이전트는 일반적인 쓰기 경로를 통해 디스크에 비밀 정보를 영구적으로 저장할 수 없습니다. 쓰기가 발생하기 전에 훅이 해당 작업을 거부하기 때문입니다.

이는 에이전트가 읽어들인 .env 파일을 다음에 작성할 파일에 그대로 옮겨 적는(paraphrasing) 것과 같은 실제 실수를 잡아냅니다. 또한 자격 증명 정찰(credential reconnaissance) 행위도 잡아냅니다. 저장소 전체에서 비밀번호를 검색(grep)하거나 .env 파일을 읽는(cat) Bash 명령은 애플리케이션 계층이 아닌 도구 호출(tool-call) 경계에서 차단됩니다. 저는 실제로 이 기능이 작동한 로그를 보유하고 있습니다. 올봄 초 실제 OAuth 흐름 중에, 한 에이전트가 로컬 볼트(vault) 디렉토리를 조사하고, systemctl cat을 실행하며, 설정 파일들을 검색하여 공유된 비밀번호를 추출하려고 시도했습니다. 다섯 번의 Bash 호출, 다섯 번의 거부. 각각의 거부에는 보안 정책의 명칭이 명시되었습니다. 올바른 경로는 사용자가 정식 볼트 명령을 통해 명시적으로 검색을 승인하는 것이었으며, 결국 그렇게 되었습니다. 훅(hook)이 제 역할을 다한 것입니다.

세 번째 계층: .claudeignore. 제 개발 머신의 모든 저장소에는 이 파일이 있습니다. 이는 에이전트 버전의 .gitignore와 같습니다. AI 도구가 민감한 경로를 컨텍스트(context)에 로드하는 것을 애초에 방지합니다. 목록은 논란의 여지가 없습니다: .env* 파일, 인증서 및 키 형태, 원시 데이터베이스 파일, 빌드 출력물, 에디터 메타데이터 등입니다. 에이전트가 비밀 정보를 아예 보지 못한다면, 초안이나 요약 또는 커밋에 실수로 유출할 일도 없습니다.

네 번째 계층: 단일 비밀 정보 볼트(secrets vault). 모든 실제 자격 증명은 전용 계정의 AWS Secrets Manager에 저장되며, 단일 CLI를 통해 접근합니다. 애플리케이션 코드, 에이전트 도구, 그리고 CI는 모두 런타임(runtime)에 볼트에서 정보를 가져옵니다. 소스 코드 커밋에는 플레이스홀더(placeholder)만 포함됩니다. 자격 증명을 교체(rotating)한다는 것은 한 곳에서 업데이트하는 것을 의미합니다. 만약 비밀 정보가 유출되더라도, 복사본을 보유했던 모든 설정 파일을 추적할 필요 없이 몇 초 만에 전역적으로 교체할 수 있습니다. 제 보안 정책 문서의 문구는 다음과 같습니다: "훅 실패는 린트(lint) 스타일의 문제가 아니라 보안 결함(security findings)이다. 기계적 계층이 실제 비밀 정보를 포착하면, 해당 정보는 교체되어야 한다. 훅은 꺼달라고 허락을 구하는 것이 아니다."

이것이 하지 못하는 것: 이 스택(stack)은 GitHub 침해 사고를 막지는 못했을 것입니다.

개발자의 모든 권한을 가지고 실행되는 오염된 (poisoned) VS Code 확장 프로그램은 자신만의 경로를 가집니다. 이 프로그램은 무엇인가를 커밋할 필요도 없고, 에이전트의 쓰기 경로 (write path)를 호출할 필요도 없습니다. 디스크에서 토큰을 직접 읽고, 어떤 네트워크 엔드포인트(endpoint)든 호출하여 즉시 데이터를 유출 (exfiltrate)할 수 있습니다. 제가 설정한 어떤 훅 (hook)도 이를 감지하지 못할 것입니다. 왜냐하면 이 흐름은 저의 어떤 훅 포인트 (hook point)를 통해서도 흐르지 않기 때문입니다. 이것이 솔직한 부분입니다. 기계적 계층 (mechanical layer)은 방어 계층 (defense in depth)이지, 벽이 아닙니다. 이 스택이 실제로 수행하는 역할은 일반적인 실패 모드 (failure modes)를 강화하는 것입니다. 즉, 커밋에 실제 키를 붙여넣는 개발자, 비밀 정보를 파일에 친절하게 다시 에코 (echo)해버리는 에이전트, 초기 침해 이후 공격자가 다음 단계의 정찰 (reconnaissance)로 사용하는 자격 증명 조사 (credential probe) 같은 것들입니다. 스택은 쉬운 실수를 제거하고, 시도를 기록하며, 권한이 있는 경로를 가시화합니다.

더 어려운 문제는 GitHub 침해 사고가 강력하게 경고하고 있는 문제입니다. 개발자의 로컬 환경으로 제3자 코드를 전달하는 공급망 (supply chain)에는 보안 모델 (security model)이 거의 없습니다. VS Code 확장 프로그램에 대해서는 "보고된 후 삭제됨" 이외의 의미 있는 검토가 존재하지 않습니다. MCP 서버에 대해서는 "유지 관리자를 신뢰하라" 이외의 의미 있는 검토가 없습니다. 강제되는 서명 (signing) 요구 사항도, 출처 증명 (provenance attestation) 요구 사항도 없으며, 대부분의 팀이 신뢰할 수 있는 런타임 샌드박스 (runtime sandbox)도 없습니다.

만약 당신이 보안 책임자라면, 실행 가능한 질문은 "공격자들이 GitHub에 무엇을 했는가?"가 아닙니다. 실행 가능한 질문은 "내 환경에서 개발자 권한으로 실행되는 제3자 프로세스의 인벤토리 (inventory)는 무엇이며, 만약 오늘 오후에 그중 단 하나라도 침해된다면 어떤 일이 벌어질 것인가?"입니다. 대부분의 조직에게 이 답변은 낙관적이지 않습니다. 앞으로 다가올 일들에 대해, 저는 향후 12개월 내에 세 가지 일이 일어날 것이라 예상합니다. 첫째, 주요 플랫폼들이 강화될 것입니다. GitHub과 Microsoft는 VS Code 확장 프로그램 게시 제어를 강화할 것입니다. Anthropic과 OpenAI는 자신들의 도구 생태계에 출처 서명 (provenance signatures)을 추가할 것입니다.

npm과 PyPI는 레지스트리 수준에서 필요한 변화가 실제로 일어나기 전까지 적어도 한 번의 파동을 더 겪게 될 것입니다. 둘째, MCP (Model Context Protocol) 서버들이 첫 번째 주요 사고를 맞이할 것입니다. 신뢰 모델 (trust model)이 잘못되었습니다. 공격 표면 (attack surface)은 넓습니다. 방어 측의 대응은 이제 겨우 시작된 단계입니다. 누군가 악성 VS Code 확장 프로그램처럼 동작하는 악성 MCP 서버를 작성할 것이며, 이는 아무도 알아차리기 전까지 몇 주 동안 실행될 것입니다. 셋째, 엔지니어링 노트북의 엔드포인트 보안 (endpoint security)에 대한 논의는 "EDR과 메모 한 장" 수준에서 "당신의 개발 환경은 프로덕션 시스템이다"라는 수준으로 이동할 것입니다. 이러한 사고 모델 (mental model)을 먼저 갖춘 조직은, 자신들만의 TeamPCP 모멘트를 기다리는 조직들보다 향후 18개월 동안 비용을 덜 쓰게 될 것입니다. 지난 주말 제가 제거한 Codex Chronicle 설치 건은 올바른 반사 신경의 작은 사례입니다. 제가 제거한 것은 악성 프로그램이 아니었습니다. 그것은 주요 연구소의 정당한 리서치 프리뷰 (research preview)였습니다. 제가 그것을 제거한 이유는 제가 원하는 목적에 아키텍처 (architecture)가 맞지 않았기 때문입니다. 즉, 클라우드 서비스를 통해 주기적으로 최근 화면 컨텍스트 (screen context)를 사용하는 로컬 기능, 제가 감사 (audit)할 수 없는 바이너리, 그리고 열어둘 필요가 없는 네트워크 경로를 가지고 있었습니다. 대체재는 제가 소유한 하드웨어에서 실행되며, 제가 검사할 수 있는 방식으로 작동하고, 강제적인 아웃바운드 의존성 (outbound dependency)이 없습니다. 이러한 아키텍처 선택은 2026년에 더 많은 개발자 도구들이 기본값으로 채택해야 할 방식입니다. 프라이버시 쇼 (privacy theater) 때문이 아니라, 신뢰 프로필 (trust profile)이 더 작고 실패 모드 (failure modes)가 더 잘 보이기 때문에 로컬이어야 합니다. 클라우드 왕복 (cloud round trip)은 벤더가 지속적인 사용을 원하는 경우가 아니라, 클라우드가 진정으로 필요한 경우에만 예약되어야 합니다. GitHub 침해 사고는 제가 화이트보드에 그릴 수 있는 그 어떤 위협 모델 (threat model)보다도 이러한 반사 신경의 보안적 근거를 더 명확하게 만들었습니다. 흥미로운 질문은 보안 팀이 원칙적으로 이에 동의하느냐가 아닙니다. 물어본다면 대부분은 동의할 것입니다. 진짜 흥미로운 질문은, 누군가가 동의하든 안 하든 상관없이 실행될 수 있는 집행력 (enforcement)을 그들이 갖추고 있느냐 하는 것입니다.

만약 귀하의 개발자 엔드포인트 (developer endpoints)가 정책 메모 (policy memos)에 의존하여 운영되고 있다면, 내년은 비용이 많이 드는 한 해가 될 것입니다.

AI 자동 생성 콘텐츠

본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.

원문 바로가기
0

댓글

0