npm 공급망 보안과 내가 작성하지 않은 코드

지원 종료(EOL)된 PHP용 php2shell 패치(CVE-2026-109618 및 CVE-2026-109619)가 출시되었습니다. 수요가 많아 평소보다 영업팀의 답변이 늦어지고 있으므로, 패치된 패키지를 가장 빠르게 확보하려면 온라인에서 Runtimes용 ELS를 구매하시기 바랍니다 (새 탭에서 열림). 패치 FAQ 읽어보기

이 블로그 글의 AI 요약으로 바로 가기

  • Perplexity를 사용하여 이 게시물을 요약해 주세요
  • Gemini로 이 게시물을 요약해 주세요

모든 npm install 는 신뢰의 표현입니다. 혹시 여러분은 자신의 node_modules 폴더를 보고는 궁금해하며, 여기엔 실제로 뭐가 들어 있나요?? 현대 소프트웨어 개발 현장에서 우리는, 우리가 직접 작성하지도 않은 보이지 않는 ‘코드의 빙산’에 대한 책임을 져야 하는 기묘한 상황에 처해 있습니다. 그 대부분은 전이적 의존성으로 들어오며, 팀원 중 누구도 직접 선택하지 않은 패키지들입니다. 그 코드가 프로덕션 환경에 배포되면, 그 책임감은 불안감으로 변합니다. 시큐어체인 이러한 제3자로부터의 압박 중 일부를 관리하기 위한 방어적 장치를 제공합니다.

전이적 의존성의 빙산

직접 의존성으로 제공되는 패키지를 설치하기 전에, GitHub 별점, 유지보수자의 프로필, 그리고 기여자들의 프로필을 확인해 보는 것이 좋습니다. 라이브러리는 거의 단독으로 존재하는 경우가 드뭅니다. 직접 의존성이 이를 필요로 하기 때문에 전이적 패키지가 함께 설치되곤 합니다. 이를 “여러분의 패키지에 포함된 패키지”, 심지어 “여러분의 패키지에 포함된 패키지에 포함된 패키지”라고 생각하면 됩니다. 이러한 패키지는 여러 계층으로 깊게 얽혀 있을 수 있으며, 사용자가 직접 건드리지 않은 채로 남아 있을 수도 있습니다.

이 빙산은 겉보이는 것보다 훨씬 깊습니다. 말장난을 의도한 표현입니다. “기본적인” 웹 앱이라도 쉽게 1,000개 이상의 패키지를 넘어설 수 있습니다. node_modules. 깊숙이 숨겨진 전이적 종속성은 공급망 공격이 주로 도사리는 곳입니다. 이러한 종속성은 상속받는 타사 코드의 범위를 극적으로 확대시키지만, 수동 감사로는 그 깊숙한 곳까지 도달하기 어려운 경우가 많습니다.

문제는 전이적 의존성이 나쁘다는 것이 아닙니다. 현대적인 개발은 바로 이러한 의존성에 의존하고 있습니다. 문제는 상속받은 코드가 검토하는 코드보다 더 빠르게 증가한다는 점입니다.

악의적인 것이 정당한 것처럼 보일 때

이러한 불안감은 겉보기에는 정상적으로 보이지만 실제로는 악의적인 성격을 띤 패키지들에서 비롯됩니다. 개발자로서 우리는 업무를 처리할 때 습관적인 동작에 많이 의존합니다. 그런데 이제는 AI 덕분에 업무를 처리하는 과정에서 그런 습관적인 동작조차 필요하지 않게 되었습니다. 코딩 보조 도구는 때때로 존재하지 않는 패키지 이름을 제안하기도 합니다. 이로 인해 ‘슬롭스쿼팅(slopsquatting)’이라는 새로운 수법이 등장했는데, 이는 모델이 계속해서 허구적인 이름을 제시할 때 그 이름을 등록해 두고 기다리는 방식입니다.

다음은 가장 흔한 사례 몇 가지를 정리한 목록입니다.

오타 스쿼팅

