CVE-2026-9198 | Critical Unauthenticated RCE in IBM Langflow OSS
Disclaimer: This document is published for defensive and educational purposes. All exploitation was performed against an isolated, locally-hosted Docker lab. Do not attempt these techniques against systems you do not own or have explicit written permission to test.
Introduction
This document illustrates an unauthenticated Remote Code Execution (RCE) in IBM Langflow OSS – an open-source visual framework for building AI agent and RAG applications, widely self-hosted by developers and enterprises to compose LLM-powered workflows. The vulnerability, tracked as CVE-2026-9198 with a CVSS 3.1 base score of 9.8, chains a token-issuing endpoint with a code-validation endpoint so that an adversary with nothing but network access can execute arbitrary operating-system commands on the server, and read the output directly in the HTTP response. Disclosed on 2026-07-17 and reported to IBM by security researcher Harish Kolla, the flaw was added to the CISA Known Exploited Vulnerabilities catalog on 2026-08-04, confirming active exploitation in the wild.
Langflow Description
Langflow is an open-source visual framework for building agentic AI and Retrieval-Augmented Generation (RAG) applications. Users compose workflows by dragging language models, prompt templates, vector stores, and custom Python components onto a canvas and expose the results as APIs. Following IBM’s acquisition of DataStax, the project is maintained under IBM as Langflow OSS, distributed as a free open-source product alongside paid enterprise offerings, and is typically self-hosted via Docker or directly on Linux servers, listening on port 7860 by default.
Vulnerability Severity
CVE ID: CVE-2026-9198 (IBM Langflow OSS)
Severity:CRITICAL
CVSS Vector: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
Scope of Impact
This vulnerability has been reported in Langflow OSS 1.10.0 though there are various vulnerable environments listed below and official mitigations are available:
- Langflow OSS (< 1.5) – auto-login enabled by default, exploitable out of the box when network-reachable
- Langflow OSS (1.5 – 1.10.0) – exploitable when LANGFLOW_AUTO_LOGIN=true is explicitly set
- Langflow OSS (1.0.0 – 1.10.0) – the /api/v1/validate/code code-execution flaw is present in all builds in this range, regardless of auto-loginThe fix is available in Langflow OSS 1.10.1. Note: the official langflowai/langflow:1.10.0 Docker image sets LANGFLOW_AUTO_LOGIN=false at image build time, so container deployments are exploitable only when the variable is explicitly overridden – while bare-metal and systemd deployments commonly ran with auto-login enabled by default.
Where is the vulnerability present?
The vulnerability arises from the composition of two API endpoints, tracked individually as CVE-2026-9103 and CVE-2026-8481, which together form the chained CVE-2026-9198.
The first flaw sits in GET /api/v1/auto_login. This endpoint implements a local-development convenience: when the LANGFLOW_AUTO_LOGIN setting is enabled, it takes no credentials whatsoever, no body, no header, no cookie check, and simply calls create_user_longterm_token(), returning a fully privileged SUPERUSER JWT bearer token to any network caller. Tokens observed in our lab carried an expiry approximately one year in the future, and the same token is set as a session cookie and returned in the JSON body. On a laptop bound to localhost this is a convenience feature; on an instance published to the network, the authentication step of an attack simply does not exist.
The second flaw sits in POST /api/v1/validate/code. Langflow’s visual editor lets users write custom Python components, and this endpoint exists to give immediate feedback on broken imports or malformed functions before a flow runs. To do so, it passes the raw code string from the request body to validate_code(), which does not perform AST-only analysis, it compiles and executes the submission with Python’s exec() built-in. There is no sandbox, no restricted built-ins, and no import control. The only authorization gate on the route is get_current_active_user, which verifies that a valid token is presented, not whose token it is, and not any privilege level beyond authentication.
The combination is decisive: any unauthenticated adversary can first obtain a SUPERUSER token from auto_login, then submit arbitrary Python to validate/code for execution. As IBM’s advisory states, the validator “executed Python decorators, default arguments, and annotations at function definition time, enabling arbitrary command execution on the host system.” Finally, the endpoint’s error-reporting feature returns the text of any exception raised during validation in the function.errors array of the JSON response, which an adversary deliberately uses as a channel to exfiltrate command output, making this a reflected, non-blind RCE.
Risk
An unauthenticated remote adversary can immediately execute arbitrary operating-system commands on the Langflow host as the service user, which is frequently the root account, since many deployments run the process unsupervised under Docker or systemd without user separation. Because command output is reflected in the response body, the adversary can interactively read arbitrary files such as /etc/passwd, SSH keys, and application configuration, and dump environment variables, which on AI infrastructure routinely contain commercial LLM API keys and database credentials.
Beyond the host itself, Langflow instances typically hold configured connections to vector stores, model providers, and internal APIs, giving the adversary a natural pivot for lateral movement into the surrounding network with the privileges of the application. The adversary can equally modify or replace application files, implant scheduled tasks or web shells for persistence without the victim’s knowledge, and encrypt or destroy data at will.
In short, the vulnerability represents a full compromise of the Confidentiality, Integrity, and Availability (CIA) of the underlying system and its connected data sources. As the issue is listed in the CISA Known Exploited Vulnerabilities catalog, organizations running an affected, network-exposed version should treat exploitation as a matter of when, not if.
Mitigation
The official recommendation provided by IBM is to upgrade Langflow OSS to version 1.10.1 or later, which contains code fixes for the reported issue. In addition:
- Disable auto-login. Set LANGFLOW_AUTO_LOGIN=false and configure real superuser credentials. Note: this prevents the unauthenticated chain but does not stop an adversary who already holds any valid token from reaching /api/v1/validate/code – the upgrade remains necessary.
- Restrict network exposure. Bind Langflow to localhost where feasible, and place remote-access deployments behind an authenticating reverse proxy (SSO or mTLS). Port 7860 should never face the internet directly.
- Apply WAF protection as defense-in-depth for installations that cannot be upgraded immediately – for example, AWS WAF custom rules blocking external requests to /api/v1/auto_login, and managed rule sets inspecting request bodies for injection signatures such as exec(, __import__, subprocess, and os.system in POST /api/v1/validate/code bodies.
- Run the service as a non-root user with minimal capabilities to limit post-exploitation impact.
- Hunt backwards and rotate credentials. Review access logs for external GET /api/v1/auto_login requests and POST /api/v1/validate/code bodies containing default-argument exec( patterns, and unexpected child processes under the Langflow/uvicorn process, then rotate all API keys and secrets stored in the instance.
Exploit Implementation
1. Attack Scenario
We will be using an isolated Docker lab already running on the local machine (Linux or macOS): the official image langflowai/langflow:1.10.0 on port 7860, with LANGFLOW_AUTO_LOGIN=true set explicitly to recreate the vulnerable default configuration of real-world deployments. The lab is a single service with no external dependencies, and the target is confirmed accessible before testing begins.
For this practical, we require the below setup on the testing machine:
- Nuclei with the ProjectDiscovery nuclei-templates repository
- Python 3 with the requests library (for the reference PoC)
- curl
2. Exploitation
1. Confirm the vulnerable target is accessible by visiting the Langflow URL in a browser (the canvas loads with no login prompt, because auto-login is active) and verifying the service responds on port 7860:
curl -s -o /dev/null -w “%{http_code}” http://localhost:7860/
A 200 status code confirms the target is up. The absence of an authentication page is the first visible symptom of the auto-login configuration that enables this attack chain.
2.Run the official Nuclei template against the target to confirm the vulnerability. The template chains both endpoints automatically and matches the reflected uid= output in the response body, making it reliable with near-zero false positives:
nuclei -t ~/nuclei-templates/http/cves/2026/CVE-2026-9198.yaml \
-u http://localhost:7860 -v

The expected result is [CVE-2026-9198] [http] [critical] http://localhost:7860/api/v1/validate/code. We now reproduce the same chain manually to understand each step.
3. Step one of the manual chain – the authentication bypass. Request a SUPERUSER bearer token from the auto-login endpoint, which requires no credentials:

The endpoint returns HTTP 200 with a SUPERUSER JWT whose expiry is approximately one year in the future. The authentication phase of the attack is now complete – no credential was ever presented.
4. Step two of the manual chain – the code injection. Submit a Python payload to the validation endpoint under the obtained bearer token:

![The payload hides exec() inside a function default argument, which Python evaluates at definition time - so the code runs the instant the validator executes the def statement, without the function ever being called. It runs id via subprocess, merges stderr into stdout, and raises an exception whose message is the command output; the endpoint’s error-reporting feature then reflects that output back in function.errors[0]. (The chr(...) sequences simply spell subprocess and id to avoid shell quoting issues - they have no security significance.)](https://safe.security/wp-content/uploads/cve-2026-91984.png)
The payload hides exec() inside a function default argument, which Python evaluates at definition time – so the code runs the instant the validator executes the def statement, without the function ever being called. It runs id via subprocess, merges stderr into stdout, and raises an exception whose message is the command output; the endpoint’s error-reporting feature then reflects that output back in function.errors[0]. (The chr(…) sequences simply spell subprocess and id to avoid shell quoting issues – they have no security significance.)
5. Verify the impact in a single command using the reference PoC (ywh-jfellus/CVE-2026-9198), which performs the identical two-step chain and prints a verdict:
python3 poc.py

The expected output confirms the target is vulnerable and repeats the command output obtained manually in the previous step.
6. Run a second, side-effecting command to prove genuine operating-system execution rather than a string echo. With CMD = “touch /tmp/pwned” set in the PoC, run it and inspect the container filesystem:
python3 poc.py
docker exec langflow ls -la /tmp/pwned

The expected output -rw-r–r– 1 user root 0 … /tmp/pwned demonstrates that a file created through the web request now exists on the server’s filesystem confirmed, unauthenticated remote code execution.
References:
- IBM Security Bulletin- Unauthenticated Remote Code Execution via Auto-Login Bypass and Code Validation: https://www.ibm.com/support/pages/node/7278927
- NVD – CVE-2026-9198: https://nvd.nist.gov/vuln/detail/CVE-2026-9198
- CVE Record – CVE-2026-9198: https://www.cve.org/CVERecord?id=CVE-2026-9198
- Langflow 1.10.0 source – api/v1/login.py: https://github.com/langflow-ai/langflow/blob/1.10.0/src/backend/base/langflow/api/v1/login.py
- Langflow 1.10.0 source – api/v1/validate.py: https://github.com/langflow-ai/langflow/blob/1.10.0/src/backend/base/langflow/api/v1/validate.py
- Reference PoC – ywh-jfellus/CVE-2026-9198: https://github.com/ywh-jfellus/CVE-2026-9198
- Secondary PoC – 0xdak/CVE-2026-9198_exploit: https://github.com/0xdak/CVE-2026-9198_exploit
- Nuclei Template – http/cves/2026/CVE-2026-9198.yaml (ProjectDiscovery)
- CISA Known Exploited Vulnerabilities Catalog: https://www.cisa.gov/known-exploited-vulnerabilities-catalog
- Researcher – Harish Kolla: https://github.com/Har1sh-k