はじめに
英語のスカウトDMが来ました。よくある「うちのプロジェクトで働きませんか」という文面です。返信はしませんでしたが、そこから北朝鮮系の脅威アクターが実際に何をやっているのかを調べ始めて、驚いたことがひとつあります。
この記事では、公開されているインシデントレポートから将軍様の攻撃経路を4つに整理します。守る側が実際に何をすればいいのかまで落とします。Web3の話に見えますが、後半の3つ目と4つ目は普通の業務インフラ設計にそのまま効きます。
参考文献
先に一次情報を置いておきます。この記事はここに書かれている内容の整理です。
結論:破られているのは「鍵の外側」だけ
整理した結果がこれです。
入口は3つ、そして最後に「署名する瞬間の画面を差し替える」という一番えげつないやつがあります。共通しているのは、どれも鍵そのものには触っていないこと。最終的に鍵は、所有者本人の手で、正規の手順で使われます。これが厄介なところで、鍵の強度をいくら上げても防御にならないんです。
順に見ていきます。
入口1|偽の求人で開発者の端末に入る(Contagious Interview)
一番数が多い入口がこれです。LinkedInやGitHubで開発者に接触し、「コーディング課題」と称したリポジトリを渡す。候補者が npm install して実行した時点で終わりです。
怖いのは準備のほうです。ダミー企業には、まともに見えるWebサイトとアクティブなGitHub Organization、さらにGlassdoorのプロフィールまで用意されている。最近は生成AIでペルソナと面接プロセスそのものを補強する動きも報告されています。
「まずこのリポジトリをローカルで動かしてください」は、採用フローの体をなしているぶん、疑う理由を作りにくい構造になっています。正規の手順のフリをしているものほど、手順の途中では止まれません。
私のところに来たDMも、文面だけ見れば不自然なところはありませんでした。リポジトリを渡される段階まで進んでいたら、自分が確実に踏みとどまれたかというと、正直自信はないです。
入口2|npmの上流を汚染する(axios / Mastra)
開発者を1人ずつ釣るのは効率が悪い、と判断したのかどうかは分かりませんが、最近は上流のパッケージを直接汚染する方向にはっきりシフトしています。
axios(2026年3月31日)
週1億ダウンロードを超えるHTTPクライアントが汚染されました。メンテナのnpmアカウントが乗っ取られ、2026年3月31日の00:21から03:20 UTCのあいだに、バージョン1.14.1と0.30.4へ plain-crypto-js という隠し依存が差し込まれています。この依存のpostinstallスクリプトがインストール時に自動実行され、攻撃者のインフラから次段を取得する。最終的にWindows・macOS・Linuxを横断するバックドアが展開されます。
Googleはこれを金銭目的の北朝鮮系クラスタUNC1069に、MicrosoftはSapphire Sleetに帰属させました。汚染の窓は3時間ほどでしたが、StepSecurityは12,000を超えるプロジェクトで異常なC2通信を検知したと報告しています。
Mastra(2026年6月17日)
AIエージェントのフレームワークです。コントリビューターのアカウントが乗っ取られ、01:15から02:36 UTCの約81分で140を超えるパッケージが再公開されました(正確な件数は報道により144件から145件で揺れています)。中身のコードは正規版とバイト単位で同一で、変更点は easy-day-js という依存が1つ増えていることだけ。dayjsのタイポスクワットです。
このペイロードは、インストールフックでTLS検証を無効化し、生のIPアドレスから第2段を取得して、166種類の暗号資産ウォレット拡張機能を列挙して回ります。
ここで注目したいのは起点です。侵害されたメンテナはMastraの現職エンジニアで、乗っ取られたLinkedInアカウントから接触を受け、通話をして、リンクを踏んだ結果として端末を取られています。入口1と入口2は地続きなんです。 1人の開発者を釣った結果が、スコープ全体の汚染になる。
そして一番タチが悪いのは、この2件のどちらでも、被害者側が何も間違えていないことです。npm install しただけなので。
入口3|IT労働者として普通に入社する
これはもうハックですらありません。身分を偽造する、あるいは欧米圏の人物の身分を金銭で借りて、リモート開発者として正規に採用される。給与も受け取りながら、内部から鍵とインフラに触ります。
研究者が囮の暗号資産スタートアップを作って検証したところ、実際に3人を採用するところまで行けたという報告があります。ブロックチェーン調査者のZachXBTは、2024年6月以降だけで25件以上の暗号資産プロジェクトへの潜入を追跡しており、1つのグループが21人規模で複数プロジェクトに同時に入り込んでいたケースも報告しています。Chainalysisは、2025年の被害額が跳ね上がった一因として、取引所・カストディアン・Web3企業へのIT労働者の潜入が初期アクセスと横展開を加速させた点を挙げています。
この経路には、技術的な検知ポイントがほぼありません。認証は通っているし、権限も正規に付与されているし、コードレビューも普通に受けています。ここが業務インフラ設計に効いてくるところで、要は「採用を通過した人間は信用できる」という前提のうえに権限設計を積んでいると、その前提ごと持っていかれます。
事例|Bybitの15億ドルは、署名画面を差し替えられて出ていった
2025年2月のBybitの件が、技術的には一番えげつないと思います。何がえげつないかというと、Bybitは一度も侵入されていないことです。
破られたのは、Bybitが使っていたマルチシグウォレットのUI提供元、Safe{Wallet}側の開発者端末でした。Safe{Wallet}の内部調査によれば、経路はこうです。
- 開発者(Developer1)がソーシャルエンジニアリングで端末を侵害される
- 端末に仕込まれたマルウェアから、有効なAWSセッショントークンを奪取する
- 奪ったセッションでMFAを迂回し、WebインターフェースがホストされているS3上のJavaScriptを改ざんする
- 改ざんコードはBybitのコールドウォレットアドレスだけを標的に、待機する
結果として、Bybitのマルチシグ署名者たちは「正常な送金トランザクション」の画面を見ながら、実際にはコントラクトの実装を差し替えるトランザクションに署名しました。通常の呼び出しが delegatecall に化けており、これは実質的にウォレットの制御権を攻撃者のコントラクトへ渡すものです。FBIはこの攻撃をTraderTraitorとして北朝鮮に帰属させ、被害額は約15億ドルとされています。
パスワードも破られていないし、MFAも破られていないし、鍵も漏れていない。奪われたのは「まだ有効なセッション」と「配信されるJavaScript」の2つだけです。
数字で見ると、この1国だけ比率がおかしい
Chainalysisによれば、北朝鮮系アクターが2025年に盗んだ額は少なくとも20.2億ドルで、前年比51%増です。2024年の13億ドルから6.8億ドル増えており、この20.2億ドルのうち15億ドルがBybit1件です。累計は67.5億ドルと推計されています。
2026年はさらに比率が極端です。TRM Labsによれば、4月時点で暗号資産ハック被害額全体の76%を北朝鮮1国が占めており、しかもその内訳はDrift Protocol(4月1日、2.85億ドル)とKelpDAO(4月18日、2.92億ドル)のわずか2件、計5.77億ドルです。件数ベースでは全体の3%にすぎません。
シェアの推移も置いておきます。2022年22%、2023年37%、2024年39%、2025年64%、2026年は4月時点で76%。米財務省は、これらの資金が大量破壊兵器および弾道ミサイル計画の収益源になっていると明言しています。
守る側の実務1|依存関係に誰が触れるか
ここから対策です。まず依存関係から。
axiosの汚染窓は約3時間、Mastraは約81分でした。逆に言えば、新しく公開されたバージョンをすぐに取らないだけで、この手の汚染はかなりの確率ですり抜けられます。汚染バージョンは数時間で検知・削除されることが多いからです。
各パッケージマネージャに、この「寝かせ」の設定が入っています。
npm install --min-release-age=3 axios
pnpmでは minimumReleaseAge を分単位で指定します。10.16で追加された設定で、現行のドキュメント上の既定値は1440分、つまり1日です。Yarnは4.10で npmMinimalAgeGate が入りました。こちらも分単位の数値で指定します。
手元のnpm 11.12.1で挙動を確認しました。まず、--before との併用はできません。
$ npm install --dry-run --before=2026-01-01 --min-release-age=7 lodash
npm error Exit prior to config file resolving
npm error cause
npm error --min-release-age cannot be provided when using --before
そして、これが私がハマったところです。効きを確かめようとして寝かせ期間を極端に長くしたら、こうなりました。
$ npm install --dry-run --min-release-age=3650 axios
add axios 0.14.0
added 5 packages in 1s
10年寝かせろと言ったので、10年以上前のaxiosが入ってきました。当然といえば当然なんですが、この設定は「安全側に倒す」のではなく「時間軸を過去にずらす」ものなので、長くしすぎると今度は既知の脆弱性を踏みます。数日程度が現実的な落としどころです。
インストール時のスクリプト実行そのものを止める手もあります。
npm ci --ignore-scripts
axiosもMastraも、悪意あるコードの起動はインストールフックでした。ただしネイティブモジュールのビルドがこれで壊れるパッケージがあるので、CIで一括適用するなら事前に検証が要ります。
あとは基本ですが、npm install ではなく npm ci を使うこと。ロックファイルどおりに入り、package.json と食い違っていれば失敗してくれます。
守る側の実務2|署名する画面を信用できるか
Bybitの教訓を一般化すると、こうなります。
- 表示している層と、実際に署名される内容を、別々の経路で確認する
- ハードウェアウォレットの画面に出る最終的なトランザクションの中身を必ず読む。Webアプリ側の日本語の説明文は、攻撃者が書き換えられる場所にある
- 中身を確認せずに署名するblind signingを運用から禁止する
- 高額の承認は、承認者どうしが別の経路(画面ではなく、金額と宛先の読み上げなど)で突き合わせる
Web3をやっていない人には関係ない話に見えますが、「画面に出ている内容と、実際に実行される内容が一致している保証はどこにあるか」という問いは、管理コンソールでも社内の承認ワークフローでも同じです。
守る側の実務3|採用フローも攻撃面として扱う
入口1と入口3を踏まえると、採用フローはセキュリティの管轄です。
- 選考で渡されたコードは、使い捨てのVMかコンテナでしか動かさない。開発用の母艦で
npm installしない - 業務委託を含むリモート採用で、本人確認の手段を書面だけに依存しない
- 権限は入社時に一括で付与せず、段階的に広げる。とくに鍵・本番インフラ・パッケージの公開権限は分けて扱う
- オフボーディング時にnpmやGitHubの公開権限が残っていないかを棚卸しする
Mastraの件は、コントリビューターアカウント1つの侵害がスコープ全体の乗っ取りにつながりました。「もう使っていない古いアカウント」が生きていること自体がリスクです。