타이포스쿼팅 공격은 공격자가 합법적이고 널리 사용되는 라이브러리와 거의 구별되지 않는 이름의 패키지를 등록한 뒤, 누군가가 오타를 내거나 대충 훑어보거나 제안된 내용을 신뢰할 것이라는 점을 노리는 방식입니다. 이러한 패키지는 대개 대상 라이브러리의 기능을 모방하므로, 언뜻 보기에 문제가 있는 것처럼 보이지 않습니다. 일반적인 수법으로는 다음과 같은 것들이 있습니다:

  • 문자 치환: 글자를 바꾸는 것, 예를 들어 lodash 그리고 lodahs, 암호화폐 지갑을 노린 실제 악성 패키지입니다. 새로운 npm 이름은 소문자로 작성되어야 하고 URL에 안전하게 사용될 수 있어야 하므로, 유사 이름들은 이러한 규칙을 우회하는 다음과 같은 방법을 사용합니다. 1 ~ 대신 l.
  • 네임스페이스 또는 범위 모방: 공식 라이브러리의 이름을 매우 유사하게 모방한 범위 지정 패키지를 등록하는 행위. 이는 아래에서 설명하는 레지스트리 해결 공격과는 구별된다.
  • 서식 변형: 하이픈 사용 요령을 활용하여 (예: crossenv vs. cross-env) 또는 복수형 규칙을 변경하는 것.

이러한 패키지는 설치 과정에서 임의의 코드를 실행할 수 있기 때문에, 누군가가 소스 코드를 열어 검토하기 전에 API 키, 환경 변수 또는 AWS 인증 정보를 탈취할 수 있습니다.

의존성 혼동

의존성 혼동(Dependency Confusion) 공격은 공개 레지스트리와 사내 레지스트리를 혼합하여 사용하는 조직을 표적으로 삼습니다. 공격자는 내부 패키지와 동일한 이름을 가진 악성 패키지를 게시하고, 대개 더 높은 버전 번호를 부여함으로써 이러한 환경을 악용할 수 있습니다. 빌드 구성이 엄격하게 격리되어 있지 않은 경우, 시스템이 패키지 이름을 내부 패키지 대신 공격자가 게시한 공개 버전으로 해석하여, 설치 시 악성 코드가 자동으로 실행될 수 있습니다.

이 모든 것이 단지 이론에 그치는 것은 아닙니다. 알렉스 버산(Alex Birsan)은 2021년에 내부 라이브러리의 이름을 딴 패키지를 공개하고, 애플, 마이크로소프트 및 수십 개의 다른 조직 내 시스템에서 해당 패키지가 정상적으로 해결되는 것을 확인함으로써 이를 입증했습니다.

잘 모르시는 분들을 위해 설명드리자면, 범위 지정 패키지(예: @my-org/cool-package) 다음을 사용하십시오. @ 네임스페이스 종속성을 나타내는 기호. 조직이 취약한지 여부는 레지스트리, 범위, 프록시 및 락파일을 어떻게 구성했는지에 따라 달라지는 경우가 많습니다. 이러한 라우팅 동작에 대해 한 번도 감사받은 적이 없는 시스템이 가장 큰 위험에 노출되어 있습니다. 파이프라인을 안전하게 보호하려면 패키지 해결이 결정론적이어야 합니다. 비공개 범위를 내부 레지스트리에 매핑하여 .npmrc 명시적으로 지정해야 합니다. 그래야 패키지 관리자가 공용 레지스트리를 통해 해당 스코프를 예기치 않게 해결하는 일이 없습니다:

@my-org:registry=https://registry.internal.example.com/

npmjs.com에서 일치하는 범위를 신청하면 공격자가 사용자가 이미 소유한 신원 명의로 패키지를 게시하는 것을 방지할 수 있습니다. 범위 지정은 주로 명명 규칙일 뿐, 보안 제어 수단이 아니라는 점을 명심하십시오. 동일한 의존성 이름이 두 곳의 서로 다른 위치에서 해결될 수 있다면, 다른 누군가가 사용자를 대신해 그 결정을 내리게 됩니다.

라이프사이클 스크립트

