ViteVenomの7件のnpmパッケージはVite風scopeとブロックチェーンC2でRATを配る
目次
TL;DR
影響 @uw010010/vite-tree、@vite-tab/tab、@vite-ln/build-ts、@vite-mcp/vite-type、@vite-pro/vite-ui、@vitets/vite-ts、@vite-ts/vite-ui を導入し、付属CLIを実行した開発端末とCI。Checkmarxがこの7件をViteVenomとして報告
発火点 悪意あるコードは bin/vite.js にあり、インストール時や通常のパッケージimportではなく、package.jsonの bin からこのCLIを実行したときに動く。
Tron、Aptos、Binance Smart ChainをC2(攻撃者の指令サーバーや設定取得経路)として使い、RAT(遠隔操作マルウェア)を取得する多段構成
対応 該当パッケージを削除し、ロックファイル、社内npmプロキシ、CIキャッシュ、198.105.127[.]210 への通信、.bashrc、.zshrc、.profile の不審な追記、GitHub・npm・クラウド・LLM APIキーの露出を確認
Checkmarx Zeroが、Viteエコシステムを狙う7件の悪意あるnpmパッケージをViteVenomとして報告した。
The Hacker Newsは2026年7月17日にこの件を取り上げている。
今回の名前は、@vite-pro/vite-ui、@vite-ts/vite-ui、@vitets/vite-ts のように、正規の @vitejs/* や @vitest/* に寄せている。
Vite本体やVitestがよく使われる現場のpackage.jsonでは、こうした名前は依存一覧に違和感なく紛れ込む。
Vite 8.0の記事で扱った通り、Viteはフロントエンドのビルドで広く使われ、Reactプラグイン、TypeScript変換、Rolldown移行、Vitest連携まで周辺パッケージの名前が多い。
攻撃者はそこに、公式scopeではないが公式scopeらしく映る名前を置いた。
Checkmarxが挙げた7件は次の通りだ。
| パッケージ | Checkmarx報告の悪意あるバージョン | Checkmarx集計のDL数 |
|---|---|---|
@uw010010/vite-tree | 3.4.2, 3.4.3, 3.6.1 | 1,070 |
@vite-tab/tab | 3.15.10 | 289 |
@vite-ln/build-ts | 5.15.10 | 252 |
@vite-mcp/vite-type | 6.44.1 | 239 |
@vite-pro/vite-ui | 2.5.10 | 200 |
@vitets/vite-ts | 1.5.10 | 194 |
@vite-ts/vite-ui | 6.44.1 | 176 |
この表はCheckmarxが7月14日に公表した既知版で、全バージョンを網羅しない。2026年7月19日に @vite-tab/tab@5.7.0 のtarballを確認すると、7月7日公開の bin/vite.js にcampaign marker(攻撃活動の識別子)*5-7 と別の難読化された自己実行コードが追加されていた。Checkmarx報告の 3.15.10 以外にも侵害版が存在するため、7件は表の版だけに絞らずパッケージ単位で除去する。
Checkmarxは、7件を2026年7月3日にnpmへ報告し、同日に削除されたとしている。
ただし、2026年7月19日にnpm registryを再確認すると、@vite-ln/build-ts だけが 0.0.1-security に置き換わり、悪意ある 5.15.10 はregistry上で404だった。残る6件では、上表の悪意あるバージョンのmetadataとtarballが引き続き取得できた。
「7件すべて削除済み」というCheckmarxの時系列と現在のregistry状態は一致しない。OpenSourceMalwareも、一部はnpmに残り、一部は削除またはsecurity placeholderになったとしている。削除済みと決めつけず、ロックファイル、社内npmミラー、CIキャッシュとnpm registryの両方を照合する。
@vitejsではなく@vite-proや@vite-tsを作る
正規のViteプロジェクトは @vitejs/plugin-react のように @vitejs/* scopeでパッケージを出している。
ViteVenomはこのscopeを直接乗っ取ったわけではない。
@vite-pro/*、@vite-ts/*、@vite-mcp/*、@vitets/* のように、近いscopeを新しく作っている。
7件すべてのscopeが @vitejs に似ているわけではない。
Checkmarxの分類では、@vite-pro、@vite-ts、@vite-mcp は @vitejs を想起させ、@vitets は @vitest と1文字違いだ。@vite-tab と @vite-ln は一般的なViteツール風で、@uw010010 はscope自体に直接のなりすまし先がない。@uw010010/vite-tree はパッケージ名側でViteに寄せている。
ここは、Rollupポリフィル風npmパッケージの件と似ている。
あちらは正規の rollup-plugin-polyfill-node にREADMEや語彙を寄せた。
今回も正規scopeの1文字違いではなく、Viteの周辺語で別scopeを作る。
単純なタイポスクワット(名前を似せた偽パッケージの手口)検知は正規名との類似を手がかりにするため、この型は検出から漏れる。
@vitets は @vitest の最後から1文字抜けたように読めるし、vite-ts というパッケージ名もTypeScript向け補助に映る。
Vitest APIサーバーのRCE記事では、Vitestの開発用APIを起点にローカル端末でコードを実行される脆弱性を扱った。
今回は脆弱性ではなく悪意あるパッケージだが、どちらも「開発中だけ使う道具」から開発端末の認証情報にアクセスできる。
bin/vite.jsがブロックチェーンから次段を引く
Checkmarxの解析では、7件すべての bin/vite.js に同じ悪意あるブロックが入り、違うのはcampaign markerだけだった。
コードは require や module を global.r、global.m のような短い別名に置き換え、文字列も配列indexで取り出す。
静的スキャンで child_process やURLを探すだけでは、肝心な値が隠れる。
発火後の流れは、インストール時スクリプト型とは違う。
preinstall や postinstall で即実行するのではなく、Vite CLI風の bin/vite.js が動いたタイミングで次段を取りに行く。npmに残るtarballのpackage.jsonでは、悪意ある版の main は ./dist/node/index.js、bin は vite または vite-tree から bin/vite.js への対応だった。通常のimport先から悪意あるファイルへの参照は確認できないため、「importだけで発火」ではなく「付属CLIを実行すると発火」が正確だ。
CheckmarxはViteVenomがChainVeilと同じ77KBのRATを配ると確認している。そのRATは process.env.CI がある場合、またはhostnameが localhost、RUNNERADMIN の場合に早期終了し、C2接続と窃取を行わない。標準的なCIでは最終段が止まる場合があるが、loader自体は実行され、自己ホスト型runnerで条件が常に成立する保証もないため、CIを無害と判定する材料にはならない。
flowchart TD
A["開発者がVite風パッケージを追加"] --> B["npm install<br/>install scriptは入口ではない"]
B --> C["付属CLIを実行<br/>bin/vite.jsが評価される"]
C --> D["Stage 2A<br/>Tron、失敗時はAptosから<br/>BSC transaction hashを取得"]
D --> E["BSC inputをXOR復号しeval<br/>共有Tier-2経由でRATを取得"]
C --> F["Stage 2B<br/>別のTron、失敗時はAptosから<br/>BSC transaction hashを取得"]
F --> G["BSC inputをXOR復号し<br/>detachedなnode -eで実行"]
G --> H["198.105.127[.]210の<br/>/$/bootからRATを直接取得"]
E --> I["RAT起動<br/>reverse shellと認証情報窃取"]
H --> I
ブロックチェーンC2では、遮断対象がドメインや1台のサーバーではなく、複数チェーン上の取引データになる。
攻撃者はTronのtransaction dataからBSC transaction hashを引かせ、BSCのinputに埋めた暗号化payload(悪意あるコード本体)を復号させる。
Tron側が失敗した場合はAptosのゼロ値transferの送信先に入れた同じBSC hashを使う。
Stage 2Aは復号した設定から共有Tier-2をたどる。Stage 2Bは別のTron/Aptos/BSC経路で得たloaderをdetachedな node -e で動かし、198.105.127[.]210 の /$/boot からRATをHTTPで直接取る。HTTPはStage 2Aの直後に試す単純なfallbackではなく、Stage 2B側の経路だ。
通常のC2なら、ドメイン停止、ホスティング停止、IP遮断でかなりの部分を止められる。
今回の方式では、payloadへのポインタが公開ブロックチェーン上に残る。
ウォレットやtransactionそのものを消すことはできないので、検知側はAPIアクセス、復号後の通信、RATの挙動まで追う。
Checkmarxは、ViteVenomと6月のChainVeilを同じSuccessKey攻撃者の系列と評価している。
根拠は、Tier-2のTron wallet、Aptos account、XOR key、最終RATが一致することだ。
ただしCheckmarx自身も、共有インフラを複数の攻撃者へ貸すサービス型の可能性は技術的には排除できないと書いている。
ここは「同一運用者の可能性が高い」までに留める。
2026年7月17日、OpenSourceMalwareはChainVeil/ViteVenomを北朝鮮Lazarus Group系のPolinRiderと結び付けた。根拠は、ChainVeilの2つのTron wallet、Aptos address、2つのXOR keyが、同組織が3月に公開したPolinRiderのIoCと完全一致することだ。The Hacker Newsも7月19日の更新でこの見解を追記した。 これはCheckmarxの「SuccessKey」という追跡名を否定するものではなく、別の調査者が、両者を含むより広いcampaign(一連の攻撃活動)の名前と国家帰属を評価したものだ。Checkmarx原典は国家帰属を示していないため、現時点では「OpenSourceMalwareの評価」として扱う。
npm v12やage gateの外側で動く
npm v12のallowScripts記事で整理した防御は、preinstall、install、postinstall、暗黙の node-gyp rebuild を未許可なら止める。
Mastraの easy-day-js やaxiosの plain-crypto-js のようなpostinstall発火型には対応できる。
ViteVenomの入口はそこから外れる。
install scriptではなく、インストールされたCLIが後から動く。
allowScriptsを有効にしていても、bin/vite.js 自体を実行する判断はnpmのinstall工程ではなく、プロジェクトや開発者の操作側にある。
release-age gateも効き方が限定される。
pnpm 11のminimumReleaseAge記事で書いた通り、公開直後の悪意あるバージョンを一定時間取らない設定は、数時間で削除される汚染版を避けやすくする。
今回の7件はCheckmarxによると2026年6月29日ごろから7月3日の狭い期間に公開されており、version range内に十分古い候補がある場合は初期取得を遅らせられる。pnpm 11の組み込み既定値は1,440分だがnon-strictで、条件を満たす候補がなければ新しい版へfallbackし得る。確実に失敗させるには minimumReleaseAgeStrict: true を明示する。
一方で、公開から数日経ったあとに検出されたパッケージや、既にロックファイルへ入ったバージョンは別の問題になる。
npmのstaged publishingも、正規メンテナの公開フローに承認点を入れる仕組みだ。
ViteVenomのように攻撃者が自分で新しいscopeとパッケージを作る場合、正規プロジェクト側のstaged publishingは関与しない。
provenance(出所証明)も同じで、「どのCIで作られたか」は分かっても、そのパッケージ名を使うべきかまでは判断しない。
パッケージ名を信頼してよいか、コードがいつ実行されるかを確認する。
@vitejs/* ではないVite風scopeが入っていないか、ViteやVitestに似た名前のCLIをpackage scriptから呼んでいないか、依存を追加したPRでnpm registryのpublisher、scope、homepage、repositoryが正規プロジェクトと一致しているかを、lockfile差分レビューの中で照合する。
影響確認はパッケージ名とdotfileから始める
ロックファイルに7件の名前がないかを確認する。
rg '@uw010010/vite-tree|@vite-tab/tab|@vite-ln/build-ts|@vite-mcp/vite-type|@vite-pro/vite-ui|@vitets/vite-ts|@vite-ts/vite-ui' package-lock.json pnpm-lock.yaml yarn.lock
npm ls @uw010010/vite-tree @vite-tab/tab @vite-ln/build-ts @vite-mcp/vite-type @vite-pro/vite-ui @vitets/vite-ts @vite-ts/vite-ui
@uw010010/vite-tree は、同じパッケージ内に無害な版と悪意ある版が混ざっている。
Checkmarxは 3.4.1 と 8.1.0 を無害な版、3.4.2、3.4.3、3.6.1 を悪意ある版としている。
ただし、これは「そのversionのtarballに同じ悪意あるコードがない」という意味だ。OpenSourceMalwareは7件が攻撃者管理下にあるとして、既知の悪意ある版以外も使用しないよう勧めている。@vite-tab/tab@5.7.0 の追加確認もあるため、latestや公表済みの版一覧に載らない侵害版が他にもあり得る。
主なViteVenom固有・共有IoCは次の通りだ。
| 種別 | 値 | 用途 |
|---|---|---|
| ファイル/marker | bin/vite.js / global.i='*5-*' | Checkmarx報告版7件に共通する入口。追加確認した @vite-tab/tab@5.7.0 は global.o='*5-7' |
| C2 | 198.105.127[.]210:443、:80 | WebSocket、upload、/$/boot |
| 関連C2 | 166.88.54[.]158:443 | ChainVeilのprimary C2。同じ運用者のIoCとしてCheckmarxが遮断を推奨 |
| 関連C2 | 23.27.202[.]27:443、:27017 | ChainVeilのtertiary C2とMongoDB。上と同じく共有運用者のIoC |
| 静的IoC | 4606094、?.? | Checkmarx報告版の難読化seedとBSC payload delimiter |
| XOR key | 2[gWfGj;<:-93Z^C、m6:tTh^D)cBz?NM]、ThZG+0jfXE6VAGOJ | Stage 2A、Stage 2B、HTTP loaderの復号鍵 |
| Tier-1 Tron | TCqf6ZkaQD84vYsC2cuu1jRwB6JveTaRrF | Stage 2AのBSC pointer |
| Tier-1 Tron | TFMryB9m6d4kBMRjEVyFRbqKSV1cV2NcpH | Stage 2BのBSC pointer |
| Tier-1 Aptos | 0x9d202c824402ca89e9aaccd2390b6f8b332ae743caa1469c695feb2781d56519 | Stage 2A fallback |
| Tier-1 Aptos | 0x3d2075f97b7b1e3234bd653779d21c605d7d8c6ec9c98d983880be5c7f4f9471 | Stage 2B fallback |
| BSC transaction | 0x5ab85abe6c67adb94322e5700a36915c38d1db1e604920da8aa4fcb530408af0 | Stage 2A payload |
| BSC transaction | 0xbcc976e1c8f3dfd93e146ff424836a9635ab36d991a54675635d7fdf30e60616 | Stage 2B payload |
| 共有Tier-2 Tron | TA48dct6rFW8BXsiLAtjFaVFoSuryMjD3v | ChainVeilと共通の最終RAT pointer |
| 共有Tier-2 Aptos | 0x533b2dbcaeff19cd1f799234a27b578d713d8fcaa341b7501e4526106483e0b1 | ChainVeilと共通のfallback |
2026年7月19日のオンチェーン照合でも、Stage 2AのTron dataをhex decodeして反転すると上表のBSC transactionになり、Aptos側のtransfer先とも一致した。BSC RPCでもStage 2A/2Bの両transactionと、データを持つinputを確認できる。ブロックチェーン上に記録が残ることと、現在もRAT配布やC2接続が成功することは同じではない。後者は安全上、接続試験していない。
該当が出た端末やCI runnerでは、パッケージ削除に加えてRATの痕跡と認証情報の露出も確認する。
Checkmarxは、198.105.127[.]210 をViteVenomのC2 serverとして挙げている。
同時に、detachedな node -e、隠しdirectoryの machineId、.bashrc、.zshrc、.profile への不審な追記を確認するよう勧めている。shell設定への注入は200文字以上の空白の後ろに隠される。
RATがreverse shell(攻撃者側へ接続してシェルを開く仕組み)、credential harvesting(認証情報の収集)、file exfiltration(ファイル窃取)、persistent backdoor injection(再起動後も残る裏口の追加)を持つためだ。
確認は、Node.jsプロセスとshell履歴のほかにdotfileと認証情報まで広げる。
Checkmarxが解析したRATは .bashrc、.zshrc、.profile、~/.ssh/ 全体、~/.npmrc を収集し、macOSではKeychain exportからOAuth tokenとパスワードも読む。さらに任意shell command、任意JavaScript、単一ファイルとディレクトリ全体のアップロード機能がある。GitHub token、npm token、クラウドCLI、Kubernetes、Vault、.env、LLM APIキー、SSH鍵を同じ端末で使っていたなら、露出済みとして扱い、隔離後に別の安全な端末から失効・再発行する。
ViteプロジェクトのCIで踏んだ場合は、ジョブの環境変数、self-hosted runnerの永続領域、社内npmプロキシ、Docker layer、pnpm storeも照合する。
参考
- Checkmarx Zero: Sequel to ChainVeil npm Malware Targets Vite Ecosystem
- The Hacker News: Seven Malicious Vite npm Packages Use Blockchain C2 to Deliver a RAT
- Checkmarx Zero: ChainVeil: A Malicious npm Supply Chain Attack by SuccessKey
- OpenSourceMalware: ChainVeil and ViteVenom are DPRK’s PolinRider Campaign