← Back to Feed CACHED · 2026-10-02 05:42:51 · CACHE_KEY CVE-2026-10134
CVE-2026-10134 · CWE-94 · Disclosed 2026-06-30

IBM Langflow OSS Unauthenticated RCE via PythonCodeStructuredTool exec() in Public Flow Build Endpoint

ASSESSED — NOISGATE
Vendor
—
—
—
Reassessed
—
—
—
Verdict: —
Do you agree?
01 · The Real Story

It's a front door with the lock removed — anyone who knows the address walks in and owns the house

CVE-2026-10134 affects IBM Langflow OSS versions 1.0.0 through 1.9.3. The POST /api/v1/build_public_tmp/{flow_id}/flow endpoint accepts an optional data parameter containing arbitrary flow definitions — including raw Python code in PythonCodeStructuredTool node definitions. That code is passed straight to exec() with zero sandboxing, zero input validation, and zero authentication. An attacker who can reach the endpoint and knows (or enumerates) a public flow UUID gets full server-side code execution. A second authenticated path via /api/v1/build/{flow_id}/flow persisted through versions 1.9.0–1.9.3 even after the upstream project partially patched the unauthenticated vector in CVE-2026-33017 — meaning organizations that upgraded to 1.9.x believing they were safe remained vulnerable via the authenticated route. The code path flows through start_flow_build() → create_graph() → Graph.from_payload() → _instantiate_components_in_vertices() → prepare_global_scope() → exec(compiled_code, exec_globals) with no sandboxing at any stage.

The vendor's CVSS 10.0 is technically defensible for the unauthenticated path — AV:N/AC:L/PR:N/UI:N/S:C maps cleanly to a single-request, no-auth, scope-changing RCE. The Scope: Changed rating is warranted because compromising Langflow immediately yields access to every downstream service whose credentials it stores (OpenAI, Anthropic, AWS, GCP, Azure, databases). However, a perfect 10.0 implies *zero* preconditions in every deployment, while in practice the unauthenticated path requires at least one public flow to exist and its UUID to be known or enumerable. Public flows are a first-class Langflow feature and AUTO_LOGIN=true is the default, so this precondition is met in the vast majority of real deployments — warranting at most a 0.2-point adjustment to 9.8. This is Langflow's 12th exploited CVE in 2026 (Forkast), and the same exec() technique has been weaponized within 20 hours of advisory publication for functionally identical chains (CVE-2026-33017). The vulnerability is firmly, unapologetically CRITICAL.

"One unauthenticated POST gives full RCE via unsandboxed exec(). Every secret Langflow touches is forfeit."
02 · The Attack Path

5 steps from start to impact.

STEP 01

Discover an exposed Langflow instance

Scan Shodan, Censys, or FOFA for the Langflow default port (7860) or its distinctive UI fingerprint. Alternatively, target a known internal instance post-initial-access. Censys reported 500+ exposed instances during CVE-2025-3248; VentureBeat documented 7,000 targeted servers in June 2026. The service announces itself with predictable default paths (/api/v1/version).
Conditions required:
  • Target runs IBM Langflow OSS 1.0.0–1.9.3
  • Instance is network-reachable (internet-facing or internal)
Where this breaks in practice:
  • Langflow is a niche AI workflow platform; only ~1,000–7,000 instances are internet-facing depending on the survey date
  • Many enterprise deployments are internal-only behind VPN/ZTNA
Detection/coverage: Shodan/Censys/FOFA queries for port 7860 and Langflow fingerprints. GreyNoise tags for Langflow scanning activity.
STEP 02

Enumerate public flow UUIDs

Query the Langflow API to list public flows. With AUTO_LOGIN=true (the default), the flow listing endpoints may be accessible without credentials. Even on instances where auto-login is disabled, the public flow build endpoint only requires the flow UUID — no session cookie. UUIDs follow the standard UUID4 format but are not secret; they appear in shareable links.
Conditions required:
  • At least one flow is marked PUBLIC on the target instance
  • UUID can be obtained via API enumeration, shared links, or observed network traffic
