npm v12 보안 대개편: 공급망 공격의 시대, 설치 스크립트가 막힌다
💡 글의 핵심 3줄 요약
- 2026년 상반기 Axios, Mastra AI, TanStack 등 대형 패키지를 노린 npm 공급망 공격이 연달아 터지면서 자바스크립트 생태계 전체가 흔들렸습니다.
- 이에 npm v12는 설치 스크립트 자동 실행과 Git 의존성을 기본 차단하는, 16년 역사상 가장 큰 보안 개편을 단행했습니다.
- 다만 기본값 변경만으로 공급망 공격이 끝나지는 않으므로, lockfile 검증·의존성 최소화·2FA 등 개발자 각자의 방어선 점검이 여전히 필수입니다.
npm v12 보안 대개편: 공급망 공격의 시대, 설치 스크립트가 막힌다
안녕하세요! 여러분은 npm install을 입력할 때 어떤 기분이 드시나요? 예전에는 아무 생각이 없었다면, 요즘은 살짝 긴장하게 되지 않으신가요? node_modules 폴더 안에 수백, 수천 개의 패키지가 딸려 들어오는데, 그중 하나라도 오염되어 있다면 내 개발 머신과 CI 서버, 나아가 프로덕션까지 위험해지니까요.
이 막연한 불안이 2026년 들어 현실이 되었습니다. 굵직한 공급망 공격이 몇 달 간격으로 연달아 터졌고, 결국 GitHub이 npm의 기본 동작 자체를 뜯어고치는 초강수를 두게 됐습니다. 이번 달 출시되는 npm v12 이야기입니다. 오늘은 무슨 일이 있었는지, 무엇이 바뀌는지, 그리고 우리는 무엇을 점검해야 하는지 차례로 정리해 보겠습니다.
2026년 상반기, npm 생태계에 무슨 일이 있었나
올해 벌어진 사건들을 시간순으로 따라가 보면 상황의 심각성이 피부로 와닿습니다.
3월에는 HTTP 클라이언트의 대명사인 Axios가 공급망 공격의 표적이 되었습니다. 월간 다운로드가 수억 건에 달하는 패키지인 만큼 파장이 컸죠. 6월에는 AI 에이전트 프레임워크인 Mastra가 공격당했는데, 두 사건 모두 북한 국가 배후 해커 조직의 소행으로 확인되었습니다. 공격자들이 이제 개별 프로젝트가 아니라 '개발 생태계의 급소'를 노린다는 신호입니다.
같은 6월, Red Hat 클라우드 서비스 네임스페이스(@redhat-cloud-services)의 패키지 30여 개가 오염되어 Miasma라는 이름의 악성 페이로드가 배포되는 사건도 있었습니다. 코드 리뷰를 완전히 우회해서 퍼블리시가 이뤄졌다는 점이 충격적이었죠. 또 다른 사건에서는 공격자가 단 6분 만에 TanStack 계열 패키지 42개에 걸쳐 84개의 악성 버전을 쏟아냈습니다. 그중 query-core는 월간 다운로드가 2억 건이 넘는 패키지입니다. 그리고 이달 초에는 신뢰받던 개발자의 계정을 탈취해 블록체인 SDK에 백도어를 심고, 자동 배포 파이프라인을 타고 몇 분 만에 18개 연관 패키지로 퍼뜨린 사건까지 보고되었습니다.
이 사건들의 공통 패턴이 보이시나요? 첫째, 유지보수자 계정 탈취가 시작점입니다. 둘째, 자동화된 배포 파이프라인이 오히려 악성 코드의 확산 속도를 높입니다. 셋째, 악성 코드의 실행 시점은 대부분 패키지 설치 순간, 즉 install script입니다. npm은 패키지 설치 시 preinstall, postinstall 같은 스크립트를 자동 실행해 주는데, 이 편리한 기능이 공격자에게는 "설치만 하면 코드가 실행되는" 완벽한 진입로였던 셈입니다.
npm v12, 무엇이 바뀌나: 16년 만의 기본값 뒤집기
이런 배경에서 GitHub이 내놓은 답이 npm v12입니다. 핵심은 npm 역사상 가장 관대했던 기본값 세 가지를 뒤집는 것입니다.
설치 스크립트 자동 실행 차단
가장 큰 변화입니다. 이제 패키지를 설치해도 install script가 자동으로 실행되지 않습니다. 악성 코드가 패키지에 숨어 들어와도, 설치하는 순간 곧바로 실행되는 경로가 막히는 것이죠. 위에서 본 공격들의 상당수가 postinstall 스크립트를 통해 페이로드를 실행했다는 점을 생각하면, 공격 표면을 정면으로 겨냥한 조치입니다.
물론 부작용도 있습니다. 네이티브 모듈 빌드처럼 정당한 이유로 install script에 의존해 온 패키지들은 명시적인 허용 설정이 필요해집니다. 초기에는 "설치했는데 왜 안 되지?" 하는 혼란이 있을 수밖에 없죠. 편의성과 보안을 맞바꾼 결정인데, 최근의 사고 규모를 보면 커뮤니티도 대체로 수긍하는 분위기입니다.
Git 의존성과 원격 소스 기본 차단
두 번째 변화는 Git 저장소를 직접 가리키는 의존성이 기본 차단된다는 점입니다. Git 의존성은 레지스트리의 검증 절차를 우회하는 통로였고, 커스텀 Git 설정을 이용해 스크립트 제한을 뚫는 기법도 보고되었기 때문입니다. HTTP URL로 직접 받아오는 원격 소스 의존성도 마찬가지로 막힙니다. 앞으로는 레지스트리를 거친 패키지가 기본이고, 그 외의 경로는 개발자가 의식적으로 허용해야 하는 예외가 됩니다.
이 방향성은 사실 다른 생태계가 먼저 걸어간 길이기도 합니다. pnpm은 이미 설치 스크립트를 기본 차단하고 허용 목록으로 관리하는 방식을 도입했고, Bun도 비슷한 접근을 취해 왔죠. 사실상 자바스크립트 패키지 매니저 전체가 "기본은 불신, 허용은 명시적으로"라는 제로 트러스트 방향으로 수렴하고 있는 셈입니다.
"그걸로 충분한가?" 전문가들의 시선과 남은 숙제
그렇다면 npm v12만 나오면 공급망 공격은 끝나는 걸까요? 아쉽게도 보안 업계의 평가는 "중요한 진전이지만 충분하지는 않다"에 가깝습니다.
이유는 간단합니다. install script 차단은 '설치 시점'의 실행만 막을 뿐이기 때문입니다. 악성 코드가 패키지 본체에 숨어 있다가 require나 import로 로드되는 순간 실행된다면, v12의 방어선은 소용이 없습니다. 실제로 최근 공격들 중에는 라이브러리의 정상 함수 안에 악성 로직을 심는 방식도 있었습니다. 계정 탈취라는 근본 원인도 여전합니다. 유지보수자의 토큰이 털리면, 스크립트 차단과 무관하게 오염된 코드는 레지스트리에 올라갑니다.
그래서 개발자 입장에서는 npm v12와 별개로 자체 방어선을 점검할 필요가 있습니다. 실무에서 바로 적용할 수 있는 것들을 꼽아보면 이렇습니다. 첫째, lockfile을 반드시 커밋하고 CI에서는 npm ci로 lockfile 그대로만 설치하세요. 새 버전이 나오자마자 자동으로 끌려 들어오는 것을 막는 가장 기본적인 방어입니다. 둘째, 의존성 업데이트에 하루 이틀의 '숙성 기간'을 두세요. 위 사건들 대부분이 배포 후 몇 시간 안에 탐지되어 제거되었습니다. 최신 버전을 즉시 받는 습관이 오히려 위험한 시대입니다. 셋째, 의존성 자체를 줄이세요. 몇 줄이면 직접 짤 수 있는 기능 때문에 패키지 하나를 통째로 들이는 습관이 공격 표면을 넓힙니다. 넷째, 본인이 패키지 유지보수자라면 2FA와 신뢰 가능한 배포(trusted publishing) 설정은 선택이 아니라 의무입니다.
팀 단위라면 한 걸음 더 나아갈 수 있습니다. Verdaccio 같은 프라이빗 레지스트리 프록시를 사내에 두고 외부 패키지를 한 번 거쳐서 받도록 하면, 특정 버전을 조직 차원에서 차단하거나 사고 발생 시 캐시된 안전한 버전으로 버티는 일이 가능해집니다. CI 파이프라인에 의존성 변경 리뷰를 강제하는 것도 효과적입니다. package.json이나 lockfile이 바뀌는 PR은 반드시 사람의 눈을 거치게 하는 것이죠. npm audit도 물론 돌려야 하지만, 이는 이미 알려진 취약점 데이터베이스에 의존하므로 갓 배포된 악성 버전 앞에서는 무력하다는 한계를 인지하고 써야 합니다. 결국 단일 도구가 아니라 여러 겹의 방어선을 쌓는 것이 공급망 보안의 정석입니다.
결론: 편리함의 시대에서 검증의 시대로
npm v12의 등장은 단순한 버전 업이 아니라 생태계의 철학 전환을 보여주는 사건입니다. "일단 믿고 실행한다"는 편리함의 시대가 끝나고, "기본은 차단, 필요한 것만 명시적으로 허용한다"는 검증의 시대가 열린 것이죠.
돌아보면 오픈소스 생태계는 신뢰라는 자산 위에 세워졌습니다. 그 신뢰가 공격의 통로가 된 지금, 도구의 기본값이 바뀌는 것은 자연스러운 수순입니다. 다만 도구가 아무리 좋아져도 마지막 방어선은 결국 개발자 자신의 습관입니다. 이번 주에 시간을 내서 여러분 프로젝트의 lockfile 정책과 CI 설치 방식, 그리고 npm 계정의 2FA 설정을 한 번씩 점검해 보시길 권합니다. 공급망 보안은 남의 일이 아니라, npm install을 치는 우리 모두의 일이니까요.
이 글은 AI 도구의 도움을 받아 작성한 뒤 직접 검토·편집했습니다.