2026 年 8 月 4 日の npm 大規模侵害で、手元の 45 リポジトリを調べました。被弾はゼロでした。困ったのはそこではありません。「攻撃が始まった 8 月 4 日 09:00 UTC より後に、自分は何を install したのか」が、どこを見ても分からなかったのです。lockfile も SBOM も「今どの版が入っているか」しか持っていません。結局フォルダの更新時刻から推定するしかありませんでした。そこから、取り込みの記録を残す CLI を作ることにするまでの話です。
設計ノートには構成図、利用者が使い始めるまでの流れ、CLI とレポートの画面イメージ、台帳のスキーマ、設計原則をまとめてあります。
記事全体の要約です。左上が現行ツールが持っていない「時間」のコンテキスト、右上が「異常なし」の顔をした偽陰性、下段が解決策としての取り込み台帳。
Wiz が公開した侵害パッケージ 443 件のリストと、手元の lockfile 26 本および node_modules の実体 995 個を突き合わせました。完全一致はゼロ。使っていたのは旧メジャーで、侵害されたのは新しい版のほうでした。
ただしこのマルウェアは preinstall フックで動きます。分かれ目は「危ない版が今 lockfile に載っているか」ではなく「攻撃開始以降に install を走らせたか」で、その記録がどこにも無い。lockfile にも SBOM にも「いつ入れたか」という列は存在しません。事故のときに推定でしか答えられないのは、けっこう嫌なものだなと思いました。
ついでに分かったこともあります。GitHub の Dependabot アラートを一括で引いたら 0 件でしたが、内訳を見ると 39 リポジトリ中 35 リポジトリでアラート自体が無効でした。「アラート 0 件」と「監視していないから 0 件」が、API の応答からは同じに見えたわけです。
自作スクリプトで 3 回の偽陰性を出しました。左が画面に出ていたもの、右が実際に起きていたこと。走査できなかった対象を黙って捨てると、出力は「異常なし」に化けます。
既存ツールも調べました。スキャナの層は Trivy や Grype や osv-scanner で完全に飽和していて、ここで戦う理由はありません。ただ「開発マシン単位」「取り込み経路を全部」「時刻と理由を焼き付ける」の 3 つが交差する場所は空いていました。
やることは単純で、外から入ってきたものを受け取ったその場で、日時と入手元と理由を 1 行残すだけです。