Where this breaks in practice:
  • Not every Langflow instance has public flows, though it is a core feature designed for sharing AI workflows
  • UUID enumeration may generate detectable API traffic
Detection/coverage: API access logs showing sequential or bulk flow listing requests. WAF rules for high-frequency GET to /api/v1/flows/.
STEP 03

Craft malicious flow data with embedded Python

Build a JSON flow definition that embeds arbitrary Python code in a PythonCodeStructuredTool node's tool_code field. The GHSA advisory (GHSA-vwmf-pq79-vjvx) and Metasploit module (exploit/multi/http/langflow_unauth_rce_cve_2026_10134, PR #21875 by rmhowe425) provide the exact payload schema. The advisory contained sufficient detail for attackers to construct a working exploit without any external PoC — as confirmed by SecurityWeek's report that exploitation began within 20 hours of disclosure with no public PoC repository on GitHub.
Conditions required:
  • None — offline preparation
Where this breaks in practice:
  • None — advisory detail is sufficient to construct a working payload
STEP 04

POST to build_public_tmp and achieve RCE

Send a single POST request to /api/v1/build_public_tmp/{flow_id}/flow with the malicious data parameter. Langflow passes the attacker-controlled code through start_flow_build() → create_graph() → Graph.from_payload() → exec(compiled_code, exec_globals) with zero sandboxing. The Metasploit module automates this into a single exploit command yielding a Meterpreter session. Exploitation is 100% reliable — exec() is deterministic, there is no ASLR/DEP to defeat, no race condition to win.
Conditions required:
  • Flow UUID is known from Step 2
  • Endpoint is reachable and not blocked by WAF/reverse proxy
Where this breaks in practice:
  • Zero — single HTTP request, deterministic outcome, no exploit sophistication required
Detection/coverage: WAF/IDS signatures for the build_public_tmp endpoint path. Deep-packet inspection for Python __import__ / subprocess / os.system patterns in POST body JSON. Metasploit network signatures.
STEP 05

Exfiltrate secrets, establish persistence, pivot laterally

The attacker's Python code runs with the full privileges of the Langflow process. Immediate actions: read all environment variables (OpenAI/Anthropic API keys, AWS/GCP/Azure credentials, database connection strings). Query the Langflow SQLite/PostgreSQL database to steal every flow, conversation, message, file upload, and saved component. Hit cloud metadata endpoints (169.254.169.254) for IAM role credentials. On multi-tenant instances, access other tenants' data. For persistence: modify the public flow's tool_code to embed a backdoor that executes on every subsequent build request from *any* user — achieving supply-chain-like persistence. Establish a reverse shell for interactive access.
Conditions required:
  • Langflow process has access to secrets, database, and internal network (typical in Docker/cloud deployments)
  • Cloud metadata endpoint is reachable (default in most cloud environments)
Where this breaks in practice:
  • Container isolation may limit filesystem access outside the container, but environment variables, the database, and network access are available from within
  • Cloud metadata endpoint blocking (IMDSv2 enforcement on AWS) would prevent cloud credential theft
Detection/coverage: EDR on the host detecting unusual child processes from the Langflow Python process. Cloud metadata access logs (CloudTrail for IMDSv2). Unusual outbound connections from the Langflow container/host. Database audit logs showing bulk reads.
03 · Compensating Control

