FlawOpen

flawopen.com/Teardowns/cve-2026-5027-langflow-multipart-file-write

● CVE-2026-5027 · CVSS 8.8[1], [2] · 高危
安全研究 · FlawOpen

Langflow CVE-2026-5027:上传文件路径穿越

CVE-2026-5027 可通过路径穿越将文件写入 Langflow 上传目录之外。GTIG 报告称该漏洞已遭利用;请升级到 1.9.0 或更高版本。[1], [2], [6]

CVSS 向量CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H[1], [2]
💡 通俗易懂的原理解析 (ELI5)

邮局收件时,寄件人可以自选标签和目的地。如果工作人员只把标签拼到邮局文件夹路径上,却不检查最终路径,包裹就可能落到邮局之外。Langflow 上传路由信任了 multipart 文件名,而存储层没有独立确认最终路径仍位于获准目录内。[2], [3]

核心概念与专有名词

CVE-2026-5027
Tenable 为 Langflow 的 POST /api/v2/files multipart 文件名路径穿越分配的标识:CWE-22、CVSS 3.1 8.8,所需权限为低。[1], [2]
Multipart 文件名
客户端在 multipart 上传 Content-Disposition 中提供的名称。它是不可信输入,不是安全文件路径。[1], [2]
路径约束
在创建或写入文件之前解析候选路径,并证明它仍位于获准存储目录之下的检查。[3], [4], [7]
标识说明
Langflow 相关 GHSA 列出 CVE-2026-33309,而 Tenable 与 Google GTIG 使用 CVE-2026-5027。本文采用 GTIG 的标识,并保留两个来源,不悄然合并其元数据。[4], [5], [6]

框架映射

  • 本指南所述弱点的 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]

攻击执行流程分解

步骤 1

低权限用户访问上传 API

CVE-2026-5027 的 CVSS 向量要求低权限。受影响路径为 POST /api/v2/files;该记录没有证明存在认证绕过。[1], [2]

步骤 2

请求提供 multipart 文件名

文件名来自客户端可控的 Content-Disposition 元数据。验证 URL 参数不会清理这个独立输入。[1], [2], [4]

步骤 3

路径越过存储边界

如果没有规范化路径约束检查,路径穿越部分可能解析到上传目录之外。[1], [2], [3], [7]

步骤 4

文件写到根目录之外

记录的影响是任意文件写入。代码执行取决于可写路径、进程权限和部署配置;不能假定每次上传都会导致 RCE。[1], [2], [6]

步骤 5

修复两个验证边界

Langflow 将 API 文件名验证和存储层规范路径约束合并到 1.9.0 发布线。请升级并核验已解析的软件包和运行镜像。[2], [3], [4]

源代码对比:漏洞与安全实现

这些是贴近源码结构的简化示例,并非上游逐字 diff。易受攻击的路径把客户端文件名当作存储路径。修复模式先验证文件名,再在存储层检查规范化目标是否位于规范化根目录内;上游 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)

工程与系统安全加固清单

参考来源