Why I flagged this one the day it hit KEV

On July 7, 2026, CISA added three vulnerabilities to the Known Exploited Vulnerabilities (KEV) catalog. Two were ordinary CMS plugin bugs, CVE-2026-48908 in JoomShaper SP Page Builder and CVE-2026-56290 in Joomlack Page Builder, and I skimmed past them. The third, CVE-2026-55255 an authorization bypass in Langflow the open-source visual builder for LLM workflows, stopped me, because it lands on the kind of system I keep finding in environments nobody has inventoried: an internal LLM builder holding API keys, database connectors, and whatever credentials someone pasted into a flow six months ago.

Every Langflow instance I have come across was stood up by a data-science or platform team, exposed to "just the internal network," and given roughly the security review you would give a Jupyter notebook. That posture is exactly what an authorization bypass punishes.

If you run Langflow and any of the following are true, I would move on it this week, not next sprint:

  • More than one person or team shares a single instance
  • Flows carry embedded credentials, API keys to other systems, or connections to internal data sources
  • /api/v1/responses or /api/v2/workflow is reachable by anyone other than the flow's owner
  • You are not correlating API-key usage against flow ownership anywhere

The score backs that up: CVSS 9.9, network vector, low complexity, low privileges (any valid API key on the instance), no user interaction, confidentiality and integrity impact both high.

The bug: an ownership check that only runs half the time

This is a clean CWE-639 (Authorization Bypass Through User-Controlled Key), the class most people still call IDOR. It lives in the get_flow_by_id_or_endpoint_name helper in src/backend/base/langflow/helpers/flow.py. Put the two lookup branches side by side:

# src/backend/base/langflow/helpers/flow.py:399-414 (pre-1.9.1)
async def get_flow_by_id_or_endpoint_name(flow_id_or_name: str, user_id: str | UUID | None = None) -> FlowRead:
    async with session_scope() as session:
        try:
            flow_id = UUID(flow_id_or_name)
            # When using UUID, query directly WITHOUT checking user_id
            flow = await session.get(Flow, flow_id)  # no ownership check
        except ValueError:
            endpoint_name = flow_id_or_name
            stmt = select(Flow).where(Flow.endpoint_name == endpoint_name)
            if user_id:
                stmt = stmt.where(Flow.user_id == uuid_user_id)

The lookup by endpoint_name filters on user_id. The lookup by UUID calls session.get() and hands back whatever it finds. /api/v1/responses takes a flow ID and calls this helper, so any authenticated user who knows a victim's flow UUID runs that flow under their own API key. And flow UUIDs are not secrets, I have seen them in share links, in application logs, and sitting in the URL bar of the Langflow UI.

What exploitation looks like

# Attacker (user A) holding their own valid API key executes
# victim (user B)'s flow by ID alone. No ownership check occurs
# server-side, so any authenticated key + any known flow UUID works.
curl -X POST "https://langflow.internal.example.com/api/v1/responses" \
  -H "x-api-key: sk-ATTACKER_OWN_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "b7e2a9c4-1f3d-4a8e-9c21-6d5f0e8a2b17",
    "input_value": "test",
    "stream": false
  }'
# Returns HTTP 200 and runs the victim flow, returning its output

Detection is weak, and I want to be honest about that

There is no tidy log line for this. Langflow does not emit a "key owner versus flow owner" mismatch as a field before 1.9.1, which is the actual gap. If you forward reverse-proxy access logs (nginx, Traefik, an API gateway) to a SIEM, the closest thing to a detection is calls to /api/v1/responses where the x-api-key does not map to the owner of the requested flow ID, and that only works if you already maintain a key-to-user-to-flow table outside Langflow. Most teams do not. So the rule below flags every call to the endpoint for manual review rather than pretending it can separate authorized from unauthorized use, and my order of operations is patch first, hunt second.

