# Bitwarden CLI, 진행 중인 Checkmarx 공급망 캠페인에서 손상됨

> Clean Markdown view of GeekNews topic #28837. Use the original source for factual precision when an external source URL is present.

## Metadata

- GeekNews HTML: [https://news.hada.io/topic?id=28837](https://news.hada.io/topic?id=28837)
- GeekNews Markdown: [https://news.hada.io/topic/28837.md](https://news.hada.io/topic/28837.md)
- Type: GN+
- Author: [neo](https://news.hada.io/@neo)
- Published: 2026-04-24T10:11:36+09:00
- Updated: 2026-04-24T10:11:36+09:00
- Original source: [socket.dev](https://socket.dev/blog/bitwarden-cli-compromised)
- Points: 1
- Comments: 1

## Topic Body

- npm용 **Bitwarden CLI 패키지**가 진행 중인 **Checkmarx 공급망 공격**의 일부로 손상됐고, 현재 확인된 영향 범위는 `@bitwarden/cli` 2026.4.0 빌드에 한정됨
- 패키지에 포함된 **`bw1.js` 악성 코드**는 `audit.checkmarx[.]cx/v1/telemetry` 같은 동일한 인프라와 난독화 방식을 사용하며, 손상된 GitHub Action을 이용한 CI/CD 침해 정황과도 맞물림
- 수집 대상은 **GitHub 토큰**뿐 아니라 AWS, Azure, GCP 자격 증명, `.npmrc`, SSH 키, 환경 변수, Claude/MCP 설정 파일까지 넓게 퍼져 있음
- 탈취한 정보는 공개 GitHub 저장소 생성과 커밋, npm 토큰을 이용한 **재배포 확산**, workflow 주입으로 이어지며, `~/.bashrc`와 `~/.zshrc` 수정 같은 지속성 확보 기능도 포함됨
- Bitwarden CLI를 사용한 조직은 이번 사건을 **자격 증명 노출**과 **CI/CD 침해**로 다뤄야 하며, CI 로그 검토와 노출 가능 비밀정보 교체가 중요함

---

### 개요
- **Bitwarden CLI npm 패키지**가 진행 중인 **Checkmarx 공급망 공격**의 일부로 손상되었고, 확인된 대상 버전은 [`@bitwarden/cli2026.4.0`](https://socket.dev/npm/package/@bitwarden/cli/overview/2026.4.0)임
  - 악성 코드는 패키지에 포함된 [`bw1.js`](https://socket.dev/npm/package/@bitwarden/cli/files/2026.4.0/bw1.js)에 들어 있었음
  - 공격 경로는 Bitwarden의 **CI/CD 파이프라인** 안에서 손상된 GitHub Action을 활용한 정황과 맞물리며, 다른 저장소들에서 확인된 캠페인 패턴과 일치함
- 현재까지 확인된 범위는 **Bitwarden CLI 빌드**에 한정되어 있고, 손상은 더 넓은 [**Checkmarx campaign**](https://socket.dev/blog/checkmarx-supply-chain-compromise)에서 식별된 GitHub Actions 공급망 벡터를 따름
  - npm용 CLI 패키지만 관련되어 있음
  - Chrome 확장, MCP 서버, 그 밖의 정식 배포물은 현재까지 영향이 확인되지 않았음
- 조사는 계속 진행 중이며, 전체 기술 분석과 영향 버전, 침해 지표, 대응 지침은 추가 공개될 예정임
- Bitwarden CLI를 사용하는 경우 **CI 로그 검토**와 노출 가능성이 있는 **비밀정보 교체**가 필요함

### 기술 분석
- 악성 페이로드 **`bw1.js`** 는 전날 분석된 Checkmarx의 `mcpAddon.js`와 핵심 인프라를 공유함
  - 동일한 C2 엔드포인트 **`audit.checkmarx[.]cx/v1/telemetry`** 를 사용하고, `__decodeScrambled`와 시드 `0x3039`로 난독화되어 있음
  - GitHub API를 통한 커밋 기반 유출과 npm 레지스트리를 통한 토큰 탈취 및 재배포도 함께 수행함
- 내장된 페이로드 구조도 같은 계열임
  - **gzip+base64 구조** 안에 GitHub Actions `Runner.Worker` 메모리를 긁어 GitHub 토큰을 노리는 Python 스크립트가 포함됨
  - 재배포 npm 패키지를 위한 `setup.mjs` 로더, GitHub Actions workflow YAML, 하드코딩된 RSA 공개키, 이념적 선언문 문자열이 함께 들어 있음
- 자격 증명 수집 범위가 매우 넓음
  - GitHub 토큰은 `Runner.Worker` 메모리 스크래핑과 환경 변수에서 수집함
  - AWS 자격 증명은 `~/.aws/` 파일과 환경 변수에서 찾음
  - Azure 토큰은 `azd`를, GCP 자격 증명은 `gcloud config config-helper`를 통해 수집함
  - `.npmrc`, SSH 키, 환경 변수, Claude/MCP 설정 파일도 대상에 포함됨
- GitHub를 통한 **유출 방식**도 구체적으로 확인됨
  - 피해자 계정 아래에 Dune 테마 이름 규칙 **`{word}-{word}-{3digits}`** 를 따르는 공개 저장소를 생성함
  - 암호화된 결과물을 커밋하고, 커밋 메시지에는 `LongLiveTheResistanceAgainstMachines` 마커와 함께 토큰을 삽입함
- 공급망 확산 메커니즘까지 포함됨
  - 탈취한 npm 토큰으로 쓰기 가능한 패키지를 찾아 **preinstall hook**가 삽입된 상태로 재배포함
  - GitHub Actions workflow를 주입해 저장소 비밀정보를 추가로 수집함
- **러시아 로캘 킬 스위치**가 존재함
  - 시스템 로캘이 `"ru"`로 시작하면 조용히 종료함
  - `Intl.DateTimeFormat().resolvedOptions().locale`와 `LC_ALL`, `LC_MESSAGES`, `LANGUAGE`, `LANG` 환경 변수를 확인함
- 런타임은 **Bun v1.3.13**이며 GitHub Releases에서 내려받음

### Checkmarx 사고와 다른 지점
- `bw1.js`에는 Checkmarx 사고 문서에 없던 추가 침해 지표가 들어 있음
  - 하드코딩된 잠금 파일 **`/tmp/tmp.987654321.lock`** 으로 동시 실행을 막음
  - `~/.bashrc`와 `~/.zshrc`에 페이로드를 주입해 **셸 프로필 지속성**을 확보함
  - 저장소 설명을 `Shai-Hulud: The Third Coming`으로 설정하고, 디버그 문자열에 `"Would be executing butlerian jihad!"`를 포함하는 등 **명시적 브랜딩**을 사용함
- 공유 도구가 동일한 악성코드 생태계 연결성을 강하게 시사하지만, 운영 서명은 귀속 판단을 더 어렵게 만듦
  - Checkmarx 공격은 발견 뒤 TeamPCP가 `@pcpcats` 소셜 계정을 통해 자신들의 소행이라고 주장했음
  - 해당 악성코드는 정상처럼 보이는 설명으로 위장하려 했음
- 이번 페이로드는 공개적 태도가 다름
  - Shai-Hulud 저장소 이름, `"Butlerian Jihad"` 선언문, 기계에 대한 저항을 내세운 커밋 메시지처럼 **이념적 표식**이 악성코드 안에 직접 들어 있음
  - 공유 인프라를 쓰는 다른 운영자, 더 강한 이념성을 가진 분파, 또는 캠페인의 공개적 태도 변화라는 여러 가능성이 함께 남아 있음

### 권고 사항
- 악성 Bitwarden npm 패키지를 설치한 조직은 이번 사건을 **자격 증명 노출**과 **CI/CD 침해** 사건으로 취급해야 함
- 개발자 시스템과 빌드 환경에서 영향 패키지를 즉시 제거하고, 해당 환경에 노출됐을 수 있는 자격 증명을 모두 교체해야 함
  - GitHub 토큰, npm 토큰, 클라우드 자격 증명, SSH 키, CI/CD 비밀정보가 포함됨
- GitHub에서는 비인가 저장소 생성과 비정상 workflow를 점검해야 함
  - `.github/workflows/` 아래의 예상치 못한 파일, 의심스러운 workflow 실행, artifact 다운로드, Dune 테마 이름 패턴 **`{word}-{word}-{3digits}`** 를 따르는 공개 저장소를 확인해야 함
  - 영향 가능성이 있으면 새로 게시된 저장소에서 아래 키워드를 점검해야 함
    - `atreides`
    - `cogitor`
    - `fedaykin`
    - `fremen`
    - `futar`
    - `gesserit`
    - `ghola`
    - `harkonnen`
    - `heighliner`
    - `kanly`
    - `kralizec`
    - `lasgun`
    - `laza`
    - `melange`
    - `mentat`
    - `navigator`
    - `ornithopter`
    - `phibian`
    - `powindah`
    - `prana`
    - `prescient`
    - `sandworm`
    - `sardaukar`
    - `sayyadina`
    - `sietch`
    - `siridar`
    - `slig`
    - `stillsuit`
    - `thumper`
    - `tleilaxu`
- npm에서는 비인가 배포 여부를 감사해야 함
  - 승인되지 않은 publish, 버전 변경, 새로 추가된 설치 훅을 확인해야 함
- 클라우드 환경에서는 접근 로그를 재검토해야 함
  - 비정상적인 비밀정보 접근, 토큰 사용, 새로 발급된 자격 증명을 추적할 필요가 있음
- 엔드포인트와 러너에서는 관측된 유출 인프라와 파일 접근 흔적을 추적해야 함
  - **`audit[.]checkmarx[.]cx`** 로의 외부 연결을 찾을 필요가 있음
  - 평소 사용하지 않는 환경에서 **Bun 실행**이 있었는지 확인해야 함
  - `.npmrc`, `.git-credentials`, `.env`, 클라우드 자격 증명 저장소, `gcloud`, `az`, `azd` 접근 흔적을 살펴봐야 함
  - `/tmp/tmp.987654321.lock` 존재 여부와 `~/.bashrc`, `~/.zshrc` 수정 여부도 확인해야 함
- GitHub Actions에서는 승인되지 않은 workflow 생성 여부를 검토해야 함
  - 임시 브랜치에서 workflow가 만들어졌는지 확인이 필요함
  - `format-results.txt` 같은 artifact가 생성되거나 다운로드되었는지도 점검해야 함
- 장기적으로는 향후 공급망 사고의 **피해 반경 축소**가 필요함
  - 토큰 권한 범위를 줄이고 가능하면 단기 수명 자격 증명을 사용해야 함
  - 패키지 생성 및 배포 권한을 제한하고 GitHub Actions 권한을 강화해야 함
  - 불필요한 artifact 접근을 비활성화하고, 정상 릴리스 절차 밖에서 생긴 공개 저장소나 workflow 변경을 모니터링해야 함

### 침해 지표
- ## 악성 패키지
  - [`@bitwarden/cli2026.4.0`](https://socket.dev/npm/package/@bitwarden/cli/overview/2026.4.0)
- ## 네트워크 지표
  - `94[.]154[.]172[.]43`
  - `https://audit.checkmarx[.]cx/v1/telemetry`
- ## 파일 시스템 지표
  - `/tmp/tmp.987654321.lock`
  - `/tmp/_tmp_&lt;Unix Epoch Timestamp&gt;/`
  - `package-updated.tgz`

## Comments



### Comment 56191

- Author: neo
- Created: 2026-04-24T10:11:37+09:00
- Points: 1

###### [Hacker News 의견들](https://news.ycombinator.com/item?id=47876043) 
- **최소 릴리스 대기 기간**을 두는 것보다 더 나은 방어책이 있는지 궁금함  
  `.npmrc`에 `min-release-age=7`만 넣었어도, 약 **19시간 전** 올라왔다가 악성으로 드러난 `@bitwarden/cli 2026.4.0`을 받은 334명은 피할 수 있었을 것 같음  
  비슷하게 `axios`, `ua-parser-js`, `node-ipc` 사례에도 꽤 잘 맞고, `event-stream`처럼 오래 잠복한 경우엔 못 막아도 대부분의 급성 공급망 공격엔 효과가 있어 보임  
  설정 예시로 npm/pnpm/bun/uv 각각에 대기 시간을 넣는 방법이 있고, 원클릭으로 점검·적용하는 도구가 없어서 직접 [https://depsguard.com](https://depsguard.com)을 만들었음  
  비슷한 아이디어의 [https://cooldowns.dev](https://cooldowns.dev)도 방금 확인함
  - **Aikido safe-chain**을 쓰고 있음  
    최소 릴리스 대기 기간만 거는 게 아니라, npm/uv 등을 감싸는 래퍼로 설치 전에 각 의존성을 상용 **취약점 데이터베이스**와 대조해 알려진 문제나 의심 신호를 검사해 줌
  - **쿨다운** 아이디어는 좋은데, 아무도 바로 업데이트하지 않았다면 이 공격이 과연 잡혔을지도 궁금함  
    현실에선 늘 누군가는 즉시 업데이트하겠지만, 이런 사고가 드러나는 과정 자체가 빠른 업데이트 사용자들에 기대는 면이 있어 보임
  - **backend나 CLI 도구를 NPM에 두지 않는 것**부터 시작하는 편이 낫다고 봄
  - 새로 설치할 때는 그렇다 쳐도, 기존 의존성은 **patch 버전으로 pin**하고 **sha를 고정**하면 되지 않나 싶음
  - 이런 공격은 대개 **upstream source**까지 들어가지 않아서, [https://www.chainguard.dev/libraries](https://www.chainguard.dev/libraries)처럼 **소스에서 빌드**하는 방식이면 대략 98%는 막을 수 있음  
    레지스트리 바이너리를 그대로 당겨와야 한다면 쿨다운으로 위험을 조금 낮출 수 있음  
    GitHub 쪽까지 침투한 긴 꼬리 사례는 커밋·메인테이너 휴리스틱과 **AI 기반 코드 변경 분석**을 돌리고, 이상 징후가 있으면 사람이 검토하는 조합이 필요해 보임  
    참고로 여기서 일하고 있음

- 이번 사고는 **빌드 파이프라인이 탈취**돼서 오염된 패키지가 배포된 게 핵심임  
  그래도 업무상 중요한 걸 npm에 얹고 있다면 의존성은 꼭 **pinning**하는 편이 낫다고 봄  
  많은 개발자가 lockfile이면 충분하다고 여기지만, `^` 범위가 남아 있으면 lockfile 갱신 시 내가 명시적으로 고르지 않은 새 버전을 끌어올 수 있음  
  회사 존립에 영향 줄 수 있는 시스템이라면 이 정도 번거로움은 감수할 가치가 있음
  - 반대로 생각하면, 나중 버전에서 **보안 취약점이 수정**됐을 때는 시스템이 그걸 자동으로 받아 적용해 주는 게 이상적이기도 함

- [https://github.com/doy/rbw](https://github.com/doy/rbw)는 **Bitwarden CLI의 Rust 대안**임  
  Rust 생태계도 점점 npm처럼 크고 깊은 의존성 트리로 가는 느낌이 있지만, 그래도 JavaScript에서 흔한 경우보다 신뢰해야 할 작성자 수는 훨씬 적은 편임
  - [https://github.com/doy/rbw/blob/main/Cargo.toml#L16](https://github.com/doy/rbw/blob/main/Cargo.toml#L16)를 보면 여기도 **의존성은 꽤 많음**  
    그래도 적어도 버전은 pin되어 있음
  - **Firefox 내장 비밀번호 관리자**를 쓰는 데 단점이 있는지 궁금함
  - 다들 Rust를 더 안전하다고 보면서도, **의존성을 통해 멀웨어를 끌어올 위험**이 크게 늘어난 건 너무 쉽게 무시하는 듯함
  - `rbw + vaultwarden` 조합이면 **self-hostable Rust 버전의 Bitwarden**처럼 굴러가서 꽤 괜찮음
  - 이런 일 때문에 더 많은 소프트웨어가 **.Net처럼 서드파티 의존성 없이도 대부분 해결되는 스택**으로 갈 수도 있겠다고 봄  
    반대로 언어 표준 라이브러리에 기능을 더 많이 넣는 쪽으로 갈 수도 있음

- Bitwarden **CLI 경험이 아주 나빴음**  
  `bw list`를 실행했더니 비밀번호 이름만 나올 줄 알았는데, 실제로는 **비밀번호와 현재 TOTP 코드까지 전부** 보여줬음  
  더 무서운 건 서버에 ssh로 들어가 tmux 안의 weechat를 열어 보니, `bw` 명령의 전체 내용이 **weechat 입력 히스토리**에서 접근 가능했다는 것임  
  왜 그런지 전혀 모르겠고, tmux와 weechat 세션을 넘어 계속 남아 있었고 서버를 재부팅해야만 사라졌음  
  그 뒤로 `bw` CLI는 바로 지웠고 다시 설치할 생각도 없음  
  참고로 터미널은 ghostty를 씀
  - 이건 본 주제와 상관없는 **불평에 가까움**
  - CLI를 써보려다가 **JavaScript 기반**인 걸 보고 접었음
  - 정말 이상한 일임  
    weechat에 `bwcli` 확장이라도 있는 건지 궁금하고, Bitwarden에 CLI가 있는지도 이번에 처음 알았음  
    나는 로컬에서 keepass를 씀

- CLI는 안 써봤지만 **브라우저 플러그인**은 쓰고 있음  
  이게 뚫리면 정말 큰일인데, 뭘 해야 막을 수 있을지 모르겠음  
  검증된 **구버전**을 계속 쓰는 게 답인지 고민됨  
  내 삶의 상당 부분이 이 비밀들이 비밀로 남는 데 달려 있다는 사실이 새삼 기묘하게 느껴짐
  - **통합 지점**이 많아질수록 공격면도 커짐  
    그래서 비밀번호 관리자 **브라우저 확장**은 아예 쓰지 않음  
    예전에 브라우저 연동에서 보안 문제가 있었던 제품을 본 뒤로 완전히 피하게 됐고, iOS 통합은 상대적으로 더 믿지만 그래도 경계함
  - **쿨다운**은 기본값으로 어디에나 들어가야 한다고 봄  
    개발용 패키지 매니저, OS 패키지 매니저, 브라우저 확장, 독립 앱의 자동 업데이트까지 전부 포함해서 말임  
    Socket 같은 회사가 악성 업데이트를 잡아낼 시간을 벌어야 하는데, 모두가 게시 몇 분 만에 내려받으면 그런 탐지 자체가 무의미해짐
  - 내 디지털 자산 중 가장 소중한 **이메일과 Bitwarden 계정**은 항상 몸에 지니는 **Yubikey** 하나와 다른 지역에 둔 백업 키 하나로 보호하고 있음  
    이런 구성을 강력히 추천함  
    제목 보고 좀 식겁하긴 했지만, 편집증으로 갈 정도는 아니면서 합리적으로 할 수 있는 건 다 하고 있다고 느낌
  - **브라우저 플러그인** 대신 데스크톱 앱이나 웹 vault를 직접 쓰면 됨
  - 막는 방법은 간단히 말해 이 둘임  
    [https://cooldowns.dev](https://cooldowns.dev)  
    [https://depsguard.com](https://depsguard.com)  
    두 번째 건 내가 관리하고 있고, 첫 번째를 미리 알았으면 굳이 만들지 않았을 듯함  
    둘 다 거의 같은 일을 하고, 내 쪽은 Rust를 써서 약간 과한 편임

- 여기서 가장 중요한 건 **npm install만으로 충분했다**는 사실임  
  침해 지점이 `preinstall`이면, 설치 후 검사하자는 통념은 바로 무너짐  
  그 시점엔 이미 페이로드가 실행될 기회를 얻었기 때문임  
  이건 **에이전트, CI, ephemeral sandbox** 환경에서 더 흥미로운데, 노출 시간이 짧아도 설치가 자동으로 반복되면 충분히 당할 수 있음  
  또 하나 주목할 건 이 페이로드가 비밀정보만 노린 게 아니라 **AI 툴링 설정**도 겨냥했다는 점임  
  셸 프로필 변조가 다음 코딩 어시스턴트가 읽어갈 컨텍스트를 오염시키는 경로가 될 가능성도 꽤 현실적임  
  이 관점은 AgentSH 작업과 함께 [https://www.canyonroad.ai/blog/the-install-was-the-attack/](https://www.canyonroad.ai/blog/the-install-was-the-attack/)에 더 길게 적어둠
  - 설치 후 패키지를 검사하는 사람은 사실상 없고, **npm install 스크립트**만 특별히 문제 삼는 건 여러 번 반박된 주장이라고 봄  
    어차피 결국 실제 바이너리를 실행하게 됨  
    그리고 정말 따지자면 설치 전에 패키지를 직접 받아 검사할 수도 있는데, 설치 프로그램의 동작 보장과 범위를 깊이 이해하지 못한다면 악성 코드를 내려받고 풀어놓는 과정을 어설프게 신뢰하는 쪽이 더 이상함

- **러시아 로캘 kill switch**라니, 대담하면서도 비겁해 보임
  - 더 나쁜 건 이게 진짜 흔적인지, 아니면 **false flag**인지조차 알 수 없다는 점임
  - `Discretion is the better part of valor` 같은 온갖 격언이 다 떠오름  
    요컨대 **자기 발등은 찍지 않는다**는 태도처럼 보임
  - 그 자체로 **결정적 증거**는 아님  
    `Vault7` 유출에서도 NSA와 CIA가 출처를 흐리려고 이런 흔적을 일부러 남긴다는 내용이 있었고, 다른 국가 행위자들도 충분히 쓸 법한 기법임
  - 다른 나라가 건 **협박성 공작**처럼도 보임
  - npm publish GitHub CI 작업에서 누가 로캘을 그렇게 맞춰 두겠냐 싶음  
    너무 노골적인 **오도용 흔적** 같지만, 동시에 국가 행위자가 개입했다는 인상을 강하게 주긴 함

- **KeePass** 사용자로 살면 이런 스트레스가 훨씬 적음  
  지난 5년만 해도 로컬 인프라에 KeePass를 써서 여러 보안 사고를 피했음
  - 이번 건 **vault 자체가 아니라 접근 도구**가 문제였음  
    KeePass용 접근 도구라고 해서 이런 문제가 불가능한 건 아닌데, 무엇이 다르다는 건지 잘 모르겠음
  - 비밀번호를 **인프라와 휴대폰에서 함께 접근**해야 하는데, KeePass로 그걸 어떻게 해결하는지 궁금함  
    불가능하다고 생각해 왔지만 솔직히 깊게 파보진 않았음
  - 자기 인프라를 굴릴 수 있는 사람에겐 좋겠지만, **stress free**라는 표현을 평균 사용자에게까지 적용하긴 어려움
  - 단일 파일 방식은 알겠는데, 현실적으로 **동기화와 충돌 해결**을 어떻게 하는지 궁금함  
    두 기기가 오프라인 상태에서 각각 비밀번호를 추가한 뒤 다시 온라인이 되면 어떻게 처리하나 싶음
  - KeePass에서 아직 감을 못 잡은 건 **클라우드 백업**임  
    백업을 암호화하면 그 암호는 어디에 저장하고, 또 클라우드 제공자 비밀번호는 어디에 저장해야 하나 싶음

- 이번 공격에서 특히 인상적인 건, 공격자들이 **GitHub가 다운되지 않은 타이밍**과 정확히 맞춰야 했다는 점임
  - GitHub는 최근에 **가동 시간 이슈**가 좀 있었음  
    [https://mrshu.github.io/github-statuses/](https://mrshu.github.io/github-statuses/)

- 그래서 나는 **서드파티 비밀번호 관리자**를 아예 쓰지 않음  
  보안, 업데이트, 백업 같은 걸 제대로 해줄 거라고 계속 믿어야 하기 때문임  
  직접 **stateless 비밀번호 생성기**를 만들었고, 덕분에 기기 간 데이터 백업이나 동기화가 아예 필요 없음  
  아주 길고 강한 마스터 비밀번호와 서비스명, 사용자명을 넣으면 적절한 파라미터의 **scrypt 해시**를 돌려 브루트포스를 사실상 불가능하게 만드는 방식임  
  중요한 계정엔 **2FA**도 함께 씀
