FutureVuls Blog

OWS 2026に登壇しました――CVEに出ない保守の停止と、依存を減らした実践

作成者: kotakanbe|Oct 27, 2026, 1:17:33 AM

2026年10月21日、CSS2026と同時に開かれた「OSSセキュリティ技術ワークショップ(OWS)2026」で招待講演を行い、午後のパネル討論にも参加しました。講演で伝えたかったのは、CVE(公表された脆弱性の番号)が 0 件でも、そのライブラリの保守が続いているとは限らない、ということです。講演の準備の中で、当社の OSS「uzomuzo」に新しい注意の表示をいくつか足しました。どれも人に確認を促す表示を添えるもので、判定の結果と、CI(自動テストやビルドの仕組み)を失敗にするかどうかは変えません。CI を止められるのは 1 年ぶりのバージョンに付く印だけで、それも使う側が --fail-on dormant-release を指定したときに限ります。

セッション情報

項目 内容
イベント OSSセキュリティ技術ワークショップ(OWS)2026(CSS2026 併催)
日時 2026年10月21日(水)
会場 アクトシティ浜松とオンライン(Zoom)
講演の枠 招待講演「AI時代のOSSとソフトウェアサプライチェーン」(座長:荒川玲佳さん、NTT)
講演 「CVEの死角から依存関係を減らすまで――uzomuzoとCode Dietの実践」11:00〜、C会場
パネル 「AIはOSSの守護者か、それとも破壊者か? ~フロンティアAI時代のOSSセキュリティ~」14:10〜15:50、A会場

講演は、4月の VulnCon 2026 で話した内容(登壇報告)を、その後の測定で更新したものです。

発表内容

出発点:Vault が使い続けているライブラリ

HashiCorp Vault は、アクセス制御の条件をコピーする処理(vault/acl.go)に mitchellh/copystructure を使っています。このライブラリは 2024年7月に GitHub でアーカイブされ(読み取り専用にされ)、作者は 2023年12月に「新しいリリースは二度と出さない」と宣言しました。私が確かめた範囲では CVE は 0 件です。

私が作った脆弱性スキャナ Vuls で Vault を調べると、Vuls は copystructure を読み取っていますが、copystructure については何も警告しません(他のライブラリの CVE は出ます)。Vuls は脆弱性データベースの記録と突き合わせる仕組みで、アーカイブや保守終了(EOL)の宣言はそのデータベースに載らないからです。脆弱性があると言いたいのではありません。今後見つかっても、作者は修正を出さないと宣言しています。

講演はこの例から、ライブラリと付き合う順に 3 つの問いを立てました。

① 選ぶ前:保守が止まったライブラリを見分けられるか

当社の調査(FutureVuls Foresight vol.2、2025年11月)では、国内 74 組織の本番環境で動く OSS 16,627 件のうち、分類できなかった 1,199 件を除いた中で 48.5% が、開発停滞か保守終了(予定を含む)でした。この値は「人の最後のコミットが半年以内か」などの条件で数えたもので、条件を変えれば値も変わります。

uzomuzo の scan コマンドは、ライブラリごとに最終リリースからの日数、人の最後のコミット、アーカイブされているか、既知の脆弱性の件数などを集め、置き換えを勧めるかどうかを根拠とともに出します。copystructure を渡すと、次のように「置き換えを勧める・開発停滞・アーカイブ済み」と出ます。

$ uzomuzo scan pkg:golang/github.com/mitchellh/copystructure@v1.2.0
🔴 replace  pkg:golang/github.com/mitchellh/copystructure@v1.2.0  Stalled · archived

この判定は、当社の脆弱性管理サービス FutureVuls にも取り込んでいます。2026年6月3日のリリースで、提供元が保守の終了を宣言していなくても開発が止まっている OSS を「実質 EOL」として出せるようになりました(リリースノート)。FutureVuls でスキャンしたサーバに入っているライブラリなら、ソフトウェア詳細の「ソフトウェアヘルス」でこの判定を確認できます。FutureVuls では、これに加えて、提供元が保守の終了を明示的に宣言しているもの(確定 EOL)も独自の仕組みで検知し、対応のタスクとして起票します。なお、この記事で紹介する注意の表示(メールのドメインの注意、1 年ぶりのバージョンの印、公開から 7 日以内のバージョンの注意)は、いまは uzomuzo のコマンドで使う機能です。