Package.json 다음과 같은 라이프사이클 훅 preinstall, install,그리고 postinstall 의존성 설치 과정에서 자동으로 실행되며, 개발팀 구성원 중 누구도 그 내용을 실제로 확인하기 훨씬 전에 이루어집니다.

이러한 페이로드는 은행 인프라, 빌드 서버 등과 같이 가장 가치가 높은 표적을 정밀 타격합니다. 이들은 다음을 포함한 중요한 기밀 정보를 추출합니다. .env 파일, AWS 토큰, SSH 키: 바로 우리가 버전 관리 시스템에 절대 푸시해서는 안 된다고 늘 듣는 것들입니다.

일부 스크립트는 먼저 환경을 탐색하여 샌드박스나 면밀히 감시되는 시스템이 있는지 확인한 뒤, 보안이 덜 철저한 곳에 도달할 때까지 실행을 보류합니다.

샤이-훌루드는 이것이 어느 정도 규모에 이르는지 보여주었습니다. 2025년 9월의 파동은 postinstall 수백 개의 패키지에서 npm 토큰과 클라우드 인증 정보를 탈취한 뒤, 훔친 정보를 이용해 스스로를 다시 게시했습니다. 11월의 공격 물결은 실행 시점을 앞당겨, preinstall, 그래서 설치가 완료되기 전에 페이로드가 실행되었습니다. 이후 변종들은 선택적 종속성 안에 숨어, 페이로드를 실행한 뒤 npm이 허용하는 방식으로 오류가 발생하도록 했습니다.

그렇긴 하지만, 기본 동작이 드디어 바뀌었습니다. pnpm v10부터는 종속성 라이프사이클 스크립트의 자동 실행이 중단되었으며, 빌드가 필요한 모든 항목은 onlyBuiltDependencies. 2026년 7월 8일에 출시된 npm v12도 동일한 입장을 취했습니다. 즉, 루트 패키지의 allowScripts 정책상 허용되는 경우, 그리고 npm approve-scripts --allow-scripts-pending 결정이 내려지기만을 기다리고 있는 모든 항목을 나열합니다.

한 가지 주의할 점이 있습니다. 승인되지 않은 스크립트는 경고와 함께 건너뛰어지며, 설치 과정은 여전히 종료 코드 0을 반환합니다. 이로 인해 네이티브 종속성이 부분적으로만 구축될 수 있으며, 이로 인해 빌드 또는 런타임 단계에서 나중에 오류가 발생할 수 있습니다. 다음을 커밋하십시오. allowScripts 차단 및 설정 strict-allow-scripts=true CI 환경에서는 검토되지 않은 스크립트가 빌드 실패로 이어집니다. npm 11 이하 버전을 사용 중이라면, 아래 플래그를 사용하면 이 문제를 해결할 수 있습니다:

npm install --ignore-scripts

유용하긴 하지만, 완벽하지는 않습니다. 이 중 어느 것도 임포트 시점의 실행 문제를 다루지 않으며, 앱이 호출하는 순간 최상위 코드가 실행되는 악성 패키지의 경우 require() 설치 스크립트의 보안 조치를 손쉽게 우회합니다.

우리가 배포하는 코드에 대한 책임 문제로 인해 우리 어깨에는 엄청난 부담이 지워집니다. TuxCare의 ‘2026 오픈소스 현황 보고서’에 따르면, 소속 조직에서 사이버 보안 사고를 보고한 응답자 중 61.4%가 패치가 ‘사용 가능’했음에도 불구하고 적용되지 않았다고 답했습니다. 이 수치는 극히 낮아야 마땅합니다. 위험이 존재한다는 것을 아는 것과 그 위험을 제거하는 것은 전혀 다른 문제입니다.

의존성 깊이가 문제를 더 복잡하게 만듭니다. 업스트림에 있는 수정 사항이, 여러분의 트리에서 4단계 아래에 고정된 복사본에는 아무런 영향도 미치지 않습니다.

수동 검토는 여전히 프로세스의 일부로 남아 있지만, 그 정도 규모의 그래프를 수작업으로 감사하는 것은 비현실적입니다. 배포하는 내용에 대한 가시성이 부족하면, 이는 결국 시스템 전체의 안정성을 위협하는 결과로 이어질 수 있으며, 실제로 그렇게 될 것입니다.

