Langflow, the open-source tool for building AI flows and agents, has a critical authenticated remote code execution flaw, CVE-2026-105740 (CVSS 9.9). Any signed-in user, including a non-admin, could save an MCP server "command" that the server later ran through bash, and a honeypot has recorded attackers trying it since September 2026. The Hacker News has the report.
What happened
According to the report, the flaw lets any authenticated user "execute arbitrary OS commands on the server with the privileges of the Langflow process." Versions before 1.9.0 are affected. The article doesn't give a separate fixed version for this CVE; it also mentions a different flaw, CVE-2026-105697 (CVSS 9.9), patched in 1.10.3.
The mechanism has two requests:
POST /api/v2/mcp/servers/{server_name}stores an MCP server definition, including an attacker-suppliedcommand.GET /api/v2/mcp/servers?action_count=truetriggers it.
In the report's words: "The user-supplied command field is passed directly to bash -c "exec {command}" with zero validation, no allowlisting, and no sandboxing." The definition also has an env field that accepts arbitrary variables, such as LD_PRELOAD or PATH, which change what a process loads or which binary it finds. Because the definition is stored in project settings, it runs again whenever the server list loads, and it is "not visible during normal flow review."
A honeypot run by Previdian has recorded the activity. The first count was 1,423 attempts from 27 IP addresses since September 19, 2026, later updated to 1,706 attempts from 28 addresses. The attackers:
- checked the Langflow version;
- tried
/api/v1/auto_login, which returned 403; - logged in with "a common username and password" and used the returned bearer token;
- ran payloads that exfiltrated environment variables, including
LANGFLOW_SECRET_KEYandLANGFLOW_SUPERUSER_PASSWORD, ran Docker commands to reach the host filesystem and/etc/passwd, and ranidandwhoami.
Why it worked
An MCP server entry is, by design, "a program to start". Langflow let users configure one, which is a reasonable feature. The flaw is that the configured value was a free-text string handed to a shell, so the feature was a remote shell for anyone who could log in. Combined with a common password, that's anyone on the network.
Three separate mistakes stack up:
- A shell around user text.
bash -cinterprets everything:;,&&,$(...), redirects. There's no safe way to escape your way out of that for arbitrary input. - User-controlled environment. Letting a caller set
LD_PRELOADorPATHhands them code execution even if the command itself were fixed. - Authentication as the only gate. Every authenticated user, not just admins, could define what the server executes.
Here is an illustrative example in Python, not Langflow's code. The vulnerable version stores whatever the user sends and runs it in a shell:
# illustrative example, not the product's code (vulnerable)
def start_mcp_server(cfg: dict) -> subprocess.Popen:
env = {**os.environ, **cfg.get("env", {})} # caller sets LD_PRELOAD, PATH...
return subprocess.Popen(
f'bash -c "exec {cfg["command"]}"', shell=True, env=env
)The safer version only starts programs an administrator registered, passes an argument list with no shell, and allows a short list of environment variables:
# illustrative example, not the product's code (safer)
ALLOWED_SERVERS = { # set by an admin in deployment config
"files": ["/usr/local/bin/mcp-files", "--read-only"],
"search": ["/usr/local/bin/mcp-search"],
}
ALLOWED_ENV = {"MCP_LOG_LEVEL"}
def start_mcp_server(cfg: dict) -> subprocess.Popen:
argv = ALLOWED_SERVERS.get(cfg["server"])
if argv is None:
raise PermissionError("unknown MCP server")
env = {"PATH": "/usr/bin:/bin"}
env.update({k: v for k, v in cfg.get("env", {}).items() if k in ALLOWED_ENV})
return subprocess.Popen(argv, shell=False, env=env)Put the "who may register a server" check on an admin role as well. The general rule: if a setting means "run this", treat writes to it like a deployment, not like a preference.
What to do now
- Upgrade Langflow to a version that fixes CVE-2026-105740 (versions before 1.9.0 are affected), and to 1.10.3 or later for CVE-2026-105697.
- Disable auto-login with
LANGFLOW_AUTO_LOGIN=false. - Use strong, unique passwords for every account, and change any default or shared credentials. The attackers in the honeypot got in with a common one.
- Review logs for requests to
/api/v2/mcp/servers/, and review stored MCP server definitions in your projects for commands you didn't add. - Don't expose Langflow to untrusted networks. Put it behind a VPN or an authenticating proxy.
- Assume exposed secrets are gone if you find signs of use: rotate
LANGFLOW_SECRET_KEY, the superuser password and any API keys in the process environment. - Limit the blast radius. Run Langflow as a non-root user, without the Docker socket mounted, with only the environment variables it needs.
How OpenRouting helps
OpenRouting can't patch a Langflow instance, but it looks for the same class of bug in your own code and agent setup:
- Semgrep's command-injection rules flag shell sinks such as
subprocesswithshell=True,os.system, and f-strings built into abash -ccommand, in Python, JavaScript/TypeScript, Go and other languages. - The [command injection agent](/agents/command-injection) reviews those findings to judge whether user-controlled input actually reaches the shell. A fixed command or an argument list with no shell is marked a likely false positive, so real sinks stand out.
- The [AI/LLM safety agent](/agents/ai-llm-safety) looks at LLM application code where model output or untrusted text drives tool, shell or SQL calls, and at agent tools broader than the task needs.
- The [agent setup review](/agents/agent-setup-review) inventories the MCP configs in your repository (
.mcp.jsonand similar) and reviews them for unsafe commands, over-broad tools and secrets. See also MCP server security. - A [passive website scan](/use-cases/dynamic-scanning) of an exposed instance reports security headers, cookie flags and information leaks.
- AI triage (Claude, via Amazon Bedrock) explains each real finding in plain English and suggests a fix; secret values are redacted before any AI call.
What it won't catch
- Your Langflow version. OpenRouting doesn't do dependency scanning yet, so it won't tell you that you run a vulnerable Langflow. Check the version and upgrade.
- Exploitation attempts. The passive website scan sends no attack payloads, so it won't test whether this endpoint is exploitable, and it isn't a runtime monitor for the requests in your logs.
- Weak passwords and settings. A common admin password or auto-login left on lives in your deployment, not in code a scan reads.
- Findings need a scan. Results appear when you run a scan or review a pull request.
Sources
- Langflow's critical authenticated RCE, The Hacker News