一方で、限界も見せました。2026年7月に RubyGems で、6〜7 年活動の無かったアカウント 2 つが乗っ取られた事件があります(SleeperGem)。そのアカウントの gem(Ruby のパッケージ。乗っ取り前のバージョン)を uzomuzo に渡すと ok と出ます。この gem は最後のリリースから約 6 年が経ち、既知の脆弱性も 0 件なので、「更新の要らない古い部品」と判定されたためです。乗っ取りの入口は放置されたアカウントでしたが、アカウントの状態はリリース日やコミット日には出てきません。ok は安全の保証ではないことを、画面を隠さずに示しました。

そのうえで、乗っ取りの前に出る手がかりを探しました。2026年5月の npm の node-ipc の事件(事後報告書、悪性パッケージの記録 MAL-2026-3744)では、悪性のバージョンを公開したアカウントの連絡先メールのドメインが、公開の 7 日前に登録し直されていました(登録者は非公開。報告者の issue)。この日付はリポジトリのリリース日やコミット日には出てきませんが、ドメインの登録記録(RDAP)には出ます。そこで「メールが npm の記録に初めて載った日より後に、そのドメインが登録し直されていたら注意を出す」表示を作り、講演当日の朝に公開した v0.9.0 に入れました(設計の記録 ADR-0030。標準では動かず、--maintainer-domain を付けたときだけ動きます)。当時この表示は無かったので、事件の前に気づけたという意味ではありません。一度に多数が乗っ取られた事件を除いた過去の単発の乗っ取り 103 件のうち、ドメインの登録記録を照合できた 44 件に当てると、当てはまったのは node-ipc の 1 件だけでした。この 1 件は、この判定を思いついたきっかけの事件そのものです。VS Code と npm cli の 2 つのプロジェクトの依存を記録したファイルに載る 2,017 パッケージに当てると、8 パッケージ(アカウント 7 つ、ドメイン 6 つ)に注意が付きました。ドメインの登録し直しには正当な理由もあるため、この 8 件は乗っ取りの候補ではなく、人が確かめる対象の数です。外れた注意がどれだけあるかは測っていません。

あわせて、npm で 1 年以上リリースの無かったパッケージに新しいバージョンが出たら、7 日間だけ印を付ける表示(--fail-on dormant-release を指定したときだけ CI を止める)も紹介しました。印を付けるのは npm だけで、7 日の根拠にした計測も npm だけです。OpenSSF(OSS のセキュリティ団体)の悪性パッケージの一覧から、一度に多数が乗っ取られた事件は 1 事件と数えて、npm の乗っ取り 85 事件を数えました。そのうち 1 年以上ぶりに出たバージョンだった 27 事件で、23 件は公開から 7 日以内にこの一覧に載りました。残りの 4 件は 7 日を過ぎてから載った(1 件は時刻不明)ので、その間は印も一覧の記録もありません。印で防げるわけではなく、一覧に載るまでの数日のつなぎです。

② 使っている今:Vuls で依存を減らした

Vuls の依存を減らした「Code Diet」の経過を話しました。最初はアーカイブ済みの go-homedir を Go の標準機能に置き換え、2 か所の書き換えで 15 分ほどで済みました。勢いで 9 個の依存を置き換える PR を作りましたが、サーバーに配って動かすスキャナの実行ファイルは、ほとんど小さくなりませんでした。外したはずの go-homedir など 4 個が、別のライブラリを通して入り続けていたためです。

効いたのは、別の切り口でした。Vuls のスキャナが Trivy から使うのは、依存を記録したファイル(package-lock.json など)を読む部分だけでした。それなのに、コンテナイメージやインフラの設定ファイルまで調べるための層を通して呼んでいたので、使わないコードまで実行ファイルに入っていました。この層を通さず、読み取る部品を直接呼ぶ形に変えると、スキャナだけの実行ファイルは 106.6 MB から 34.1 MB になりました。脆弱性の検出やレポートまで含む実行ファイルは 139.1 MB から 138.5 MB で、ほとんど変わっていません。

変更前後で、実在の OSS から集めた 129 個のファイル(13 種類の依存を記録したファイル 125 件と、JAR などのバイナリ 4 件)を読ませ、ライブラリの名前・バージョン・識別子(PURL)が 129 件すべてで一致することを確かめました。比べたのは読み取りの結果で、脆弱性の検出結果は比べていません。依存を外す順番を決める uzomuzo diet は、この作業の後に作った道具です。

③ 外に出した後:報告すれば外してもらえるのか