SecureChain으로 불안 해소하기

의존성 위험 관리는 정책의 필수 요소여야 합니다. 이러한 관리를 대규모로 수행하려면 어느 팀이든 감당하기 어려울 수 있습니다. SecureChain은 패키지 사용 경로를 변화시킵니다. 공개 레지스트리에서 직접 해결하는 대신, 빌드 과정에서 TuxCare가 관리하는 레지스트리에서 패키지를 가져오게 되며, 이 패키지들은 미리 공지된 일정에 따라 재빌드, 서명 및 패치 처리된 상태입니다.

어떤 레지스트리든 여전히 신뢰에 기반한 결정입니다. 달라진 점은 그 신뢰의 상당 부분이 검증 가능해졌다는 것입니다.

소스 코드 강화

상류에서 공개한 아티팩트를 그대로 재배포하는 대신, 전이적 종속성을 포함한 모든 패키지는 보안이 강화되고 격리된 환경에서 소스 코드부터 재컴파일되며, 알려진 악성코드 및 의심스러운 코드에 대한 검사를 거칩니다.

지속적인 패치 적용

SecureChain은 CVE가 발견될 때마다 SLA에 따라 수정 패치를 제공합니다. 업스트림에서 지원 종료(EOL) 단계에 도달한 패키지의 경우, Endless Lifecycle Support(ELS)를 통해 중요 및 고위험 수정 패치를 사용자가 현재 실행 중인 버전으로 지속적으로 백포트해 드립니다.

패키지 관리 도구를 SecureChain이나 이미 사용 중인 리포지토리 관리 도구(Artifactory 및 Nexus와 호환됨)에 연결하세요. 그러면 검증 가능한 SLSA 레벨 3 준수를 지원하도록 구축된 출처 정보, 특정 패키지 버전에 영향을 미치는 CVE를 명시하는 VEX 문서, 그리고 지원되는 모든 구성 요소에 대한 기계 판독 가능한 SBOM이 제공되며, 지원 범위는 지속적으로 확대되고 있습니다. 물론 이러한 것들만으로는 올바른 보안 관행을 대체할 수는 없습니다. 여전히 락파일, 범위 지정 레지스트리 규칙, 최소 권한 CI 자격 증명이 필요합니다.

핵심 요점

자신이 작성하지 않은 코드를 배포할 때 느끼는 불안감을 어느 정도 덜 수 있습니다. 보안은 지속적인 작업이자 정책입니다. 결코 “한 번 설정해 두고 잊어버리는” 식의 사고방식이나 관행이 아닙니다. 전이적 의존성을 이해하고, 그로 인해 발생하는 문제들을 인지한다면 건전한 프로덕션 코드를 배포하는 데 도움이 될 것입니다.

목표는 오픈 소스에 대한 신뢰를 접는 것이 아닙니다. 우리 모두는 오픈 소스에 의존하고 있습니다. 목표는 그 신뢰를 더 이상 당연시하지 않는 것입니다.

SecureChain과 같은 도구를 활용하면 우리 모두가 짊어지고 있는 그 막중한 부담 중 일부를 덜어낼 수 있습니다. 한 발 앞서 나가서 여러분의 공급망을 안전하게 보호하십시오.

요약
npm 공급망 보안과 내가 작성하지 않은 코드
기사 이름
npm 공급망 보안과 내가 작성하지 않은 코드
설명
앱의 대부분은 팀원 중 누구도 직접 선택하지 않은 코드로 구성되어 있습니다. npm 공급망 공격이 어떻게 이루어지는지, 그리고 이를 어떻게 막을 수 있는지 알아보세요.
작성자
게시자 이름
TuxCare
게시자 로고

4,500명 이상의 Linux 및 오픈 소스 전문가와 함께하세요!

한 달에 두 번. 스팸이 없습니다.

목차
필요한 오픈 소스 보안에 대한 답변 얻기

4,500명 이상의 Linux 및 오픈 소스 전문가와 함께하세요!

한 달에 두 번. 스팸이 없습니다.