技術約12分で読めます

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-tree3.4.2, 3.4.3, 3.6.11,070
@vite-tab/tab3.15.10289
@vite-ln/build-ts5.15.10252
@vite-mcp/vite-type6.44.1239
@vite-pro/vite-ui2.5.10200
@vitets/vite-ts1.5.10194
@vite-ts/vite-ui6.44.1176

この表は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だけだった。 コードは requiremoduleglobal.rglobal.m のような短い別名に置き換え、文字列も配列indexで取り出す。
静的スキャンで child_process やURLを探すだけでは、肝心な値が隠れる。

発火後の流れは、インストール時スクリプト型とは違う。
preinstallpostinstall で即実行するのではなく、Vite CLI風の bin/vite.js が動いたタイミングで次段を取りに行く。npmに残るtarballのpackage.jsonでは、悪意ある版の main./dist/node/index.jsbinvite または vite-tree から bin/vite.js への対応だった。通常のimport先から悪意あるファイルへの参照は確認できないため、「importだけで発火」ではなく「付属CLIを実行すると発火」が正確だ。

CheckmarxはViteVenomがChainVeilと同じ77KBのRATを配ると確認している。そのRATは process.env.CI がある場合、またはhostnameが localhostRUNNERADMIN の場合に早期終了し、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記事で整理した防御は、preinstallinstallpostinstall、暗黙の 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.18.1.0 を無害な版、3.4.23.4.33.6.1 を悪意ある版としている。
ただし、これは「そのversionのtarballに同じ悪意あるコードがない」という意味だ。OpenSourceMalwareは7件が攻撃者管理下にあるとして、既知の悪意ある版以外も使用しないよう勧めている。@vite-tab/tab@5.7.0 の追加確認もあるため、latestや公表済みの版一覧に載らない侵害版が他にもあり得る。

主なViteVenom固有・共有IoCは次の通りだ。

種別用途
ファイル/markerbin/vite.js / global.i='*5-*'Checkmarx報告版7件に共通する入口。追加確認した @vite-tab/tab@5.7.0global.o='*5-7'
C2198.105.127[.]210:443:80WebSocket、upload、/$/boot
関連C2166.88.54[.]158:443ChainVeilのprimary C2。同じ運用者のIoCとしてCheckmarxが遮断を推奨
関連C223.27.202[.]27:443:27017ChainVeilのtertiary C2とMongoDB。上と同じく共有運用者のIoC
静的IoC4606094?.?Checkmarx報告版の難読化seedとBSC payload delimiter
XOR key2[gWfGj;<:-93Z^Cm6:tTh^D)cBz?NM]ThZG+0jfXE6VAGOJStage 2A、Stage 2B、HTTP loaderの復号鍵
Tier-1 TronTCqf6ZkaQD84vYsC2cuu1jRwB6JveTaRrFStage 2AのBSC pointer
Tier-1 TronTFMryB9m6d4kBMRjEVyFRbqKSV1cV2NcpHStage 2BのBSC pointer
Tier-1 Aptos0x9d202c824402ca89e9aaccd2390b6f8b332ae743caa1469c695feb2781d56519Stage 2A fallback
Tier-1 Aptos0x3d2075f97b7b1e3234bd653779d21c605d7d8c6ec9c98d983880be5c7f4f9471Stage 2B fallback
BSC transaction0x5ab85abe6c67adb94322e5700a36915c38d1db1e604920da8aa4fcb530408af0Stage 2A payload
BSC transaction0xbcc976e1c8f3dfd93e146ff424836a9635ab36d991a54675635d7fdf30e60616Stage 2B payload
共有Tier-2 TronTA48dct6rFW8BXsiLAtjFaVFoSuryMjD3vChainVeilと共通の最終RAT pointer
共有Tier-2 Aptos0x533b2dbcaeff19cd1f799234a27b578d713d8fcaa341b7501e4526106483e0b1ChainVeilと共通の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も照合する。

参考