
TanStack에게 무슨 일이 일어났나요?
요약
TanStack 생태계가 겪은 공급망 공격 사례를 통해 AI 기반 자동화 시스템의 보안 중요성을 다룹니다. 공격자는 가짜 신원을 이용해 CI/CD 흐름과 캐시를 오염시켜 npm에 악성 패키지를 대량 배포했습니다.
핵심 포인트
- 공격자는 Anthropic Claude 앱을 사칭하여 신뢰를 악용함
- GitHub Actions 캐시 오염을 통해 OIDC 토큰을 탈취함
- 단 6분 만에 42개 패키지에 84개의 악성 버전 주입
- 공급망 공격(Supply Chain Attack)의 진화된 위험성 경고
안녕 여러분!👋🏻 오늘은 기능(features)에 대해 이야기하고 싶지 않습니다. 더 중요한 것, 바로 신뢰(confianza)에 대해 이야기하고 싶습니다. 최근 tanstack.com이 AI 기반 자동화 시스템 덕분에 차단된 해킹 시도를 겪었다는 사실이 알려졌습니다. 바이럴이 될 만한 드라마틱한 사건이나 역사적인 다운타임은 아니었지만, 위기로 변하기 전에 실제 위협을 저지했다는 점에서 훨씬 더 흥미로운 사건이었습니다.
솔직히 말해서 이는 많은 것을 시사합니다. 왜냐하면 우리가 TanStack(React Query부터 TanStack Router까지 현대 인터넷의 절반을 지탱하는 데이터베이스와 같은 도구들)과 같은 도구로 작업할 때, 우리는 단순히 코드만을 이야기하는 것이 아니라 생태계, 살아있는 프로젝트, 그리고 이 인프라에 조용히 의존하고 있는 수천 개의 제품에 대해 이야기하고 있기 때문입니다.
그리고 여기서 불편한 진실이 나옵니다. 보안은 더 이상 선택 사항이 아니며 예방은 과장이 아닙니다. 따라서 AI는 더 이상 "미래"가 아니라, 우리가 잠든 사이 야간 근무를 서는 보안 요원입니다.
🔍 정확히 무슨 일이 일어났나요?
Mini Shai-Hulud 캠페인으로 명명된 이 공격은 자격 증명(credentials)을 직접 훔친 것이 아니라, 자동화된 신뢰 시스템을 해킹했습니다.
수십 개의 패키지에 영향을 미치는 악성 버전을 npm에 게시했습니다. (단 6분 만에 CI/CD 흐름과 OIDC 토큰을 악용하여 42개 패키지에 84개의 악성 버전 주입). 또한 서명(signature)과 SLSA가 적용된 아티팩트조차도 침해될 수 있음을 보여주었으며, 이는 공급망 공격(supply chain attacks)의 무서운 진화를 나타냅니다.
[Fork의 악성 PR] ──> [pull_request_target 악용] ──> [GitHub Actions 캐시 오염]
│
[공격 실행] <── [npm의 OIDC 토큰 주입] <── [며칠 후 합법적인 PR 병합]
- 트로이 목마 (
Pwn Request): 공격자는 눈에 띄지 않도록 Anthropic의 Claude 앱이라는 가짜 신원을 사용하여, 이름을 바꾼 포크(fork)로부터Pull Request(PR)를 생성했습니다. - 캐시 오염 (Cache Poisoning): 베이스 저장소의 높은 권한으로 실행되는
pull_request_target트리거를 악용하여, 해당 PR은 공식 프로덕션 흐름에서 사용할 키를 완벽하게 모방한 1.1 GB 크기의 오염된pnpm캐시를 주입했습니다. - 타이밍 트랩 (The timing trap): 공격자는 의심스러운 PR을 닫았습니다. 캐시는 8시간 동안 잠복해 있었고, 며칠 후 정당한 유지 관리자가 실제 코드를 병합했을 때 프로덕션 흐름이 감염된 캐시를 복구했습니다. 이로 인해 OIDC를 통해 신원 토큰(identity tokens)이 탈취되었고,
npm에 악성 버전들이 대량으로 게시되었습니다. - AI 웜(Worm) 요소: 페이로드(payload)는 단순히 AWS,
SSH,npm키를 훔치는 데 그치지 않았습니다. 피해자의 GitHub 토큰을 사용하여 개발자의 로컬 AI 도구 및 코드 에디터에 숨겨진 설정을 작성함으로써, 로컬 개발 환경이 다른 저장소로 바이러스를 보이지 않게 전파하도록 만들었습니다. - 실제 영향: 이 캠페인은 자격 증명(credentials)을 유출했으며 OpenAI와 같은 기업의 내부 장치에 영향을 미쳤습니다. 예방 차원에서 인증서가 교체되었습니다.
정말로 불안한 점은 전파 구성 요소입니다. 이 멀웨어는 OpenAI와 같은 거대 기업에 영향을 미쳤으며(직원들의 장치 감염), .claude/settings.json 및 .vscode/tasks.json에 숨겨진 설정 파일을 주입하는 자가 전파 벡터(self-propagation vector)로 설계되었습니다. 즉, 개발자의 AI(Claude Code 등)와 로컬 환경 자체를 사용하여 자동으로 저장소를 계속 오염시키도록 만든 것입니다.
⚠️ 이러한 일이 프로젝트에 영향을 미치지 않도록 방지하는 방법
이는 편집증을 가지라는 뜻이 아닙니다. 냉철하게 행동하라는 뜻입니다.
침해된 의존성(dependencies)은 preinstall/prepare 단계에서 코드를 실행할 수 있으며 IDE에 지속적으로 남아 있을 수 있습니다.
- 서명 및 SLSA에 대한 신뢰는 배포 파이프라인(pipeline)이 탈취된 경우 절대적이지 않습니다.
- 의식적인 버전 관리:
staging환경, 자동화된 테스트, 패키지 무결성 검증 없이 프로덕션(production) 환경에서 자동으로 업데이트하지 마세요. 검토 없는npm install은 계약서를 읽지 않고 서명하는 것과 같습니다. - 정기적인 감사:
npm audit을 실행하고,Snyk나Dependabot같은 스캐너를 사용하며, 중요한 리포지토리(repository)의 변경 사항을 모니터링하세요. 보안은 일회성 이벤트가 아니라 습관입니다. - 중요 버전 고정:
package-lock.json,pnpm-lock.yaml,yarn.lock을 사용하세요. 락파일(lockfile)은 관료주의적 절차가 아니라 프로젝트의 역사적 기록입니다. - 관측 가능성(Observability) 및 모니터링: 알림을 통합하고, 로그를 검토하며, 이상 행동 탐지를 구성하세요. 새벽 3시 17분에 애플리케이션에 무언가 변화가 생긴다면, 누군가는 이를 알아야 합니다.
- 예방 문화: 팀과 보안에 대해 이야기하고, 프로토콜을 문서화하며, 시나리오를 시뮬레이션하세요. 견고한 프로젝트는 좋은 아이디어만으로 구축되는 것이 아니라 예견(prevision)을 통해 구축됩니다.
기술적 봉쇄 프로토콜 (Technical Containment Protocol)
- 히스토리 검토: 만약
@tanstack/*(또는 동일한 부수적 공격을 받은 Mistral AI의 SDK) 업데이트를 포함하는npm install,pnpm install또는yarn을 실행했다면, 로컬 환경이 노출되었다고 가정하십시오.
개발 머신이나 CI/CD 워크플로우(workflow)에 영향이 의심된다면, 다음 조치들을 임계 순서(critical order)에 따라 실행하십시오:
- 자격 증명 전체 취소 (Revocación integral de credenciales): 즉시 실행하십시오. 로컬에 저장되어 있던 모든 AWS 키, 환경 변수,
SSH개인 키, GitHub 토큰 (PATs), 그리고 npm 게시 토큰을 긴급하게 교체(rotate)하십시오. - AI 및 에디터 설정 정리: 로컬 머신에서 수행하십시오. 로컬 저장소에 변조된 내용이 있는지 조사하십시오. 특히
.claude/settings.json또는.vscode/tasks.json과 같은 폴더에 의심스러운 파일이 없는지 구체적으로 확인하십시오. - 패키지 매니저의 방어적 설정: 선제적 보호 조치입니다.
pnpm또는Bun과 같은 도구를 설정하여 기본적으로 포스트 설치 스크립트 (postinstall)를 비활성화하고, 패키지별로 명시적인 승인을 요구하도록 설정하십시오. 공격자의 코드가 실행되는 지점이 바로 이곳입니다. - 격리된 환경으로의 마이그레이션 (Dev Containers): 보안 아키텍처입니다. 머신의 운영 체제 위에서 직접 개발하는 것을 중단하십시오. 일상적인 개발을 위해 Docker Dev Containers 또는 가상 머신을 도입하십시오. 만약 설치 스크립트가 악성 코드를 실행하더라도, 해당 코드는 컨테이너 내에 격리되어 사용자의 글로벌
SSH키에 접근할 수 없습니다.
자동화와 AI 에이전트의 사용은 전례 없는 수준으로 우리의 속도를 높여주지만, 캐시와 제3자의 자동화 프로세스를 맹목적으로 신뢰하는 것은 업계의 새로운 아킬레스건(Achilles' heel)이 되고 있습니다.
보안은 지루하거나 창의적인 흐름을 늦출 필요가 없습니다. 보안은 당신의 가장 빛나는 아이디어들이 간섭 없이 최종 배포에 이를 수 있도록 보장하는 보이지 않는 프레임워크(framework)가 되어야 합니다.
실무 가이드 및 예시
- 설치 시 위험한 hooks 피하기:
build및 CI 환경을 위해 권장되는 명령어
npm ci --ignore-scripts
설명: --ignore-scripts는 이번 캠페인에서 사용되었던 preinstall, install, postinstall의 실행을 방지합니다. CI 및 build 컨테이너에서 사용하세요. (중요: 프로젝트가 정당한 스크립트에 의존하는 경우, 예외 사항을 문서화해야 합니다).
- 더 안전한 GitHub Actions 워크플로우:
.github/workflows/ci.yml파일 (스니펫):
name: CI
on: [push]
permissions:
...
설명: 외부 기여자의 코드를 실행하기 위해 pull_request_target을 사용하지 마세요. 권한을 제한하고 id-token은 필요한 경우에만 사용하세요.
- CI에서의 간단한 탐지 스크립트:
scripts/scan-node-modules.js
const fs = require('fs');
const path = require('path');
...
설명: 알려진 시그니처(signature)를 검색합니다 (패턴을 조정하세요). CI에서 npm ci 실행 후에 실행하며, 일치하는 항목이 탐지되면 build를 실패 처리합니다.
🧠 이번 해킹 시도가 우리에게 상기시켜 주는 것
- 의존성(dependencies)은 문입니다: 우리가 설치하는 각 패키지는 신뢰 관계입니다. 그리고 신뢰는 가정하는 것이 아니라 검증하는 것입니다.
- 오픈 소스(open source)는 취약하지 않지만... 공격받기 쉽습니다: 바로 영향력이 크기 때문입니다.
- 잘 사용된 AI는 강력한 아군입니다: 조기 탐지, 이상 패턴, 자동 차단. AI가 인간의 판단을 대체하지는 않지만, 대응 속도를 배가시킵니다.
빠른 완화 조치 비교표
결론
tanstack.com에 대한 해킹 시도는 세상의 종말이 아니었습니다. 그것은 디지털 세계가 살아있는 영역이라는 점을 상기시켜 주는 계기였습니다. 우리는 모든 위협을 통제할 수는 없지만, 우리가 얼마나 준비되어 있는지는 통제할 수 있습니다. 기술이 진화하듯 공격자들도 진화합니다. 오늘 무언가를 구축한다는 것은 내일을 생각한다는 것을 의미하며, 우리가 만든 것을 보호하는 것은 직업의 일부입니다.
우리의 프로젝트는 단순한 저장소 (Repository)가 아니기 때문입니다. 그것은 투입된 삶의 시간이며, 우리를 신뢰하는 팀원들이고, 우리의 안정성에 기대를 거는 고객들입니다. 신뢰할 수 있는 인프라가 배후에서 무너진다면, 가장 화려한 디자인과 가장 민첩한 기능도 아무런 가치가 없습니다.
이 기술적 여정에 함께해 주셔서 감사합니다! 👩🏻🦰 👩🏻💻✨
🚀 이 콘텐츠가 영감을 주었나요?
여러분의 의견이나 경험을 듣고 싶습니다. 🧡
제가 만들고 있는 것들(프로젝트, 블로그, 기술 콘텐츠, AI/ML 소식)을 더 탐색하고 싶다면 다음을 방문해 주세요:
-
🎯 orli ext{.app}
연결을 원하신다면: -
📚 개인 블로그
✨ Code with heart - Create with soul ✨
참고 문헌:
Gemini (google.com)로 생성된 이미지
porunmillondeamigos #makeyourselfvisible #creatorcontent #linkedin #developers #opentowork #hackeo #tanstack #npm #security #MiniShaiHulud #SLSA #IA #OIDC
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기