VulnCon で「報告済み」と紹介した 4 件の、半年後の状態です(2026年10月26日に GitHub で確認)。

報告先 報告したこと 今の状態
Trivy アーカイブ済みの go-homedir を置き換える PR 2026年4月24日に取り込み(出してから 19 日)
Grafana アーカイブ済みの GitHub Actions を 13 ファイルで使っていること(issue) 2026年9月15日に完了として close
HashiCorp Vault copystructure を含むアーカイブ済みの 3 つの依存(issue) open、コメント 0。3 つとも go.mod に残る
Next.js 保守終了の @vercel/kv を置き換える提案(discussion) open、コメント 0。package.json に残る

Grafana は、こちらの提案とは違う方法で、自社の共通の仕組みに移しました。報告がきっかけだったかは分かりません。Vault と Next.js にコメントが無い理由も、外からは分かりません。言えるのは、報告すれば直るとは限らず、直すかを決めるのは上流の保守者だということです。

自分の側も同じでした。Trivy では 19 日で取り込まれた go-homedir の置き換えを、Vuls では 7 か月進めていません。今すぐ困っていない変更は、外せと言っている本人でも後回しになります。だから講演の結論は「後から外せると当てにせず、ライブラリは選ぶ前に見る」にしました。

パネル討論

午後は、パネル討論「AIはOSSの守護者か、それとも破壊者か? ~フロンティアAI時代のOSSセキュリティ~」にも登壇しました。司会は須崎有康さん(情報セキュリティ大学院大学)で、面和毅さん、金井遵さん、川名のんさん、佐田淳史さん、高江洲勲さん、山内利宏さんと私の 7 人が登壇しました(プログラム)。

登壇後に入れた改良(uzomuzo v0.10.0)

講演の後、10月26日に公開した v0.10.0 で 2 つを足しました。

公開から 7 日以内のバージョンに注意を出す(PR #583、設計の記録 ADR-0031)。出たばかりのバージョンは、悪性でも一覧にまだ載っていないことがあります(講演で示した 27 事件のうち 23 件は、載るまで最長 7 日)。この間は「一覧に無い」ことが安全の根拠になりません。1 年ぶりの印は長く止まっていたパッケージにしか付かないので、更新が続いているパッケージにも効く表示として、渡したバージョンが公開から 7 日以内なら、詳細表示(--format detailed)に次のような注意を出すようにしました(途中を省略しています)。npm だけでなく、PyPI など公開日時が分かる他の配布元も対象です。

⚠ Release age: This version was published on 2026-10-21, 4 days before this scan. ...
If you can, wait until 2026-10-28 before adopting it, or check who published it.

この注意は判定・終了コード・--fail-on を変えません。7 日待てば防げるという表示でもありません。

同じ考え方は、依存の更新を自動で提案する道具の設定にもあります。Dependabot の cooldown(設定しなくても、バージョンの更新は 3 日待ちます)や、Renovate の minimumReleaseAge は、新しいバージョンの公開から指定した日数が経つまで、更新の PR を作りません。上の 27 事件では 23 件が 7 日以内に悪性パッケージの一覧に載ったので、7 日ほど待つ設定にしておけば、PR ができた時点でそのバージョンがすでに一覧に載っていて、uzomuzo などで見つけられる場合が多くなります。私たちの数字は、この設定を使う理由の 1 つになります。ただし、残りの 4 件は 7 日を過ぎてから載っており、待つだけでは防げない事件もあります。また、この数字は npm で 1 年以上ぶりにバージョンが出た事件だけを数えたものです。Dependabot の待ち時間は、セキュリティの更新には効きません。

メールのドメインの注意に、そのアカウントがこのパッケージを最後に公開した日を添える(PR #584)。npm がパッケージごとに持つ「公開できる人の一覧」には、記録の上ではそのパッケージを公開したことが無い人や、何年も前に公開したきりの人も載っています。先月公開したアカウントの注意と、公開の記録が無いアカウントの注意では、読み方が変わります。そこで、このパッケージの npm の記録に、そのアカウントが最後に公開した日付があれば書き、取得した記録に見つからなければそう書くようにしました。

おわりに

研究者の方が多い場で、測れたことと測っていないことを分けて話しました。uzomuzo の判定が人の判断とどれだけ合うか、放置されたパッケージほど乗っ取られやすいかは、まだ比べていません。uzomuzo は GitHub で公開しています。使ってみての指摘や issue をお待ちしています。