Langflow RCE: an MCP server setting that runs bash

$ cat blog/langflow-mcp-command-rce.md
✓ incident
✓ command injection
✓ MCP
✓ AI security
6 min read
$ 

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:

  1. POST /api/v2/mcp/servers/{server_name} stores an MCP server definition, including an attacker-supplied command.
  2. GET /api/v2/mcp/servers?action_count=true triggers 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_KEY and LANGFLOW_SUPERUSER_PASSWORD, ran Docker commands to reach the host filesystem and /etc/passwd, and ran id and whoami.

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 -c interprets 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_PRELOAD or PATH hands 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.

attack, as reported where OpenRouting checks 1 Probe version, try auto_loginoutside a code scan 2 Log in with a common passworddeployment setting 3 POST MCP server with a command✓ Command injection agent 4 Server runs bash -c exec {command}✓ Semgrep: shell sinks 5 Exfiltrate env vars and secretsnot a runtime monitor
The attack as reported, and where an OpenRouting check applies. Illustrative.

What to do now

  1. 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.
  2. Disable auto-login with LANGFLOW_AUTO_LOGIN=false.
  3. 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.
  4. Review logs for requests to /api/v2/mcp/servers/, and review stored MCP server definitions in your projects for commands you didn't add.
  5. Don't expose Langflow to untrusted networks. Put it behind a VPN or an authenticating proxy.
  6. 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.
  7. 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 subprocess with shell=True, os.system, and f-strings built into a bash -c command, 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.json and 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

Questions

What is Langflow CVE-2026-105740?

It is a critical authenticated remote code execution flaw in Langflow, rated CVSS 9.9. Any signed-in user, including a non-admin, could store an MCP server definition whose command field the server later passed to bash -c with no validation, allowlisting or sandboxing.

Which Langflow versions are affected by CVE-2026-105740?

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, which is patched in 1.10.3.

Is CVE-2026-105740 being exploited?

A honeypot run by Previdian has recorded attempts since September 19, 2026, with the latest count at 1,706 attempts from 28 IP addresses. The attackers logged in with a common username and password, then ran payloads that exfiltrated environment variables such as LANGFLOW_SECRET_KEY and LANGFLOW_SUPERUSER_PASSWORD.

How do I lock down a Langflow instance?

Upgrade, disable auto-login with LANGFLOW_AUTO_LOGIN=false, use strong unique passwords, and keep Langflow off untrusted networks, behind a VPN or an authenticating proxy. Review stored MCP server definitions for commands you didn't add, and rotate exposed secrets if you find signs of use.

Keep reading