Modern Frontend CVEs

対象CVE: CVE-2026-69257

[緊急解説] Flowiseの深刻なSSRF脆弱性 (GHSA-c6xh-wv4j-ppv5) - フロントエンド開発者への影響と対策

FlowiseのSSRF保護に、IPv4-mapped IPv6アドレスを悪用したバイパス脆弱性が見つかりました。この脆弱性により、内部システムやクラウドメタデータサービスへの不正アクセスが可能となり、Flowiseを利用するアプリケーションのセキュリティに深刻な影響を及ぼす可能性があります。

はじめに:FlowiseとSSRF脆弱性とは?

Flowiseは、Node.jsベースで構築されたオープンソースのローコードAIツールで、Generative AIアプリケーションの開発を容易にします。AIチャットボットやワークフローの構築に利用されることが多く、フロントエンドアプリケーションのバックエンドとして活用されるケースも増えています。

SSRF (Server-Side Request Forgery) とは、サーバーが外部のURLにリクエストを送信する機能を悪用し、攻撃者が意図しない内部ネットワーク上のリソースや、クラウドのメタデータサービスにアクセスさせる攻撃手法です。通常、内部リソースは外部から直接アクセスできないため、SSRFはこれらのリソースに到達するための「踏み台」として悪用されます。

フロントエンドエンジニアとして、直接SSRFの脆弱性を作り込むことは稀かもしれませんが、バックエンド(Flowiseを含む)との連携において、ユーザーが提供するURLやパスの検証が不十分な場合、アプリケーションがSSRF攻撃に利用されるリスクを理解しておくことが重要です。

脆弱性の概要 (GHSA-c6xh-wv4j-ppv5 / CVE-2026-69257)

今回報告されたFlowiseの脆弱性 `GHSA-c6xh-wv4j-ppv5` (CVE: `CVE-2026-69257`) は、深刻度が「High」と評価されており、Flowiseに実装されているSSRF保護をバイパスできるというものです。具体的には、`v3.1.1` を含むそれ以前のすべてのバージョンが影響を受けます。

この脆弱性は、FlowiseのHTTPセキュリティモジュール (`httpSecurity.ts`) が、`IPv4-mapped IPv6アドレス` を適切に処理できないことに起因します。これにより、denyリスト(アクセスを禁止するIPアドレスリスト)による保護が機能せず、攻撃者はFlowiseサーバーから内部サービスやクラウドメタデータエンドポイントにリクエストを送信できるようになります。

この脆弱性は、以前にSSRF脆弱性 (CVE-2026-31829) が報告され、修正されたとされていた `v3.0.13+` のバージョンでも依然として存在している点が特に重要です。

根本原因:「Kindの不一致」が引き起こすバイパス

脆弱性の核となるのは、FlowiseがIPアドレスの検証に利用している `ipaddr.js` ライブラリの挙動と、`isDeniedIP()` 関数の実装方法にあります。Flowiseは、URLから解決されたIPアドレスがdenyリストに含まれているかをチェックする際に、以下のロジックを使用しています。

```typescript // packages/components/src/httpSecurity.ts - isDeniedIP() export function isDeniedIP(ip: string, denyList: string[]): void { const parsedIp = ipaddr.parse(ip); for (const entry of denyList) { if (entry.includes('/')) { try { const [range, _] = entry.split('/') const parsedRange = ipaddr.parse(range) // ⚠️ BUG: ここが問題! if (parsedIp.kind() === parsedRange.kind()) { // <-- BYPASS HERE if (parsedIp.match(ipaddr.parseCIDR(entry))) { throw new Error('Access to this host is denied by policy.') } } } catch (error) { throw new Error(`isDeniedIP: ${error}`) } } else if (ip === entry) { throw new Error('Access to this host is denied by policy.') } } } ```

このコードの `parsedIp.kind() === parsedRange.kind()` の部分が問題です。`ipaddr.js` は、`::ffff:127.0.0.1` のような `IPv4-mapped IPv6アドレス` を受け取ると、その `kind()` メソッドは `'ipv6'` を返します。しかし、denyリストに登録されている内部IPアドレスのCIDRエントリ(例: `127.0.0.0/8` や `169.254.0.0/16`)は、純粋なIPv4アドレスとして解析されるため、`kind()` は `'ipv4'` を返します。

結果として、`'ipv6' === 'ipv4'` は常に `false` となり、**IPv4のCIDRチェックが完全にスキップされてしまいます。** これにより、攻撃者はIPv4-mapped IPv6アドレスを悪用して、denyリストによる制限を迂回し、アクセス禁止とされているIPv4アドレスの内部サービスに到達することが可能になるのです。

攻撃シナリオ:なぜ危険なのか?

具体的な攻撃の流れは以下のようになります。

1. **攻撃者のDNS設定**: 攻撃者は自身の管理するドメイン(例: `evil.attacker.com`)に対して、AAAA DNSレコードを `::ffff:169.254.169.254` (AWSのメタデータサービスのアドレス) や `::ffff:10.0.0.1` (内部ネットワークのアドレス) など、ターゲットとしたい内部IPv4アドレスに対応するIPv4-mapped IPv6アドレスに設定します。

2. **Flowiseへのリクエスト**: 攻撃者は、FlowiseのHTTP NodeやAPI Chain、Document Loaderなどの機能を悪用し、`http://evil.attacker.com/` のようなURLへのリクエストをChatflowに組み込みます。

3. **DNS解決とバイパス**: Flowiseは `evil.attacker.com` をDNS解決し、結果として `::ffff:169.254.169.254` のようなIPv4-mapped IPv6アドレスを取得します。このアドレスが `isDeniedIP()` 関数に渡されますが、前述の「Kindの不一致」により、denyリストのIPv4 CIDRチェックが全てスキップされてしまいます。

