エムスリーテックブログ

エムスリー(m3)のエンジニア・開発メンバーによる技術ブログです

ライブラリ脆弱性に対するAIトリアージの試み

お疲れ様です。エムスリーでセキュリティなどを担当している山本です。

最近は「生成AI x セキュリティ」にも関心を寄せており、色々と試していますので、その辺りの話をブログリレーの中で書いてみたいと思います。

テーマは「検出された少ないライブラリ脆弱性にどのようにAIを武器にして向き合っていくか」です。

脆弱性検出とその対処

システムが持つライブラリの脆弱性は、常にゼロにしておくのがもちろん理想です。 とはいえ、有名なライブラリからも常時脆弱性が発見されており、仮に作成当時完璧なシステムであったとしても時間が経てば対応が必要となります。

理想を言えば発見された脆弱性に対して全て即座に処置することが求められますが、現実としては次のような二段階で対処していきます。

  • 判定されたライブラリの脆弱性の危険性(ex. CRITICAL)を見ながらトリアージを実施し改善を求める<セキュリティチーム主導>
  • 各システムの開発メンバーに伝えてなんらかの対処をしてもらう<開発メンバー主導>

さらに具体的に言えばエムスリーでは隔週でエンジニアの間でセキュリティ定例が行われており、その議題の1つにこの話題があります。

最終的に全てがゼロになって、どんどん危険性の低い問題にも取り組めれば良いのですが、新たに発見される脆弱性への対処と相まって埋もれやすくなってしまいます。

とは言え、それでいいというわけにはいきません。最近は生成AIの力を借りられないかと模索しており、今回はその一例を紹介します。

脆弱性情報から脆弱性の実効性探索へ

脆弱性情報の収集と形式化

商用ツールや、例えばAmazon Inspectorのようなものはライブラリの脆弱性情報を検出できます。検出された脆弱性には脆弱性の番号(例えばCVE-XXXXのようなもの)が付与されています。その情報を生成AIに食わせます。

エムスリーではyamoryと呼ばれるツールを活用しています。 yamoryには各種の機能(CSPMやOS内の古いパッケージの検出)がありますが、ソースコードのリポジトリを食わせることによってパッケージ管理の仕組み(例えばGradleやnpmのことです)を解析して脆弱性のあるライブラリを自動的にリストアップした上で、各種脆弱性の危険度や詳細、対策を提示してくれます。

yamory.io

ですので、「yamoryの吐き出してきた情報 x 生成AI」というところから開始いたしました。

yamoryとの連携も完全に自動化できればよいのですがまずはお試しなので手動で実施しています。

トリアージの試み

もちろん、yamoryの判定にしろCVEの危険度数値にしろ、すでに一定のトリアージはなされています。

我々の作業を再掲いたします。

  • 判定されたライブラリの脆弱性の危険性(ex. CRITICAL)を見ながらトリアージを実施し改善を求める<セキュリティチーム主導>
  • 各システムの開発メンバーに伝えてなんらかの対処をしてもらう<開発メンバー主導>

ここでセキュリティチーム主導の部分は、yamoryの判定と人間の知識を加えてのものですが、現状では開発メンバー主導の部分でも再度の「トリアージ」が必要となります。 要するに「これがクリティカルだ」と言われても、今現在でそのシステムにおいてどの程度危険であるのか、まさに本日にでも攻撃されうるのか、というところはシステム依存となります。

従いまして「そのシステムドメスティックな情報」と「その脆弱性」の組み合わせで本来の危険度を知るところまでセキュリティチーム側でトリアージできれば、開発メンバー側は非常に楽になりそうです。

「脆弱性判定プロンプトを作れ」

そこで次のようなプロンプトを提示しました。

CVE-2025-7783脆弱性が存在するバージョンを使っているかどうかはすでに判定されている。この脆弱性がそれらの各種プロジェクトに対して適用可能か(すなわち利用可能な穴があるか、あるいは事実上塞がれているか)を判定することを行いたい。

そのためのチェック内容を示したプロンプトをmarkdownとして生成して欲しい。
攻撃可能性の大小を判定すること。

以下、CVEについての情報を示す。

https://nvd.nist.gov/vuln/detail/CVE-2025-7783
(以下略)

生成AIによって次のようなmarkdownが生成されました。

# CVE-2025-7783 脆弱性攻撃可能性判定チェックリスト

## 脆弱性概要

**CVE-2025-7783** は、form-dataライブラリがマルチパートフォームエンコードされたデータの境界値生成に`Math.random()`を使用することによる脆弱性です。

