Bitwarden CLI 하이재킹과 npm 공급망 공격 방어 설계
Bitwarden CLI 하이재킹 사례를 바탕으로 npm 공급망 공격의 전파 방식, SBOM·provenance·SCA 기반 방어 체계를 정리한다.
2026-08-14 · 최초 발행 2026-04-24
2026년 4월 22일 오후 늦은 시각, Bitwarden의 공식 CLI 패키지 @bitwarden/cli에 악성 코드가 포함된 2026.4.0 버전이 올라왔다. 이 패키지는 90분 동안 npm 레지스트리에서 유통됐으며, npm 토큰·GitHub 인증 토큰·SSH 키·AWS/Azure/GCP 클라우드 자격증명을 수집하고 발행 권한이 있는 패키지에 자신을 전파하는 웜 기능을 담고 있었다.
JFrog 보안 리서치팀이 공격을 처음 공개했고, Checkmarx와 Socket.dev 분석을 통해 더 넓은 캠페인과의 연결점도 확인됐다. 이 사례는 공식 패키지 배포 경로 자체가 침해되면, 단순한 악성 의존성 탐지를 넘어 개발자 환경과 CI/CD 인프라가 함께 위험해질 수 있음을 보여준다.
공식 배포 경로를 통과한 변조 패키지
@bitwarden/cli 2026.4.0은 2026년 4월 22일 23:57(독일 현지시각, 한국 기준 4월 23일 06:57)부터 4월 23일 01:30까지 배포됐다. 표면상 공식 Bitwarden CLI로 동작하지만, 백그라운드에서 자격증명 탈취 루틴을 수행하는 트로이목마 형태였다.
공격자는 Bitwarden CI/CD 파이프라인에 삽입된 악성 GitHub Action을 이용해 빌드 단계에서 코드를 주입했다. Bitwarden은 해당 npm 릴리스를 deprecated 처리하고 침해된 접근 권한을 폐기했다. 최종 공식 성명에서는 엔드유저 볼트 데이터 접근이나 프로덕션 시스템 침해의 증거를 발견하지 못했다고 밝혔다.
이 공격에서 문제가 된 지점은 패키지 이름이 유사하거나 배포 채널이 비공식적이었다는 데 있지 않다. 공식 빌드 파이프라인이 공격 경로가 됐기 때문에, 사용자는 공식 채널에서 배포된 아티팩트라는 신뢰를 그대로 악용당했다.
Checkmarx Action을 경유한 공격 체인
JFrog, Checkmarx, OX Security의 교차 분석은 이 사건을 TeamPCP로 알려진 위협 행위자 그룹의 공급망 캠페인 일부로 연결했다. TeamPCP는 이전 Trivy와 LiteLLM 공급망 공격에도 연루됐으며, 개발자 도구를 겨냥한 공급망 무기화 전략을 이어 왔다.
공격의 출발점은 Checkmarx의 KICS(Keeping Infrastructure as Code Secure) 오픈소스 프로젝트에서 사용되는 GitHub Action 침해였다. 인프라 코드 보안 스캐닝에 쓰이는 이 Action은 여러 프로젝트의 CI/CD 파이프라인에서 참조됐고, Bitwarden CLI 빌드도 이 경로를 사용했다. 공격자는 신뢰된 Action을 통해 빌드 환경에 접근한 뒤 최종 npm 패키지에 악성 코드를 넣었다.
직접 표적이 아닌 신뢰 관계의 서드파티 도구를 통과하는 이 방식은 2차 공급망 공격(second-order supply chain attack)의 전형이다. Checkmarx와 Bitwarden은 공격 주체가 아니라 피해자였다.
설치 시점에 실행된 탈취와 전파
변조된 @bitwarden/cli 2026.4.0의 package.json에는 preinstall 스크립트가 추가됐다. 설치가 시작되면 bw_setup.js 로더가 실행되고, 로더는 Bun 런타임으로 난독화된 bw1.js를 실행하도록 구성됐다.
탈취 대상에는 다음이 포함됐다.
- npm 인증 토큰 (
~/.npmrc) - GitHub 개인 접근 토큰 (
~/.gitconfig, 환경변수) - SSH 개인 키 (
~/.ssh/) - AWS 자격증명 (
~/.aws/credentials) - Azure CLI 세션 토큰
- Google Cloud 서비스 계정 키
- AI 코딩 어시스턴트(Cursor, Continue 등) 인증 세션
탈취한 npm 토큰으로 피해자가 발행할 수 있는 npm 패키지를 자동 재감염시키는 웜 기능도 포함됐다. 감염된 개발자 한 명의 권한이 관리 중인 수십 개 패키지로 이어질 수 있는 기하급수적 확산 구조다.
유출 채널도 일반적인 C2 서버와 달랐다. 자격증명을 AES-256-GCM으로 암호화한 뒤 피해자 GitHub 계정에 공개 리포지토리를 만들고 그 안에 저장했다. 이 GitHub 데드드롭(dead-drop) C2 방식은 일반 C2 트래픽 탐지를 우회하며, 리포지토리가 압수된 뒤에도 공격자가 이미 확보한 암호화 데이터를 사용할 수 있게 한다.
RSA 서명 기반 명령 전달 채널을 통한 사후 지시 실행 기능과, ~/.bashrc·~/.zshrc에 영속성 코드를 삽입하는 기능도 포함됐다. 따라서 시스템 재시작 이후에도 동작을 유지하도록 설계됐다.
npm 생태계에서 반복되는 침해 경로
npm 공급망 공격은 타이포스쿼팅, 계정 탈취, 의존성 혼동이라는 서로 다른 진입점을 가진다.
오탈자를 노리는 타이포스쿼팅
타이포스쿼팅은 정상 패키지와 비슷한 이름을 등록해 개발자의 오탈자를 유도한다. 예를 들어 axios 대신 axois, react 대신 reac t를 사용하는 방식이다. 2026년 Veracode 분석에서는 4,708개의 타이포스쿼팅 패키지가 발견됐고, 관련 공격은 전년 대비 104.3% 증가했다.
2026년 3월 Axios 공급망 공격에서는 plain-crypto-js라는 악성 패키지를 먼저 배포한 뒤, 주간 다운로드가 1억 회 이상인 axios 공식 버전의 의존성으로 이 패키지를 추가했다. 미국 사이버보안 기관들은 이 공격을 북한 국가 행위자 Sapphire Sleet로 귀속했다.
신뢰된 계정에서 나오는 악성 릴리스
계정 탈취는 정상 패키지 관리자의 npm 계정을 탈취해 기존 패키지에 악성 버전을 배포하는 방식이다. Bitwarden CLI 사건은 이 범주에 속한다. 인포스틸러, 피싱, CI/CD 파이프라인 침해처럼 발행 자격증명을 얻는 경로는 여러 가지다. 패키지 이름 자체는 합법적이므로 타이포스쿼팅보다 식별이 어렵다.
내부 이름을 선점하는 의존성 혼동
의존성 혼동 공격은 기업 내부 패키지와 같은 이름을 공개 npm 레지스트리에 등록해, 내부 레지스트리 대신 공개 레지스트리의 악성 패키지가 설치되도록 유도한다. 2021년 Alex Birsan이 처음 공개한 뒤 실제 공격에 널리 쓰였으나, 2026년에는 스코프드 패키지(@company/package) 정책과 프라이빗 레지스트리 통제가 강화되면서 발생 빈도가 77.1% 감소했다.
개방형 의존성 그래프가 만드는 공격 표면
2025년 npm 레지스트리에서는 454,648개의 악성 패키지가 발견됐다. 전체 오픈소스 악성코드의 99% 이상이 npm을 표적으로 삼았고, 2026년 1분기에도 여러 건의 대형 npm 공급망 사고가 발생했다.
npm은 신뢰를 전제로 한 개방형 생태계라는 설계에서 비롯된 취약점을 갖는다. 먼저 preinstall, install, postinstall 같은 라이프사이클 스크립트는 설치 중 자동 실행된다. 편의 기능이지만, 악성 패키지가 설치 순간 코드를 실행할 수 있는 통로이기도 하다.
npm 레지스트리가 단일 신뢰 루트로 작동한다는 점도 위험을 키운다. 레지스트리 또는 개별 계정이 침해되면 해당 패키지를 신뢰하는 사용자가 함께 노출된다. 여기에 현대 Node.js 프로젝트의 수백~수천 개 직간접 의존성이 더해져 모든 구성요소를 사람이 검토하기 어려워진다.
SBOM과 서명으로 빌드 출처를 검증하는 방법
이런 변조를 방어하는 기반은 SBOM(Software Bill of Materials)과 패키지 서명이다. SBOM은 소프트웨어를 이루는 모든 컴포넌트의 이름, 버전, 공급업체, 라이선스, 알려진 취약점 정보를 담는 목록이다.
미국 NTIA(국가통신정보청)의 권고와 EO 14028(사이버보안 행정명령)에 따라 연방 정부 조달 소프트웨어에는 SBOM 제출이 의무화됐고, 적용 범위는 기업 환경으로도 빠르게 확산되고 있다.
| 포맷 | 주관 기관 | 특징 | 주요 도구 |
|---|---|---|---|
| SPDX | Linux Foundation | ISO/IEC 5962 국제표준, 텍스트/JSON/XML 지원 | syft, trivy |
| CycloneDX | OWASP | VEX(Vulnerability Exploitability eXchange) 지원, JSON/XML | cdxgen, @cyclonedx/cyclonedx-npm |
| SWID | NIST | 설치된 소프트웨어 식별에 특화 | Microsoft, IBM |
npm 환경에서는 @cyclonedx/cyclonedx-npm 또는 syft로 SBOM을 만들고, CI/CD 파이프라인에서 빌드마다 갱신하는 방식이 권고된다.
npm provenance는 2023년 GA(일반 공개)를 달성했다. SLSA(Supply-chain Levels for Software Artifacts) 프레임워크를 바탕으로 패키지 빌드 출처를 암호학적으로 증명하는 체계다.
- CI/CD 환경(GitHub Actions, GitLab CI)에서
npm publish --provenance실행 - npm CLI가 Sigstore 공개 CA에 OIDC 토큰 제출
- Sigstore CA가 단기(ephemeral) X.509 서명 인증서 발급
- 서명된 증명(attestation)이 Rekor 투명성 로그에 기록
npm install시 자동으로 provenance 검증
Rekor 투명성 로그는 변조 방지(tamper-evident) 구조를 사용하므로, 이미 게시된 provenance를 사후 변경하려는 시도를 탐지할 수 있다. Bitwarden CLI 사건에서 npm provenance가 활성화됐다면 공식 소스 리포지토리 커밋과 맞지 않는 빌드를 즉시 감지할 수 있었을 것이다.
CVE 중심 검사를 넘어서는 SCA 운영
SCA(Software Composition Analysis)는 오픈소스 컴포넌트를 분석해 취약점, 라이선스 위험, 공급망 위협을 식별한다. 하지만 Bitwarden CLI처럼 알려진 패키지 자체가 변조된 상황은 전통적인 CVE 기반 SCA만으로 찾기 어렵다. 패키지 무결성 검사와 행위 분석을 함께 두는 전략이 필요하다.
| 도구 | 유형 | 강점 | 한계 |
|---|---|---|---|
| Snyk | 상용 | 개발자 친화적 IDE 통합, 2M+ 취약점 DB | 비용, 상용 라이선스 |
| GitHub Dependabot | 무료/내장 | GitHub 완전 통합, PR 자동 생성 | GitHub 생태계에 종속 |
| OWASP Dependency-Check | 오픈소스 | NVD 연동, 다양한 에코시스템 지원 | 오탐률, 성능 |
| Socket.dev | 상용 | 패키지 행위 분석, 공급망 위협 탐지 | 신규 서비스 |
| Mend Renovate | 오픈소스/상용 | 자동 의존성 업데이트, SBOM 생성 | 설정 복잡도 |
| JFrog Xray | 상용 | Artifactory 통합, 정책 기반 차단 | 비용 |
파이프라인에는 한 단계의 검사만 두기보다, 개발부터 배포까지 통제를 나눠 배치해야 한다.
npm audit은 알려진 CVE를 검사하는 출발점이지만 Bitwarden CLI 유형의 신규 공급망 공격은 탐지하지 못한다. Socket.dev는 네트워크 요청, 파일 시스템 접근, 환경변수 읽기처럼 패키지 코드의 실제 행위를 분석해 의심스러운 패키지를 사전에 찾는 접근법이다.
레지스트리와 설치 경로를 통제하기
기업에서는 패키지가 들어오는 경로를 제어하는 방식이 npm 공급망 위협을 줄이는 데 효과적이다. JFrog Artifactory, Nexus Repository, AWS CodeArtifact 같은 프라이빗 레지스트리는 사용 가능한 패키지를 필터링하고 감사 기록을 남기는 통제 지점이 된다.
운영 시에는 공개 npm 레지스트리를 개발자가 직접 참조하게 두기보다 내부 레지스트리가 업스트림 프록시 역할을 하도록 구성할 수 있다. 승인된 패키지만 허용 목록(allowlist)에 넣고 신규 패키지는 보안 검토 뒤 추가한다. 등록 패키지의 지속적인 CVE 모니터링과 패키지 사용 주체·시점을 남기는 감사 로그도 함께 필요하다.
Bitwarden CLI의 악성 페이로드가 preinstall을 이용했다는 점에서 라이프사이클 스크립트 통제는 별도 방어 계층이 된다.
# .npmrc 또는 프로젝트 설정에서 라이프사이클 스크립트 비활성화
ignore-scripts=true
# LavaMoat allow-scripts로 필요한 패키지만 허용
# package.json
{
"lavamoat": {
"allowScripts": {
"esbuild": true,
"@esbuild/linux-x64": true
}
}
}
package-lock.json 또는 yarn.lock은 설치될 패키지의 정확한 버전과 무결성 해시를 고정한다. npm ci는 잠금 파일과 정확히 일치하는 버전만 설치하며, 수동 변경이 있으면 설치에 실패한다. 따라서 CI/CD에서는 npm ci를 사용하고 프로덕션 파이프라인의 npm install 사용을 금지해야 한다.
발행 토큰에는 최소 권한 원칙(least privilege)을 적용한다. 특정 패키지에서만 사용할 수 있는 그래뉼러 접근 토큰(Granular Access Token)을 사용하고, CI/CD에서는 OIDC 기반 토크리스(tokenless) 발행으로 장기 정적 토큰 노출 위험을 줄인다.
| 보안 조치 | 효과 | 구현 난이도 |
|---|---|---|
| npm provenance 서명 | 빌드 출처 검증 | 낮음 (CI 설정 1줄) |
| 라이프사이클 스크립트 비활성화 | preinstall 공격 차단 | 낮음 |
| 그래뉼러 npm 토큰 | 토큰 탈취 피해 최소화 | 중간 |
| 프라이빗 레지스트리 | 패키지 접근 통제 | 높음 |
| SBOM 자동 생성 | 공급망 가시성 확보 | 중간 |
| SCA 파이프라인 통합 | 취약점/악성 패키지 탐지 | 중간 |
Bitwarden CLI 사례에서 90분이라는 유통 시간은 짧았지만, 웜의 자기 전파 기능은 피해 범위를 더 넓힐 수 있었다. 빌드 무결성을 검증하는 npm provenance, 구성요소를 파악하는 SBOM, 지속적 모니터링을 위한 SCA, 접근 경로를 제한하는 프라이빗 레지스트리, 스크립트 실행 통제는 어느 하나로 대체되지 않는다.
패키지 설치 전 변경 이력을 확인하고 낯선 preinstall·postinstall 스크립트를 경계하며 npm 토큰의 환경변수 노출을 줄이는 습관도 남는다. 공급망 보안은 특정 도구 하나가 아니라 개발 문화와 프로세스 전반에서 유지해야 하는 통제다.
Sources
- https://research.jfrog.com/post/bitwarden-cli-hijack/
- https://thehackernews.com/2026/04/bitwarden-cli-compromised-in-ongoing.html
- https://www.bleepingcomputer.com/news/security/bitwarden-cli-npm-package-compromised-to-steal-developer-credentials/
- https://www.aikido.dev/blog/shai-hulud-npm-bitwarden-cli-compromise
- https://www.ox.security/blog/shai-hulud-bitwarden-cli-supply-chain-attack/
- https://blog.gitguardian.com/bitwarden-cli-gitguardian-views-on-helloworm00/
- https://www.mend.io/blog/compromised-bitwarden-cli-npm-worm-ai-poisoning/
- https://securityboulevard.com/2026/04/bitwarden-cli-compromise-linked-to-ongoing-checkmarx-supply-chain-campaign/
- https://docs.npmjs.com/generating-provenance-statements/
- https://blog.sigstore.dev/npm-provenance-ga/
- https://github.blog/security/supply-chain-security/introducing-npm-package-provenance/
- https://www.veracode.com/blog/threat-research-spring-2026-software-supply-chain-security/
- https://cheatsheetseries.owasp.org/cheatsheets/NPM_Security_Cheat_Sheet.html
- https://www.armorcode.com/blog/defending-against-npm-supply-chain-attacks-a-practical-guide
- https://www.endorlabs.com/learn/how-to-defend-against-npm-software-supply-chain-attacks
- https://socket.dev/blog/axios-npm-package-compromised
- https://rafter.so/blog/sca-tools-comparison
- https://bastion.tech/blog/npm-supply-chain-attacks-2026-saas-security-guide