# Sigma rule (generic HTTP proxy log source, vendor-neutral)
# Requires an external key-owner-to-flow-owner join; not a native
# Langflow log field. Treat this as a starting point, not a
# drop-in detection.
title: Langflow Cross-User Flow Execution via /api/v1/responses
id: 8f2c1e40-langflow-idor-cve-2026-55255
status: experimental
logsource:
  category: proxy
  product: reverse_proxy
detection:
  selection:
    cs-uri-path|contains: '/api/v1/responses'
    cs-method: 'POST'
  condition: selection
falsepositives:
  - Legitimate shared-flow use cases where cross-user execution is by design
level: medium
fields:
  - x-api-key
  - requested_flow_id
  - source_ip
note: >
  This rule flags all calls to the endpoint for manual review against
  a flow-ownership table maintained outside Langflow. It cannot, on
  its own, distinguish authorized from unauthorized cross-user access
  pre-patch.

The actual fix, and it's the priority action:

pip install --upgrade "langflow>=1.9.1"

Langflow 1.9.1 closes both lookup branches, enforces ownership on UUID and endpoint-name lookups alike, and returns a uniform 404 for cross-user lookups instead of leaking existence via a 403-vs-404 oracle. It also moves the /api/v1/run* routes off the bare unscoped dependency as defense in depth.

The CVE-2026-55255 authorization bypassLooking up a flow by endpoint name checks that the requesting user owns it, but looking up by UUID queries the database directly with no ownership check, so any authenticated user can execute another user's flow by its ID.Any valid API keyPOST /api/v1/responseslookup by endpoint_nameWHERE user_id = you (safe)lookup by UUIDsession.get(Flow, id), NO checkVictim's flow runsunder attacker's keyFlow UUIDs appear in share links, logs, and the UI, so "knowing the ID" is not a real barrier.
The asymmetry at the heart of the bug: the endpoint-name lookup path enforces ownership, the UUID path does not. CWE-639 (Authorization Bypass Through User-Controlled Key), CVSS 9.9.

How I would work it

  1. Upgrade to Langflow 1.9.1 or later today. I have not found a compensating control that meaningfully closes an IDOR at this severity. Network ACLs narrow who can reach the endpoint; they do not restore the missing check.
  2. If you genuinely cannot patch same-day, lock inbound access to known internal ranges and assume every API key on the box is equally privileged, because until you patch, it is.
  3. Rotate API keys after patching if there is any chance it was exploited. Langflow gives you no reliable retroactive signal, so when audit certainty matters I rotate rather than argue about it.
  4. Confirm whether you even run Langflow. Twice now I have found an instance a proof-of-concept left behind that nobody owned. Grep your container registries and internal DNS before you assume you are clear.
  5. Federal: the KEV entry carries a BOD 26-04 remediation date. Check the catalog entry for the exact deadline.

Frequently Asked Questions

What is CVE-2026-55255?

It is an authorization-bypass (IDOR, CWE-639) vulnerability in Langflow rated CVSS 9.9. Because the flow-lookup helper queries the database by UUID without checking ownership, any user holding any valid API key on the instance can execute another user's flow, and its stored credentials, simply by knowing that flow's UUID, which routinely appears in share links, logs, and the UI.

Is CVE-2026-55255 being actively exploited?

Yes. CISA added it to the Known Exploited Vulnerabilities catalog on July 7, 2026 based on confirmed active exploitation, which sets a federal remediation deadline under BOD 26-04 and should be treated as same-week urgency by everyone else.

How do I fix it?

Upgrade to Langflow 1.9.1 or later, which enforces ownership on both the UUID and endpoint-name lookup paths and returns a uniform 404 for cross-user lookups. There is no reasonable compensating control that closes an IDOR at this severity without the code fix; if you cannot patch same-day, restrict network access to known internal ranges and rotate API keys after patching if exploitation is suspected.

Can I detect whether it was exploited?

Only imperfectly. Langflow does not emit a key-owner-to-flow-owner correlation as a log field before the fix, so reliable detection requires joining reverse-proxy or API-gateway logs against a flow-ownership table you maintain outside Langflow. The pragmatic order is patch first, hunt second, and rotate keys if audit certainty matters.