1
CRITICAL 9.8→HIGH 7.5
SEVERITY REDUCED
Block the build_public_tmp endpoint at the reverse proxy — Add a deny rule for POST /api/v1/build_public_tmp/* in nginx, HAProxy, or your cloud load balancer. This eliminates the unauthenticated attack path entirely while preserving other Langflow functionality. Deploy within 3 days per the noisgate mitigation SLA for CRITICAL. The authenticated build path (/api/v1/build/{flow_id}/flow) remains open, so any user with valid credentials can still trigger the exec() chain.
2
CRITICAL 9.8→MEDIUM 6.5
SEVERITY REDUCED
Set AUTO_LOGIN=false and enforce strong authentication with MFA — Disable auto-login by setting AUTO_LOGIN=false in the Langflow environment configuration. Require strong credentials and enforce MFA via an identity-aware proxy (e.g., Cloudflare Access, Azure AD Application Proxy). This forces authentication on all endpoints, reducing the authenticated build path's exploitability to post-credential-compromise only. Deploy within 3 days. Note: any authenticated user can still trigger exec() — this does not fix the underlying code injection flaw.
3
CRITICAL 9.8→HIGH 7.2
SEVERITY REDUCED
Network-isolate Langflow from the internet — Place Langflow behind a VPN or zero-trust access proxy with no direct internet exposure. Remove any public DNS records or load balancer rules that expose port 7860. Deploy within 3 days. This eliminates the external attack surface entirely but leaves the vulnerability exploitable by internal attackers or through lateral movement from other compromised hosts.
4
CRITICAL 9.8→HIGH 7.8
SEVERITY REDUCED
Harden the Langflow container runtime — Run Langflow with --security-opt=no-new-privileges, --read-only root filesystem, dropped capabilities (--cap-drop=ALL), and a network policy blocking outbound access to 169.254.169.254 (cloud metadata) and sensitive internal subnets. Deploy within 3 days. RCE still works within the container, but lateral movement and cloud credential theft via metadata are constrained.
5
CRITICAL 9.8→IGNORE 0.0
SEVERITY REDUCED
Upgrade to IBM Langflow OSS 1.10.0+ — Full remediation. Run pip install langflow>=1.10.0 or update your Docker image tag. Consider 1.10.1+ to also cover CVE-2026-9198. Deploy within 90 days per the noisgate remediation SLA for CRITICAL. For internet-facing instances or those holding production API keys, front-load to this week.
What doesn't work
  • Container isolation alone — the attacker gets RCE *inside* the container, which still has access to environment variables (API keys), the Langflow database (all flows, secrets, conversations), and internal network. Containers are a deployment convenience, not a security boundary for this vulnerability.
  • Rate limiting — exploitation requires a single HTTP request. Rate limiting at any practical threshold (even 1 req/min) will not prevent exploitation.
  • Application-layer input validation (custom middleware) — the vulnerability IS the lack of input validation. The exec() call processes attacker-controlled code during flow graph construction, *before* any downstream validation or business logic can intervene. You cannot out-validate exec().
  • Upgrading to Langflow 1.9.0–1.9.3 only — the upstream patch for CVE-2026-33017 addressed the unauthenticated build_public_tmp path, but the authenticated build endpoint's exec() call remained vulnerable through 1.9.3. You must reach 1.10.0+.
04 · Intelligence Metadata

The supporting signals.

In-the-wild statusNot on CISA KEV for this specific CVE as of 2026-10-02. However, CVE-2026-33017 — which targets the *same endpoint* (build_public_tmp) using the *same technique* (exec() of attacker-controlled code) — was weaponized within 20 hours of disclosure. GreyNoise reports ongoing C2 activity leveraging "unpatched Langflow RCE." Langflow has accumulated 12 exploited CVEs in 2026 with 15,000+ successful exploitation attempts across campaigns (Forkast). Assume the existing attacker toolkit works against CVE-2026-10134.
PoC availabilityMetasploit module exploit/multi/http/langflow_unauth_rce_cve_2026_10134 in rapid7/metasploit-framework PR #21875 by rmhowe425 — yields Meterpreter session. GHSA-vwmf-pq79-vjvx advisory provides the full attack schema (endpoint path, data parameter structure, tool_code injection point). No standalone GitHub PoC repo found specifically for this CVE ID, but advisory detail alone was sufficient for exploitation within 20 hours (SecurityWeek). Horizon3's Unsafe at Any Speed documents the underlying exec() technique from CVE-2025-3248.
EPSS0.00641 (0.641% probability of exploitation in next 30 days). Deceptively low — the EPSS model likely hasn't fully absorbed exploitation data from functionally identical chains. Do not use this score to deprioritize; the attack surface is proven exploitable.
KEV statusNot listed as of 2026-10-02. Related Langflow CVEs (CVE-2025-3248, CVE-2026-5027, CVE-2026-33017) have been actively exploited at scale. KEV listing for CVE-2026-10134 is plausible if not imminent.
CVSS vectorCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H → 10.0. Every base metric at maximum. AV:N — network-accessible endpoint. AC:L — no specialized conditions (public flows are default). PR:N — unauthenticated build_public_tmp endpoint. UI:N — no victim interaction. S:C — compromise of Langflow yields access to downstream services via stored credentials. C:H/I:H/A:H — full read/write/destroy on the Langflow process and all reachable services.
Affected versionsIBM Langflow OSS 1.0.0 through 1.9.3. Note: the upstream Langflow project partially patched the *unauthenticated* path in version 1.9.0 (CVE-2026-33017/GHSA-vwmf-pq79-vjvx), but the *authenticated* build path via /api/v1/build/{flow_id}/flow persisted through 1.9.3. Organizations on 1.9.0–1.9.3 have a false sense of security.
Fixed versionIBM Langflow OSS 1.10.0 via PyPI (pip install langflow==1.10.0). No vendor workaround documented. IBM recommends immediate upgrade. Note: a subsequent CVE (CVE-2026-9198) was fixed in 1.10.1 — consider upgrading to 1.10.1+ to cover both.
Scanning / exposure dataShodan/Censys: ~1,000–7,000 internet-facing Langflow instances depending on survey date. Censys reported 500+ exposed instances during the CVE-2025-3248 era (Horizon3). VentureBeat documented 7,000 servers targeted in a June 2026 campaign. Shodan showed ~1,050 instances during the JadePuffer ransomware incident (July 2026). The default port is 7860; AUTO_LOGIN=true means most exposed instances accept unauthenticated requests.
Disclosed2026-06-23 (IBM Security Bulletin publication). 2026-06-30 (NVD publication date). The upstream GHSA (GHSA-vwmf-pq79-vjvx) for the related CVE-2026-33017 was published earlier; exploitation began within 20 hours.
Researcher / orgAviral2642 (vulnerability reporter), andifilhohub (analyst), Jkavia (remediation developer) per the GHSA advisory. Metasploit module by rmhowe425. Naveen Sunkavally (Horizon3) documented the original exec() technique for CVE-2025-3248 that established this vulnerability class in Langflow.

Sources.

  1. IBM Security Bulletin: Unauthenticated Server-Side RCE via PythonCodeStructuredTool
  2. NVD — CVE-2026-10134
  3. GHSA-vwmf-pq79-vjvx — Unauthenticated RCE in Langflow via Public Flow Build Endpoint
  4. Metasploit Module PR #21875 — Langflow Unauth RCE
  5. SecurityWeek — Critical Langflow Vulnerability Exploited Hours After Public Disclosure
  6. Horizon3 — Unsafe at Any Speed: Abusing Python exec for Unauth RCE in Langflow
  7. Forkast — Langflow's 12th Exploited CVE Confirms AI Frameworks Are Credential Harvesting Infrastructure
  8. BitNinja — CVE-2026-10134 Critical Server Vulnerability Alert
05 · The Call

Final Verdict
= UNCHANGED to CRITICAL (9.8/10)

Why this verdict

  • Unauthenticated, single-request RCE: The build_public_tmp endpoint accepts attacker-controlled Python code via the data parameter and feeds it directly to exec() with zero sandboxing. No credentials, no user interaction, one POST request to full server compromise. The exploit is deterministic — no memory corruption, no race condition, no ASLR to defeat.
  • Active exploitation of identical attack surface: CVE-2026-33017, which targets the *same endpoint* (build_public_tmp) and uses the *same technique* (exec() of attacker code in PythonCodeStructuredTool), was weaponized within 20 hours of advisory publication (SecurityWeek). GreyNoise reports ongoing C2 activity leveraging unpatched Langflow RCE. Langflow has 12 exploited CVEs and 15,000+ successful exploitation attempts in 2026. The exploit toolkit is directly transferable to CVE-2026-10134.
  • Weaponized tooling available: A Metasploit module (exploit/multi/http/langflow_unauth_rce_cve_2026_10134) is publicly available in rapid7/metasploit-framework PR #21875, lowering the bar to script-kiddie level. The GHSA advisory alone contained sufficient detail for attackers to construct a working exploit without any external PoC.
  • Public-flow precondition is minimal friction: Public flows are a first-class Langflow feature designed for sharing AI workflows. AUTO_LOGIN=true is the default configuration. Most active deployments meet this precondition without additional attacker effort. This is the *only* friction point in the entire chain, and it applies to the majority of real-world deployments.
  • Role multiplier: Langflow instances function as AI agent build infrastructure analogous to CI/CD platforms (Jenkins, GitLab Runner). They store production API keys (OpenAI, Anthropic, cloud provider credentials, database connection strings), connect to internal services, and access cloud metadata endpoints. In this high-value role (estimated ≥30% of production Langflow deployments operate as the orchestration layer for production AI agents), a successful chain yields: (a) credential theft across all stored secrets (blast radius: tenant → multi-service), (b) lateral movement to connected internal services and cloud accounts, (c) persistent backdoor injection into shared flows consumed by other users (blast radius: supply-chain-adjacent). The verdict floor is HIGH based on this role analysis; trivial exploitability and confirmed active exploitation of identical chains push to CRITICAL.
  • Minimal downgrade from vendor 10.0 to 9.8: The only real friction in the entire attack chain is the requirement for at least one public flow with a known UUID. This is a genuine precondition that CVSS AC:L doesn't fully capture, but it applies to the majority of real deployments, warranting at most a 0.2-point adjustment. The 1.9.0–1.9.3 false-security window (where the authenticated path remained exploitable after the upstream 'fix') is an additional concern.

Why not higher?

The vendor already assigned the maximum possible CVSS score of 10.0. Our reassessed 9.8 is at the ceiling of the CRITICAL band. The 0.2-point delta acknowledges a genuine precondition — the attacker needs at least one flow to be marked PUBLIC on the target, and needs to obtain its UUID. This is a real requirement that the base CVSS vector (AC:L) doesn't fully capture, even though it is met in the vast majority of real deployments. No further upgrade is possible or warranted.

Why not lower?

Downgrading below CRITICAL would require evidence that the attack path is significantly harder than described or that the blast radius is contained to low-value targets. Neither is true: exploitation is a single unauthenticated HTTP request, exec() is completely unsandboxed and deterministic, active exploitation of functionally identical Langflow chains is confirmed within hours of disclosure, a Metasploit module exists, and the target component stores production credentials for downstream services. The deployment-role analysis establishes a HIGH floor based on Langflow's role as AI agent build infrastructure; exploitation ease and active weaponization keep the verdict at CRITICAL. Lowering to HIGH would misrepresent the trivial barrier to exploitation and the demonstrated attacker interest in this exact attack surface.

06 · Verification

Crowdsourced verification payload.

Run this script from any machine with network access to the target Langflow instance (auditor workstation, CI runner, or jump host). No authentication required — it queries the unauthenticated version API and probes the vulnerable endpoint. Invoke as: ./check_cve_2026_10134.sh https://langflow.example.com:7860

noisgate-verify.sh
BASHREAD-ONLYSAFE
#!/usr/bin/env bash
# CVE-2026-10134 Checker — IBM Langflow OSS PythonCodeStructuredTool RCE
# Checks whether a Langflow instance is running a vulnerable version
# and whether the unauthenticated build_public_tmp endpoint is reachable.
#
# Usage:  ./check_cve_2026_10134.sh <LANGFLOW_BASE_URL>
# Example: ./check_cve_2026_10134.sh https://langflow.example.com:7860
#
# Exit codes:
#   0 = PATCHED    (version >= 1.10.0)
#   1 = VULNERABLE (version < 1.10.0)
#   2 = UNKNOWN    (could not determine version)
#   3 = usage error

set -euo pipefail

FIXED_VERSION="1.10.0"
TARGET="${1:-}"

if [[ -z "$TARGET" ]]; then
  echo "Usage: $0 <LANGFLOW_BASE_URL>"
  echo "Example: $0 https://langflow.example.com:7860"
  exit 3
fi

# Strip trailing slash
TARGET="${TARGET%/}"

echo "[*] CVE-2026-10134 checker for IBM Langflow OSS"
echo "[*] Target: $TARGET"
echo "[*] Fixed in: >= $FIXED_VERSION"
echo ""

# --- Step 1: Fetch version from API ---
echo "[*] Querying /api/v1/version ..."
VERSION_RAW=$(curl -sk --connect-timeout 10 --max-time 15 \
  "${TARGET}/api/v1/version" 2>/dev/null) || {
  echo "[!] Could not reach ${TARGET}/api/v1/version"
  echo "[!] The instance may be down, unreachable, or require authentication."
  echo "UNKNOWN"
  exit 2
}

# Parse version — try jq first, fall back to grep
if command -v jq &>/dev/null; then
  VERSION=$(echo "$VERSION_RAW" | jq -r '.version // empty' 2>/dev/null)
else
  VERSION=$(echo "$VERSION_RAW" | grep -oP '"version"\s*:\s*"\K[^"]+' 2>/dev/null || true)
fi

if [[ -z "$VERSION" ]]; then
  echo "[!] Could not parse version from API response."
  echo "[!] Raw response: $VERSION_RAW"
  echo "UNKNOWN"
  exit 2
fi

echo "[+] Detected Langflow version: $VERSION"

# --- Step 2: Probe the vulnerable endpoint ---
echo "[*] Probing /api/v1/build_public_tmp/ endpoint ..."
DUMMY_UUID="00000000-0000-0000-0000-000000000000"
PUBFLOW_STATUS=$(curl -sk -o /dev/null -w '%{http_code}' \
  --connect-timeout 10 --max-time 15 \
  "${TARGET}/api/v1/build_public_tmp/${DUMMY_UUID}/flow" \
  -X POST -H 'Content-Type: application/json' -d '{}' 2>/dev/null) || PUBFLOW_STATUS="000"

if [[ "$PUBFLOW_STATUS" == "404" ]]; then
  echo "[+] build_public_tmp endpoint returned 404 (endpoint may be removed or blocked)"
elif [[ "$PUBFLOW_STATUS" == "000" ]]; then
  echo "[?] Could not reach build_public_tmp endpoint (connection failed)"
else
  echo "[-] build_public_tmp endpoint responded with HTTP $PUBFLOW_STATUS (endpoint EXISTS)"
fi

# --- Step 3: Version comparison ---
version_gte() {
  # Returns 0 if $1 >= $2 using sort -V
  printf '%s\n%s' "$2" "$1" | sort -V -C 2>/dev/null
}

echo ""
if version_gte "$VERSION" "$FIXED_VERSION"; then
  echo "[+] Version $VERSION >= $FIXED_VERSION"
  echo "PATCHED"
  exit 0
else
  echo "[-] Version $VERSION < $FIXED_VERSION"
  if [[ "$PUBFLOW_STATUS" != "404" && "$PUBFLOW_STATUS" != "000" ]]; then
    echo "[-] WARNING: build_public_tmp endpoint is reachable (HTTP $PUBFLOW_STATUS)"
    echo "[-] This instance is likely exploitable via CVE-2026-10134."
  fi
  echo "VULNERABLE"
  exit 1
fi