4. **内部リソースへのアクセス**: 結果的に、Flowiseサーバーは、SSRF保護を回避して `169.254.169.254` (AWS IMDS) やその他の内部サービスへリクエストを送信してしまい、IAMロールのクレデンシャルや機密情報が攻撃者に窃取される可能性があります。これは、クラウド環境での認証情報を盗むための典型的なSSRF攻撃です。

この脆弱性は、`secureAxiosRequest()`, `secureFetch()`, `checkDenyList()` を利用するFlowiseの多くのコンポーネント(HTTP Node, ApiChain, Custom Function sandboxなど)に影響を及ぼします。

フロントエンド開発者への影響

直接的にはFlowiseが動作するバックエンド側の脆弱性ですが、Flowiseをバックエンドとして利用し、ユーザーからの入力(特にURL指定)を受け付けるチャットフローやアプリケーションを公開しているフロントエンドエンジニアは注意が必要です。

あなたの開発したフロントエンドアプリケーションが、意図せずSSRF攻撃のトリガーになってしまう可能性があります。これにより、Flowiseがデプロイされているクラウド環境(AWS, GCP, Azureなど)のメタデータサービスから認証情報が盗まれたり、Flowiseが稼働するサーバーと同じネットワーク内の他の内部システムにアクセスされたりするリスクがあります。

開発中のAIアプリケーションが、外部のデータソースやAPIと連携する際に、URLの指定をユーザーに許している場合、この脆弱性は深刻なセキュリティリスクとなり得ます。バックエンドのセキュリティ対策だけでなく、フロントエンド側での入力バリデーションや、安全なURL設計の重要性を改めて認識する必要があります。

対策と修正方法

この脆弱性に対処するためには、Flowiseを速やかに最新バージョンにアップデートすることが最も推奨される対策です。しかし、修正がリリースされるまでの間、または緊急対応として、以下の修正案を理解しておくことも重要です。

根本的な修正は、IPv4-mapped IPv6アドレスが適切にIPv4アドレスとして正規化されてから、denyリストのチェックが行われるようにすることです。`ipaddr.js` ライブラリには、このための便利なメソッドが用意されています。

`isDeniedIP()` 関数内で、IPアドレスを解析した後、それがIPv4-mapped IPv6アドレスであればIPv4アドレスに変換するロジックを追加します。これにより、denyリストのIPv4 CIDRエントリと正しく比較できるようになります。

```typescript export function isDeniedIP(ip: string, denyList: string[]): void { let parsedIp = ipaddr.parse(ip); // ✅ FIX: IPv4-mapped IPv6をIPv4に正規化してからチェック if (parsedIp.kind() === 'ipv6' && parsedIp.isIPv4MappedAddress()) { parsedIp = parsedIp.toIPv4Address(); } for (const entry of denyList) { if (entry.includes('/')) { try { const [range, _] = entry.split('/'); let parsedRange = ipaddr.parse(range); // デナイリストのエントリも同様に正規化を検討 (防御強化) if (parsedRange.kind() === 'ipv6' && parsedRange.isIPv4MappedAddress()) { parsedRange = parsedRange.toIPv4Address(); } if (parsedIp.kind() === parsedRange.kind()) { if (parsedIp.match(ipaddr.parseCIDR(entry))) { throw new Error('Access to this host is denied by policy.'); } } } catch (error) { throw new Error(`isDeniedIP: ${error}`); } } else if (ip === entry) { throw new Error('Access to this host is denied by policy.'); } } } ```

上記に加えて、Flowiseのデフォルトのdenyリストに `::ffff:0:0/96` を追加することで、すべてのIPv4-mapped IPv6アドレスを明示的にブロックすることも防御強化になります。これにより、たとえ正規化のロジックに別の不備があったとしても、この範囲のアドレスが許可されるのを防ぐことができます。

```typescript const DEFAULT_DENY_LIST = [ // ... 既存のエントリ ... '::ffff:0:0/96', // 全てのIPv4-mapped IPv6アドレスをブロック '::ffff:127.0.0.1/128', // 明示的なループバックマッピング // ... 他の明示的な mapped IPアドレス ... ]; ```

`resolveAndValidate()` 関数内でも、DNS解決結果として得られたアドレスを `isDeniedIP()` に渡す前に正規化することで、より早期に問題を検知し、多層防御を構築できます。

```typescript async function resolveAndValidate(url: string): Promise<ResolvedTarget> { // ... 既存のコード ... const records = await dns.lookup(hostname, { all: true }); for (const r of records) { let address = r.address; // DenyリストチェックのためにIPv4-mapped IPv6を正規化 if (ipaddr.isValid(address)) { const parsed = ipaddr.parse(address); if (parsed.kind() === 'ipv6' && parsed.isIPv4MappedAddress()) { address = parsed.toIPv4Address().toString(); } } isDeniedIP(address, denyList); } // ... 残りのコード ... } ```

まとめ

今回のFlowiseのSSRF脆弱性は、IPアドレスの表現形式(IPv4とIPv6、そしてそのマッピング)の複雑さがセキュリティの落とし穴になりうることを改めて示しています。特に、一見同じに見えるIPアドレスでも、その内部的な種類によって処理が分かれる点に注意が必要です。

フロントエンド開発に携わる私たちも、バックエンドフレームワークやライブラリのセキュリティ情報を常にチェックし、利用しているサービスが最新かつセキュアな状態であるかを確認する習慣をつけましょう。ユーザーからの入力がバックエンドに渡る際のURL処理や、API連携におけるエンドポイントの安全性については、特に意識を高く持つことが、アプリケーション全体のセキュリティレベル向上に繋がります。

← ブログ一覧に戻る