### 技術的詳細
- **影響ライブラリ**: form-data
- **問題箇所**: 境界値生成における予測可能な疑似乱数の使用
- **攻撃手法**: Math.random()の状態予測による境界値偽装とパラメータインジェクション
- **類似脆弱性**: undiciライブラリで発見された脆弱性と同様の手法

## 脆弱性成立の必要条件

プロジェクトが攻撃可能であるためには、以下の**すべての条件**が満たされる必要があります:

### 条件1: form-dataライブラリの使用 ✅/❌

(略)

### 条件2: ユーザー制御データの外部送信 ✅/❌

- [ ] ユーザー入力を含むform-dataリクエストを外部システムに送信
- [ ] ファイルアップロード機能でform-dataを使用
- [ ] Webhook送信でユーザーデータを含むform-dataを使用
- [ ] 外部API呼び出しでユーザー制御可能なデータを送信

**確認ポイント:**
- ユーザーがリクエストの一部フィールドを制御可能か
- 送信先システムで追加パラメータ注入による悪影響があるか
- 重複パラメータの処理方法(上書き vs 配列化)

### 条件3: Math.random()値の観測可能性 ✅/❌

#### 直接的な観測経路
- [ ] リクエストIDヘッダー(x-request-id等)でMath.random()使用
- [ ] エラーレスポンスでランダム値を露出
- [ ] ログファイルでMath.random()値を出力
- [ ] WebhookやCallback URLでランダム値を送信

#### 間接的な観測経路
- [ ] OpenTelemetryトレーシングIDでMath.random()使用
- [ ] セッションIDやトークン生成でMath.random()使用
- [ ] 分散トレーシングシステムでの相関ID
- [ ] デバッグ情報やメトリクスでのランダム値露出

**調査コマンド例:**
# Math.random()の使用箇所確認
grep -r "Math\.random" src/
grep -r "request.*id\|requestId" src/
grep -r "trace.*id\|traceId" src/

# ヘッダー生成箇所の確認
grep -r "x-request-id\|X-Request-ID" src/
grep -r "correlation.*id" src/

## 詳細調査手順

### 1. 依存関係の確認

# package.jsonの確認
cat package.json | grep -E "(form-data|axios|request)"

# lock fileの確認
grep -A5 -B5 "form-data" package-lock.json
grep -A5 -B5 "form-data" yarn.lock
grep -A5 -B5 "form-data" pnpm-lock.yaml

# 依存関係ツリーの確認
npm ls --depth=10 | grep form-data

### 2. コードベースでの使用箇所特定

# form-data使用箇所の検索
find . -name "*.js" -o -name "*.ts" -o -name "*.jsx" -o -name "*.tsx" | \
  xargs grep -l -E "(FormData|form-data|multipart/form-data)"

# Math.random()使用箇所の検索
find . -name "*.js" -o -name "*.ts" -o -name "*.jsx" -o -name "*.tsx" | \
  xargs grep -n "Math\.random"

# リクエストID生成箇所の検索
find . -name "*.js" -o -name "*.ts" -o -name "*.jsx" -o -name "*.tsx" | \
  xargs grep -n -E "(request.*[Ii]d|[Rr]equest.*ID|x-request-id)"

### 3. 外部通信の監査

(略)

### 4. ログ・レスポンス・ヘッダーの確認

(略)

実際のプロジェクトに適用

これを実際のプロジェクトごとに食わせてみます。

CVE-2025-7783_攻撃可能性判定チェックリスト.mdがある。
当該markdownを読みこみ、当プロジェクトについて脆弱性の利用可能性を判定せよ。
なお、別ツールによって当プロジェクトが該当バージョンのライブラリを使っていることはすでに指摘されている。

タスクは大きいのでいくつかのタスクに分割して順次実施するよう計画を立ててほしい。

生成AIは休むことを知りません。

チェックリストの内容を確認しました。
CVE-2025-7783は、form-dataライブラリがマルチパートフォームエンコードされたデータの境界値生成に`Math.random()`を使用することによる脆弱性です。

以下のタスク分割計画で順次実施します:

## タスク分割計画

### フェーズ1: 依存関係の調査

1. __form-dataライブラリの使用確認__

   - 直接依存・間接依存の確認
   - package.json、pnpm-lock.yamlの分析

### フェーズ2: コードベースの分析

2. __form-data使用箇所の特定__

   - FormData、multipart/form-dataの使用箇所検索
   - HTTPクライアント(axios、fetch等)での使用確認

### フェーズ3: Math.random()の調査

