정상 서명이 붙은 악성 패키지, OpenAI가 인증서를 바꾼 이유
TanStack npm 사고가 OpenAI Codex와 ChatGPT Desktop 인증서 교체로 번졌습니다. AI 개발 도구의 공급망 신뢰가 다시 시험대에 올랐습니다.
- 무슨 일: TanStack Router/Start 계열
@tanstack/*42개 패키지에서 84개 악성 npm 버전이 약 6분 동안 게시됐습니다.- OpenAI는 직원 기기 2대가 영향을 받았고, 예방 조치로 ChatGPT Desktop, Codex App, Codex CLI, Atlas의 macOS 서명 인증서를 교체한다고 밝혔습니다.
- 핵심 맹점: 공격은 장기 npm 토큰 탈취가 아니라
pull_request_target, Actions cache poisoning, OIDC 토큰 추출을 연결했습니다. - 개발자 영향: provenance와 SLSA가 있어도 서명된 악성 배포가 가능했습니다. AI 코딩 도구는 모델보다 설치 체인부터 믿어야 합니다.
- 주의점: macOS OpenAI 앱 사용자는 2026년 6월 12일까지 최신 버전으로 업데이트해야 하며, lockfile과 credential rotation 확인이 필요합니다.
TanStack npm 공급망 사고가 OpenAI의 AI 개발 도구 업데이트 문제로 번졌습니다. 사건의 출발점은 프론트엔드 생태계의 인기 패키지였습니다. 하지만 도착점은 ChatGPT Desktop, Codex App, Codex CLI, Atlas 같은 OpenAI macOS 앱의 서명 인증서 교체였습니다. 그래서 이 뉴스는 단순한 "npm 패키지가 뚫렸다"는 보안 기사로만 보기 어렵습니다. AI 코딩 에이전트가 로컬 저장소, 터미널, 브라우저, 사내 도구, 클라우드 자격 증명 근처에서 움직이는 시대에, 패키지 설치 체인이 곧 AI 제품의 신뢰 경계가 됐다는 신호입니다.
OpenAI는 2026년 5월 13일 사고 대응문에서 TanStack npm 공급망 공격으로 직원 기기 2대가 영향을 받았다고 밝혔습니다. OpenAI 설명에 따르면 공격자는 제한된 credential material을 일부 내부 source repository에서 빼냈습니다. 다만 OpenAI는 고객 데이터 접근, 프로덕션 시스템 접근, 지식재산 유출, 배포된 소프트웨어 변조 증거를 확인하지 못했다고 설명했습니다. 그럼에도 OpenAI는 해당 repository에 iOS, macOS, Windows 제품 서명 인증서가 포함돼 있었다는 이유로 인증서를 교체하기로 했습니다. 피해 범위가 작아 보여도, 코드 서명 신뢰는 작게 다룰 수 없는 영역이기 때문입니다.
여기서 눈에 띄는 점은 인증서 교체 대상입니다. OpenAI는 macOS용 ChatGPT Desktop, Codex App, Codex CLI, Atlas를 언급했습니다. 사용자는 최신 버전으로 업데이트해야 하며, 2026년 6월 12일 이후 오래된 macOS 앱은 동작하지 않을 수 있습니다. iOS와 Windows 앱은 자동 업데이트로 처리됩니다. 이 대목이 AI 개발자에게 중요한 이유는 분명합니다. Codex CLI와 데스크톱 AI 도구는 이제 단순한 챗봇 클라이언트가 아닙니다. 로컬 프로젝트를 읽고, 코드를 고치고, 명령을 실행하고, 인증된 세션 근처에서 일합니다. 이런 도구의 서명 인증서가 신뢰 사슬에서 흔들리면, 모델 성능과 무관하게 제품 전체가 위험해집니다.
TanStack 쪽 설명은 사건의 구조를 더 선명하게 보여줍니다. TanStack 포스트모템과 GitHub 보안 권고에 따르면, 2026년 5월 11일 19:20부터 19:26 UTC 사이 42개 @tanstack/* 패키지에 총 84개 악성 버전이 게시됐습니다. 시간만 놓고 보면 6분입니다. 하지만 그 6분 동안 publish된 버전은 정상 GitHub Actions OIDC trusted publisher binding을 통과했고, npm provenance도 붙었습니다. 공격자가 오래된 npm 토큰 하나를 주워서 몰래 publish한 사건이 아니었습니다. 더 불편한 쪽입니다. 현대적인 배포 보호 장치가 있는 프로젝트에서, 워크플로 구성이 허용한 틈을 따라 정상 경로로 악성 코드가 나갔습니다.
@tanstack/* 패키지공격 사슬은 pull_request_target에서 시작했습니다. 이 이벤트는 오픈소스 프로젝트에서 조심해서 써야 하는 GitHub Actions 기능입니다. 일반 pull_request와 달리 base repository의 권한과 secret에 가까운 컨텍스트에서 실행될 수 있기 때문입니다. TanStack은 이 구성을 통해 외부 PR과 base branch 사이의 경계가 흐려졌고, 공격자가 GitHub Actions cache를 오염시킬 수 있었다고 설명했습니다. 그 다음 단계는 러너 메모리였습니다. 공격자는 publish job이 OIDC 토큰을 얻는 순간을 노렸고, 메모리에서 토큰을 추출해 npm trusted publishing에 사용했습니다. 결과적으로 publish workflow 파일 자체는 바뀌지 않았지만, 정상 publish 경로로 악성 패키지가 나갔습니다.
이 대목이 이번 사건의 핵심입니다. 많은 팀이 "npm 토큰을 오래 보관하지 않고 OIDC trusted publishing을 쓰면 안전하다"고 이해합니다. 큰 방향은 맞습니다. 장기 토큰을 없애고, GitHub Actions와 npm 사이에 짧은 수명의 identity token을 쓰는 것은 분명한 개선입니다. SLSA provenance도 배포가 어디에서 만들어졌는지 확인하는 데 도움이 됩니다. 하지만 이번 사건은 이런 장치가 워크플로 논리 오류까지 대신 고쳐주지는 않는다는 사실을 보여줬습니다. 신뢰할 수 있는 pipeline에서 악성 코드가 만들어지고, 신뢰할 수 있는 identity로 publish되면 provenance는 "이 빌드는 정말 그 pipeline에서 나왔다"고 말할 뿐입니다. "그 pipeline이 공격자에게 속지 않았다"고 보장하지는 않습니다.
외부 PR과 pull_request_target 워크플로
GitHub Actions cache poisoning으로 base/fork 경계 우회
publish job 러너 메모리에서 OIDC 토큰 추출
npm trusted publisher 경로로 악성 버전 배포
OpenAI 직원 기기 감염, macOS 제품 서명 인증서 교체
악성 payload도 전형적인 credential stealer에 가까웠습니다. GitHub 권고는 설치 시 실행되는 약 2.3MB 난독화 JavaScript 파일 router_init.js를 언급합니다. 이 코드는 AWS, GCP, Kubernetes, Vault, npm, GitHub, SSH 등 개발자와 CI 환경에서 흔히 보이는 자격 증명을 찾고 외부 네트워크로 업로드하려 했습니다. OpenAI가 "제한된 credential material"이라고 표현한 것도 이 흐름과 맞닿아 있습니다. 공격자는 모델을 속인 것이 아니라 개발 도구가 실행되는 환경을 훑었습니다. AI 보안 담론이 프롬프트 인젝션과 모델 탈옥에 집중하는 동안, 실제 사고는 여전히 패키지 설치와 credential hygiene에서 터집니다.
TanStack의 대응은 빠른 편이었습니다. 외부 연구자가 기술 분석과 함께 이슈를 열었고, Socket.dev 연락이 이어지면서 워룸이 열렸습니다. TanStack은 악성 버전을 제거하고, 영향 범위를 Router와 Start 계열 저장소로 한정했습니다. 2026년 5월 15일 후속 글에서는 Query, DB, Store, AI, Table, Form 등 다른 TanStack 저장소는 영향을 받지 않았다고 all clear 상태를 냈습니다. 동시에 하드닝 작업도 공개했습니다. pull_request_target 사용을 제거하거나 축소하고, GitHub Actions cache 사용을 더 엄격히 통제하며, publish 경로와 release workflow를 강화하는 방향입니다.
OpenAI 대응도 비슷한 문법을 가집니다. OpenAI는 영향을 받은 credential을 철회하고, 개인 접근 토큰 사용을 제한했으며, 최소 release age 같은 package manager 설정을 강화했다고 설명했습니다. Axios 관련 공급망 사고 이후 dependency protection을 계속 강화해 왔다는 설명도 붙었습니다. 이 대목은 실무적으로 중요합니다. OpenAI 같은 AI 기업도 npm 생태계 바깥에 살지 않습니다. 내부 도구, 프론트엔드, 데스크톱 앱, 문서 사이트, 테스트 환경, 개발자 워크스테이션은 모두 일반 오픈소스 공급망 위에 놓입니다. AI 모델을 직접 만드는 회사도 dependency graph 앞에서는 다른 소프트웨어 조직과 같은 위험을 공유합니다.
커뮤니티 반응은 기술적으로 꽤 냉정했습니다. Reddit의 JavaScript, Node, React, netsec 커뮤니티에서는 TanStack의 공개 대응이 빠르고 투명했다는 평가가 많았습니다. 동시에 "provenance가 붙은 악성 패키지"라는 표현이 반복됐습니다. 이 말은 다소 거칠지만 핵심을 찌릅니다. 개발자들이 provenance를 만능 방어막처럼 받아들이면 안 된다는 뜻입니다. provenance는 공격 사슬의 한 지점을 증명합니다. 그러나 공격자가 그 지점 이전, 특히 CI workflow와 runner 환경을 장악했다면 증명은 오히려 공격자에게 신뢰 도장을 찍어주는 결과가 될 수 있습니다.
이 사건이 AI 뉴스인 이유는 OpenAI라는 이름 때문만은 아닙니다. AI 코딩 도구의 사용 방식이 공급망 사고의 의미를 바꾸고 있기 때문입니다. 과거 npm 사고는 주로 빌드 서버, 웹앱, 배포 artifact 문제로 이해됐습니다. 이제는 로컬 AI 코딩 에이전트가 개발자 노트북에서 dependency install, test run, browser automation, Git operation을 함께 수행합니다. 에이전트가 pnpm install을 실행하거나, repo를 열어 dependency를 업데이트하거나, CI 설정을 고치는 상황은 더 이상 드문 실험이 아닙니다. 이때 악성 패키지는 단지 앱 코드 안으로 들어오는 것이 아니라, 에이전트가 접근할 수 있는 로컬 credential과 사내 개발 흐름 근처로 들어옵니다.
특히 Codex CLI 같은 도구는 신뢰 경계가 섬세합니다. 사용자는 자연어로 "이 버그 고쳐줘"라고 말하지만, 실제로는 로컬 파일 읽기, 패키지 설치, 테스트 실행, Git diff 작성이 이어집니다. 도구가 서명된 앱으로 배포되고, 사용자가 그 앱을 신뢰해 권한을 부여하는 순간, 코드 서명 인증서는 제품의 첫 번째 약속이 됩니다. OpenAI가 고객 데이터나 프로덕션 침해 증거를 확인하지 못했음에도 인증서를 바꾼 이유가 여기에 있습니다. 소프트웨어가 변조됐다는 증거가 없더라도, 서명 material이 노출 가능한 위치에 있었다면 미래 배포 신뢰를 다시 세워야 합니다.
개발팀이 지금 확인할 것은 네 가지입니다. 첫째, lockfile입니다. 2026년 5월 11일 전후로 @tanstack/router, @tanstack/start, 관련 @tanstack/* 패키지가 악성 버전을 가리키는지 확인해야 합니다. 둘째, 설치 로그와 CI 로그입니다. 악성 버전이 설치된 환경에서는 package install 시점의 network egress와 credential access를 봐야 합니다. 셋째, credential rotation입니다. npm, GitHub, cloud provider, Kubernetes, Vault, SSH 관련 토큰이 같은 개발 환경에 있었다면 보수적으로 회전하는 편이 맞습니다. 넷째, CI workflow입니다. pull_request_target을 쓰는 workflow가 외부 PR 코드를 checkout하거나, cache key를 신뢰하거나, publish job과 같은 권한 경계에 닿아 있는지 확인해야 합니다.
| 확인 지점 | 왜 중요한가 | 이번 사고의 교훈 |
|---|---|---|
| lockfile | 짧게 게시된 악성 버전도 lock에 남으면 오래 재현됩니다. | 6분 사고라도 설치 기록은 훨씬 오래 남을 수 있습니다. |
| CI cache | cache는 신뢰 경계를 넘는 데이터 통로가 될 수 있습니다. | fork와 base branch 사이의 cache 공유가 공격면이 됐습니다. |
| OIDC publish | 장기 토큰을 줄이지만 runner 탈취를 자동 방어하지는 않습니다. | 정상 trusted publisher 경로가 악성 배포에 쓰였습니다. |
| 코드 서명 | 사용자가 앱 업데이트를 믿는 마지막 공개 신호입니다. | OpenAI는 변조 증거가 없어도 예방적으로 인증서를 교체했습니다. |
AI 팀에는 한 가지 질문이 더 붙습니다. 에이전트가 패키지 설치와 배포 작업을 어디까지 자동으로 수행하게 할 것인가입니다. 단순히 "에이전트에게 install 명령을 금지하자"는 결론은 현실적이지 않습니다. AI 코딩 에이전트의 장점은 의존성을 추가하고, 테스트를 돌리고, 문제를 끝까지 재현하는 데 있습니다. 대신 필요한 것은 권한과 관측성의 분리입니다. 에이전트가 dependency를 바꿀 수는 있어도, 외부 PR 컨텍스트에서 publish 권한과 만나는 길은 닫혀 있어야 합니다. 에이전트가 로컬 명령을 실행할 수는 있어도, cloud credential과 code signing material은 기본적으로 같은 작업 디렉터리에 없어야 합니다.
이번 사고는 "보안 도구를 더 붙이면 된다"는 식으로 끝나지 않습니다. TanStack은 이미 2FA, npm provenance, SLSA provenance, OIDC trusted publishing을 쓰고 있었습니다. 문제가 없었다는 뜻이 아닙니다. 오히려 좋은 장치를 도입한 뒤에도 남는 위험이 무엇인지 더 정확히 봐야 한다는 뜻입니다. pull_request_target 같은 기능은 오픈소스 유지보수자에게 편리합니다. 외부 기여자의 PR에도 라벨링, 코멘트, 미리보기, 테스트 자동화를 붙일 수 있습니다. 그러나 그 편의가 publish 경로와 cache 경계를 만나는 순간, 공격자는 "권한 있는 자동화"를 자기 도구로 바꿀 수 있습니다.
시장 관점에서도 이 사건은 공급망 보안 업체와 AI 개발 플랫폼이 겹치는 지점을 보여줍니다. Socket, Snyk, StepSecurity, Wiz, Aikido 같은 보안 업체는 malicious package detection, CI hardening, dependency intelligence를 내세웁니다. OpenAI, Anthropic, GitHub, Cursor 같은 AI 개발 도구 업체는 코드를 생성하고 실행하는 경험을 고도화합니다. 두 영역은 이제 분리되지 않습니다. 에이전트가 코드를 작성하고 dependency를 바꾸는 순간, 보안 스캐너는 사후 점검 도구가 아니라 에이전트 실행 루프의 일부가 됩니다. AI 코딩 플랫폼이 앞으로 package provenance, install policy, credential boundary, approval gate를 기본 UX로 다루게 될 가능성이 큽니다.
OpenAI의 발표는 이 흐름을 조용히 인정합니다. 사용자가 체감하는 조치는 앱 업데이트입니다. 하지만 실제 메시지는 더 넓습니다. AI 개발 도구가 커질수록 "모델이 생성한 코드가 안전한가"만 볼 수 없습니다. 그 코드를 만드는 도구가 어떤 패키지를 설치하는지, CI가 어떤 cache를 믿는지, 어떤 OIDC token이 언제 발급되는지, code signing material이 어디에 있는지까지 같은 보안 이야기 안에 들어옵니다. AI 에이전트가 개발자의 손을 대신한다면, 개발자의 손이 닿던 위험도 같이 상속합니다.
이번 사건을 과장해서 해석할 필요는 없습니다. OpenAI는 고객 데이터나 프로덕션 시스템 침해 증거를 확인하지 못했다고 밝혔고, TanStack은 영향 범위를 비교적 빠르게 정리했습니다. 그러나 축소해서 볼 일도 아닙니다. 6분 동안 게시된 악성 패키지가 세계적인 AI 기업의 서명 인증서 교체까지 이어졌습니다. 이 한 줄이 충분히 큽니다. 정상 서명이 붙은 배포물도 악성일 수 있고, provenance가 있어도 workflow가 속으면 믿을 수 없으며, AI 개발 도구의 신뢰는 모델 API가 아니라 npm install과 GitHub Actions cache에서 먼저 무너질 수 있습니다.
결론은 단순합니다. AI 코딩 시대의 공급망 보안은 더 이상 배경 인프라가 아닙니다. Codex나 ChatGPT Desktop을 업데이트하는 사용자의 행동, 오픈소스 maintainer가 고치는 GitHub Actions 설정, 개발팀이 회전하는 토큰, package manager가 적용하는 release age 정책이 모두 같은 이야기입니다. 모델이 더 많은 작업을 대신할수록, 그 모델을 둘러싼 설치·서명·배포 체인은 더 엄격해야 합니다. TanStack 사고가 남긴 불편한 교훈은 바로 이것입니다. AI 도구의 첫 번째 신뢰 문제는 답변 품질이 아니라, 그 도구가 서 있는 소프트웨어 공급망입니다.