flawopen.com/Teardowns/cve-2026-5027-langflow-multipart-file-write
Langflow CVE-2026-5027:アップロード時のパストラバーサル
CVE-2026-5027ではパストラバーサルによりLangflowのアップロード領域外へ書き込めました。GTIGは悪用を報告。1.9.0以降へ更新してください。[1], [2], [6]
郵便室では、差出人が荷物のラベルと宛先を選べます。係員が最終的な場所を確かめずにラベルを郵便室のフォルダーへつなぐと、荷物が室外に置かれることがあります。Langflowのアップロード処理はmultipartのファイル名を信頼し、ストレージ層でも最終パスが許可されたフォルダー内にあるか確認していませんでした。[2], [3]
主要な概念と専門用語
CVE-2026-5027- LangflowのPOST /api/v2/filesにおけるmultipartファイル名のパストラバーサルにTenableが付与した識別子。
CWE-22、CVSS 3.1 8.8、必要権限は低い。[1], [2]
フレームワーク対応
- このガイドで説明する弱点の CWE 参照: CWE-22
根本原因の分析 (Root Cause)
TenableのCVE-2026-5027レコードは、POST /api/v2/filesがトラバーサル要素を含むmultipartファイル名を受け入れ、想定ディレクトリ外へ書き込む問題を説明しています。安全境界はAPIルートとローカルストレージにまたがります。URLパラメーターを検証してもmultipart Content-Disposition由来の名前は検証されず、その名前を保存フォルダーに結合しても封じ込めの証明にはなりません。CVEのベクトルは低い権限(PR:L)を要求します。このCVE自体が認証を回避すると書かないでください。Google GTIGはCVE-2026-5027を実環境で悪用が確認された脆弱性に含めていますが、公開要約は一律のコード実行を立証していません。任意ファイル書き込みの深刻度は書き込み可能な場所、プロセス権限、構成によって変わるため、確実なRCEではなく条件付きの影響として説明します。Langflowの関連GHSAはCVE-2026-33309を挙げ、同じく1.9.0の修正を示しています。本記事はTenableとGTIGに従ってCVE-2026-5027を扱い、識別子の不一致を明示します。Langflowのマージ済みパッチはAPI層で名前を検証し、ディレクトリー作成前も含めてストレージ層で正規パスの封じ込めを行います。[1], [2], [3], [4], [5], [6]
ステップ・バイ・ステップの攻撃フロー
ソースコード比較:脆弱 vs 堅牢化
これはソース構造に沿った簡略例で、上流の逐語的な差分ではありません。脆弱な処理はクライアント名を保存パスとして扱います。修正パターンは名前を検証し、ストレージ層で正規化した宛先が正規化したルート配下にあるか確認します。上流PRは区切り文字や制御文字も拒否し、ディレクトリー作成前に封じ込めを検証します。HTTP層で入力を検証しても、ストレージ側の検査を残してください。この例はPath.is_relative_toを備えたPythonが必要で、攻撃者が書き込めるディレクトリーでの検査と使用の競合を単独では防げません。本番では競合に強いファイル操作と厳格な権限を使います。防御の要点は名前のブラックリストだけでなくパスを封じ込めることです。[3], [2], [4], [7]
ソース抜粋: Langflow api/v2/files.py と services/storage/local.py — セキュリティ境界の簡略例
# 脆弱なデータフローを簡略化した例です。
new_filename = file.filename
file_path = folder_path / new_filename
await write_upload(file, file_path)
from pathlib import Path
def confined_upload_path(root: Path, client_name: str | None) -> Path:
name = Path(client_name or "").name
if not name or name in {".", ".."} or chr(0) in name:
raise ValueError("invalid upload filename")
base = root.resolve()
target = (base / name).resolve()
if not target.is_relative_to(base):
raise ValueError("upload path escapes storage root")
return target
# 作成または書き込みの直前、ストレージ境界で呼び出します。
target = confined_upload_path(upload_root, file.filename)
await write_upload(file, target)
エンジニアリング&システム堅牢化チェックリスト
- ✓Langflowを1.9.0以降へ更新し、デプロイ済みイメージ内のlangflowとlangflow-baseのバージョンを確認する。[2], [4]
- ✓multipart名はURLパラメーターと独立して検証し、区切り文字、制御文字、空名、不正なエンコードを拒否する。[1], [2], [3]
- ✓保存層で宛先を正規化し、ディレクトリー作成や書き込みの前にアップロードルート配下へ制限する。[3], [4], [7]
- ✓トラバーサル、絶対パス、別形式の区切り、ヌルバイト、Unicode、シンボリックリンク先をテストし、一時ルート外にファイルが作られないことを確認する。[3], [7]
- ✓Langflowは専用の最小権限サービスアカウントで実行し、アップロードを実行不可にしてコード、スケジュールタスク、認証情報から分離する。[2], [4]
- ✓インターネット公開範囲とアップロードログを確認し、ルート外の名前を調査する。ホストアクセスの証拠がある場合に限って秘密情報をローテーションする。[6], [2]
- ✓識別子の対応を明示する。Tenable/GTIGはCVE-2026-5027を、Langflowの関連GHSAはCVE-2026-33309を挙げる。記録を確認せず深刻度やバージョンを統合しない。[1], [2], [4], [5], [6]