3. __Math.random()使用箇所の特定__

   - コードベース全体でのMath.random()使用確認
   - リクエストID生成等での使用確認

### フェーズ4: 外部通信・観測可能性の調査

4. __外部送信処理の確認__

   - ユーザー制御データの外部送信箇所特定
   - Webhook、API呼び出し等の確認

5. __Math.random()値の観測可能性確認__

   - ログ出力、レスポンスヘッダー等での露出確認
   - トレーシングID等での使用確認

### フェーズ5: 総合判定と対策提案

6. __脆弱性利用可能性の総合判定__
7. __緩和策の提案__

そして数分経って。

__フェーズ5: 総合判定と対策提案__

## CVE-2025-7783 脆弱性利用可能性判定結果

### 条件1: form-dataライブラリの使用 ✅ __該当__

- __axios@1.10.0/1.9.0__ → __form-data@4.0.0__ の間接依存が存在

(略)

### 条件2: ユーザー制御データの外部送信 ✅ __該当__

(略)

### 条件3: Math.random()値の観測可能性 ❌ __該当せず__

- __Math.random()の直接使用は確認されず__
- __UUID生成にはuuidV4()ライブラリを使用__(暗号学的に安全)
- IdempotencyKeyも安全なUUID v4を使用

## __総合判定: 脆弱性利用可能性は低い__

### 理由:

1. __form-dataライブラリは使用されているが__、Math.random()値の観測経路が存在しない
2. __攻撃者がMath.random()の状態を予測できないため、境界値偽装攻撃は実行困難
3. プロジェクトで安全なUUID v4を一貫して使用

スラスラと答えてくれました。

Clineから実行した例

人間による評価

この結果をそのまますぐに信用すべきかはまた別の話かもしれません。今回の場合は私がこの結果を一応当該プロジェクトについては確認し、信頼できそうであると判定しました。今回の例で言えば Math.random()が観測されないという理由だけによっても一旦は影響小といえるわけです。

念のためですが、現在攻撃されないからといっていつ攻撃可能な形にコードが変化するかは分かりません。ですから安全なバージョンに置き換えることが推奨されること自体には変化はありません。 ただし、やるべきことが多数ある中でのトリアージが行われたことで優先度づけが下がったわけです。

今回の場合には当該ライブラリをアップデートすること自体はそれほど難しいとは思えませんが、場合によっては各種の理由でアップデートが難しい場合はあります。そのような状態において「AIチェックで一旦問題はない」「問題はあるが、生成AIにコードを修正させてワークアラウンドで回避する」といった進み方ができることは、人力頼りだった時と比較して大きな差がありそうです。

今後やりたいこと

現在は私が手動でプロンプトを作ったりそれを食わせたりしています。 これだけでもCVE-2025-7783に対する汎用プロンプトとして、当該ライブラリが検出されたところで利用可能でしょうが、さらに言えば「プロジェクトに脆弱性のあるライブラリ検出(既存ツールで可能)」→「生成AIによって脆弱性情報のプロンプト化」→「生成AIによってプロンプト+プロジェクトのコードで危険度を判定させる」までを全自動でやらせることができれば、夢の世界が広がる気がしております。

そこまで頼って大丈夫なのかと言われれば確かにそれも疑問があります。 しかし、現実として日々発生する脆弱性に対する対処の労力を大幅に減らせる可能性は見えている気がします。

他にも試していること

他には会社全体の脆弱性情報や診断結果(例えばプラットフォーム診断結果など)をCSVとして生成AIに食わせることも実施しています。その中でも色々見出すものはありました。 全体の情報を取りまとめてくれるというのはもちろんですが、どこから実施するのかの議論や各脆弱性の分類、セキュリティチームとしての優先度づけのようなものが行われています。そこから派生したのが今回示した「脆弱性情報ごとにプロンプトを作ろう」です。

まだ何も試していませんが、クラウドの脆弱性情報(AWS Security Hubなど)との連携ができれば例えばterraformのような情報をチェックしたり、あるいは実際にクラウドに対してAIから接続させることで設定を確認させることで問題の有無を判定できるかもしれません。

もしそのあたりがうまく実用化できれば、脆弱性に押しつぶされそうな世界も未来は少し明るいかもしれません。

We are hiring!

エムスリーやそのグループ会社では常に素敵なエンジニアを募集しております! 興味あればぜひお越しください!

セキュリティ強化を実施中で、セキュリティエンジニアも募集中です。

jobs.m3.com

open.talentio.com

speakerdeck.com