CVE-2026-105698

mediumPriorität · verfolgen · 0OT-Risiko · erhöhtEPSS 0.002 · 13. PerzentilUS
grimoire priorityP3 · Track
Exploitable?
—
no known exploitation
Likely / severe?
0.22% (13th) EPSS
CVSS 5.4 · medium
Is it mine?
2 products
Prüfe deine Angriffsfläche
Who says so?
1 sources
osv

EPSS · bewertet 2026-10-27

Langflow is a tool for building and deploying AI-powered agents and workflows. From 1.0.0 until 1.10.1, Langflow did not verify flow ownership in the deprecated POST /api/v1/build/{flow_id}/vertices and POST /api/v1/build/{flow_id}/vertices/{vertex_id} handlers. Through version 1.7.1, an unauthenticated caller who knew another user's flow UUID could reach these handlers; from version 1.7.2 through 1.10.0, callers had to authenticate but needed no elevated privileges. Such a caller could cause retrieve_vertices_order to load and cache the private graph, enumerate its vertex identifiers, and use build_vertex to execute selected vertices and receive their results. build_graph_from_db_no_cache performed a primary-key lookup without an owner filter. This could disclose private flow structure, configured values, and selected outputs and could trigger victim-configured side effects and build-history records, although it did not expose the victim's variable-store credentials or permit modification of the stored flow. This issue is fixed in Langflow 1.10.1 and langflow-base 0.10.1.

01

cvss

Technischer Schweregrad, 0–10. Eine Zeile je Quelle.

5.4
010

Basiswert 0–10 · höher = schwerwiegender · Vektor überfahren zum Auflösen

v3.15.4mediumCVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:L/A:Nsecondary · security-advisories@github.comAusnutzbarkeit 2.8 · Auswirkung 2.5
v3.15.4mediumCVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:L/A:Nsecondary · OSV
v3.15mediumCVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:L/A:N/E:Usecondary · CVSS-BT (t0sche)
02

SSVC

Eine Handlungsentscheidung — aus Ausnutzung und Auswirkung.

Exploitation: poc · Automatable: no · Technical Impact: partialcoordinatorcisa_ssvcUS
03

schwächen

Die CWE-Schwächeklassen, zu denen dies gehört.

04

betroffene Produkte (2)

Betroffene Produkte und Versionsbereiche.

05

Advisories (3)

Hersteller- und Ökosystem-Meldungen dazu.

  • GHSA-gh98-4phw-6fmwLangflow : Cross-user flow access and vertex execution via deprecated /api/v1/build/{flow_id}/vertices endpoints2026-10-07ghsa · osvUS

    ### Summary Before **Langflow 1.10.1**, two deprecated but still-routed endpoints in the chat API did not check that the authenticated caller owns the flow referenced in the URL path: - `POST /api/v1/build/{flow_id}/vertices` (`retrieve_vertices_order`) - `POST /api/v1/build/{flow_id}/vertices/{vertex_id}` (`build_vertex`) Any authenticated user who knows (or obtains) another user's `flow_id` could load that user's private flow graph, enumerate its vertex IDs, and build (execute) individual vertices of it, receiving the vertex results in the response. Both routes are declared with `deprecated=True, include_in_schema=False`, so they do not appear in the OpenAPI docs, but they remained registered on the router. The Langflow UI no longer calls them (it uses `POST /api/v1/build/{flow_id}/flow`), so they are only reachable by direct HTTP requests. The issue is fixed in **Langflow 1.10.1** (`langflow-base` 0.10.1) by [#13153](https://github.com/langflow-ai/langflow/pull/13153). ### Details In affected versions, both handlers go straight to the graph loader: - `retrieve_vertices_order` (`src/backend/base/langflow/api/v1/chat.py`, lines 81-159 in 1.9.1) only required authentication via `dependencies=[Depends(get_current_active_user)]`. The user was never injected into the handler, and the flow was loaded with `build_graph_from_db(flow_id=flow_id, ...)`. - `build_vertex` (`chat.py`, lines 320-491 in 1.9.1) receives `current_user`, but only uses it for variable resolution (`user_id=str(current_user.id)`). It is never used to scope the flow lookup. The graph is taken from the chat-service cache keyed by `flow_id`, or rebuilt with `build_graph_from_db` on a cache miss. - `build_graph_from_db_no_cache` (`src/backend/base/langflow/api/utils/flow_utils.py`) does a bare primary-key lookup, `session.get(Flow, flow_id)`, with no owner filter. The supported replacement, `POST /api/v1/build/{flow_id}/flow`, already restricted the lookup to the owner or a `PUBLIC` flow (added in #12305 for GHSA-qj98-rhf8-v93f). The deprecated siblings were not covered by that fix, nor by the `_read_flow` fix for GHSA-8c4j-f57c-35cf. Additional side effects in affected versions: - `retrieve_vertices_order` stores the graph in the chat-service cache under the victim's `flow_id` (`chat_service.set_cache(str(flow_id), graph)`). When the request includes a `data` body, the cached graph is attacker-supplied. - `build_vertex` schedules `log_vertex_build` for the victim's `flow_id`, so attacker-triggered builds are recorded in the victim flow's vertex build history. Note on older versions: up to and including **1.7.1**, these two routes had no authentication dependency at all. Authentication was added in 1.7.2 by #10977, but no ownership check was added. This advisory covers the missing ownership check, which is present in every release from 1.0.0 (when the routes were introduced) through 1.10.0. ### Attack scenario 1. The attacker authenticates as any valid user. 2. The attacker obtains a victim `flow_id` (shared URLs, exported flow files, logs, screenshots, etc.). 3. `POST /api/v1/build/{victim_flow_id}/vertices` returns **200 OK** with `{"ids": [...], "run_id": "...", "vertices_to_run": [...]}` listing the victim flow's vertex IDs (component type plus suffix, e.g. `ChatInput-abc12`). 4. The attacker calls `POST /api/v1/build/{victim_flow_id}/vertices/{vertex_id}` for a returned ID. The victim's graph is loaded and the vertex is built. Its results, outputs and artifacts are returned to the attacker. ### Impact - **Confidentiality (Low):** Discloses the structure of private flows (vertex IDs and component types) and the outputs of vertices the attacker chooses to build. That includes values hardcoded in node configuration, such as prompt text or fixed inputs. - Global variables and credentials in the variable store are **not** exposed, because variable resolution uses the caller's `user_id`. - The victim's stored flow definition is not returned wholesale. - **Integrity (Low):** The attacker can trigger execution of the victim's nodes, including any side effects baked into their configuration (fixed endpoints, webhooks, hardcoded API keys). Build records are written under the victim's `flow_id`. The attacker cannot modify the stored flow. - **Availability:** None. The attacker must be authenticated and must know the target flow UUID. Flow UUIDs are random v4 values, so blind enumeration is not practical. ### Proof of concept Observed on `langflow==1.9.1` using the project's test client and in-memory SQLite fixtures (see the attached `poc.zip`): | Request | Expected (hardened) | Observed on 1.9.1 | |---|---|---| | Attacker → `POST /api/v1/build/{victim_flow_id}/vertices` | `404 Not Found` | `200 OK` with vertex order payload | | Attacker → `POST /api/v1/build/{victim_flow_id}/vertices/<bogus-id>` | `404 Not Found` | `500` `{"detail":"Vertex <id> not found"}`: the victim graph was loaded before the vertex lookup failed | | Owner (control) → same endpoints | non-404 | non-404 | On 1.10.1 and later, the attacker requests return `404 Not Found`. This is covered by regression tests in `src/backend/tests/unit/test_endpoints.py`: - `test_get_vertices_returns_404_for_other_users_private_flow` - `test_get_vertices_with_supplied_data_returns_404_for_other_users_private_flow` - `test_build_vertex_returns_404_for_other_users_private_flow` ### Patches Fixed in **Langflow 1.10.1** (`langflow-base` 0.10.1) by [#13153](https://github.com/langflow-ai/langflow/pull/13153) (merge commit `fb3d6ec90b`). Both handlers now: 1. inject `current_user` (for `retrieve_vertices_order`, this replaces the dependencies-only declaration), 2. load the flow with an owner-scoped query and return `404` when it is not found, so a flow you don't own looks the same as a missing flow, and 3. call `ensure_flow_permission(current_user, FlowAction.EXECUTE, ...)` before building or caching any graph. ```python # retrieve_vertices_order / build_vertex (1.10.1) stmt = ( select(Flow) .where(Flow.id == flow_id) .where((Flow.user_id == current_user.id) | (Flow.access_type == AccessTypeEnum.PUBLIC)) ) flow = (await session.exec(stmt)).first() if not flow: raise HTTPException(status_code=404, detail=f"Flow with id {flow_id} not found") await ensure_flow_permission( current_user, FlowAction.EXECUTE, flow_id=flow_id, flow_user_id=flow.user_id, workspace_id=flow.workspace_id, folder_id=flow.folder_id, ) ``` Related hardening in later releases: - [#14342](https://github.com/langflow-ai/langflow/pull/14342) (1.11.2) applies the same guard to the sibling `GET /api/v1/build/{flow_id}/{vertex_id}/stream` route. - [#14497](https://github.com/langflow-ai/langflow/pull/14497) (1.12.0) makes all three deprecated vertex routes owner-only, dropping the `PUBLIC` exception, because their graph cache is keyed by flow UUID rather than by the executing user. Users should upgrade to **1.10.1 or later**. The latest release is recommended. ### Workarounds If upgrading is not immediately possible, block `POST /api/v1/build/*/vertices` and `POST /api/v1/build/*/vertices/*` (and `GET /api/v1/build/*/*/stream`) at a reverse proxy. The Langflow UI does not use these routes.

  • PYSEC-2026-4234Langflow : Cross-user flow access and vertex execution via deprecated /api/v1/build/{flow_id}/vertices endpoints2026-10-15vendor · osvUS

    ### Summary Before **Langflow 1.10.1**, two deprecated but still-routed endpoints in the chat API did not check that the authenticated caller owns the flow referenced in the URL path: - `POST /api/v1/build/{flow_id}/vertices` (`retrieve_vertices_order`) - `POST /api/v1/build/{flow_id}/vertices/{vertex_id}` (`build_vertex`) Any authenticated user who knows (or obtains) another user's `flow_id` could load that user's private flow graph, enumerate its vertex IDs, and build (execute) individual vertices of it, receiving the vertex results in the response. Both routes are declared with `deprecated=True, include_in_schema=False`, so they do not appear in the OpenAPI docs, but they remained registered on the router. The Langflow UI no longer calls them (it uses `POST /api/v1/build/{flow_id}/flow`), so they are only reachable by direct HTTP requests. The issue is fixed in **Langflow 1.10.1** (`langflow-base` 0.10.1) by [#13153](https://github.com/langflow-ai/langflow/pull/13153). ### Details In affected versions, both handlers go straight to the graph loader: - `retrieve_vertices_order` (`src/backend/base/langflow/api/v1/chat.py`, lines 81-159 in 1.9.1) only required authentication via `dependencies=[Depends(get_current_active_user)]`. The user was never injected into the handler, and the flow was loaded with `build_graph_from_db(flow_id=flow_id, ...)`. - `build_vertex` (`chat.py`, lines 320-491 in 1.9.1) receives `current_user`, but only uses it for variable resolution (`user_id=str(current_user.id)`). It is never used to scope the flow lookup. The graph is taken from the chat-service cache keyed by `flow_id`, or rebuilt with `build_graph_from_db` on a cache miss. - `build_graph_from_db_no_cache` (`src/backend/base/langflow/api/utils/flow_utils.py`) does a bare primary-key lookup, `session.get(Flow, flow_id)`, with no owner filter. The supported replacement, `POST /api/v1/build/{flow_id}/flow`, already restricted the lookup to the owner or a `PUBLIC` flow (added in #12305 for GHSA-qj98-rhf8-v93f). The deprecated siblings were not covered by that fix, nor by the `_read_flow` fix for GHSA-8c4j-f57c-35cf. Additional side effects in affected versions: - `retrieve_vertices_order` stores the graph in the chat-service cache under the victim's `flow_id` (`chat_service.set_cache(str(flow_id), graph)`). When the request includes a `data` body, the cached graph is attacker-supplied. - `build_vertex` schedules `log_vertex_build` for the victim's `flow_id`, so attacker-triggered builds are recorded in the victim flow's vertex build history. Note on older versions: up to and including **1.7.1**, these two routes had no authentication dependency at all. Authentication was added in 1.7.2 by #10977, but no ownership check was added. This advisory covers the missing ownership check, which is present in every release from 1.0.0 (when the routes were introduced) through 1.10.0. ### Attack scenario 1. The attacker authenticates as any valid user. 2. The attacker obtains a victim `flow_id` (shared URLs, exported flow files, logs, screenshots, etc.). 3. `POST /api/v1/build/{victim_flow_id}/vertices` returns **200 OK** with `{"ids": [...], "run_id": "...", "vertices_to_run": [...]}` listing the victim flow's vertex IDs (component type plus suffix, e.g. `ChatInput-abc12`). 4. The attacker calls `POST /api/v1/build/{victim_flow_id}/vertices/{vertex_id}` for a returned ID. The victim's graph is loaded and the vertex is built. Its results, outputs and artifacts are returned to the attacker. ### Impact - **Confidentiality (Low):** Discloses the structure of private flows (vertex IDs and component types) and the outputs of vertices the attacker chooses to build. That includes values hardcoded in node configuration, such as prompt text or fixed inputs. - Global variables and credentials in the variable store are **not** exposed, because variable resolution uses the caller's `user_id`. - The victim's stored flow definition is not returned wholesale. - **Integrity (Low):** The attacker can trigger execution of the victim's nodes, including any side effects baked into their configuration (fixed endpoints, webhooks, hardcoded API keys). Build records are written under the victim's `flow_id`. The attacker cannot modify the stored flow. - **Availability:** None. The attacker must be authenticated and must know the target flow UUID. Flow UUIDs are random v4 values, so blind enumeration is not practical. ### Proof of concept Observed on `langflow==1.9.1` using the project's test client and in-memory SQLite fixtures (see the attached `poc.zip`): | Request | Expected (hardened) | Observed on 1.9.1 | |---|---|---| | Attacker → `POST /api/v1/build/{victim_flow_id}/vertices` | `404 Not Found` | `200 OK` with vertex order payload | | Attacker → `POST /api/v1/build/{victim_flow_id}/vertices/<bogus-id>` | `404 Not Found` | `500` `{"detail":"Vertex <id> not found"}`: the victim graph was loaded before the vertex lookup failed | | Owner (control) → same endpoints | non-404 | non-404 | On 1.10.1 and later, the attacker requests return `404 Not Found`. This is covered by regression tests in `src/backend/tests/unit/test_endpoints.py`: - `test_get_vertices_returns_404_for_other_users_private_flow` - `test_get_vertices_with_supplied_data_returns_404_for_other_users_private_flow` - `test_build_vertex_returns_404_for_other_users_private_flow` ### Patches Fixed in **Langflow 1.10.1** (`langflow-base` 0.10.1) by [#13153](https://github.com/langflow-ai/langflow/pull/13153) (merge commit `fb3d6ec90b`). Both handlers now: 1. inject `current_user` (for `retrieve_vertices_order`, this replaces the dependencies-only declaration), 2. load the flow with an owner-scoped query and return `404` when it is not found, so a flow you don't own looks the same as a missing flow, and 3. call `ensure_flow_permission(current_user, FlowAction.EXECUTE, ...)` before building or caching any graph. ```python # retrieve_vertices_order / build_vertex (1.10.1) stmt = ( select(Flow) .where(Flow.id == flow_id) .where((Flow.user_id == current_user.id) | (Flow.access_type == AccessTypeEnum.PUBLIC)) ) flow = (await session.exec(stmt)).first() if not flow: raise HTTPException(status_code=404, detail=f"Flow with id {flow_id} not found") await ensure_flow_permission( current_user, FlowAction.EXECUTE, flow_id=flow_id, flow_user_id=flow.user_id, workspace_id=flow.workspace_id, folder_id=flow.folder_id, ) ``` Related hardening in later releases: - [#14342](https://github.com/langflow-ai/langflow/pull/14342) (1.11.2) applies the same guard to the sibling `GET /api/v1/build/{flow_id}/{vertex_id}/stream` route. - [#14497](https://github.com/langflow-ai/langflow/pull/14497) (1.12.0) makes all three deprecated vertex routes owner-only, dropping the `PUBLIC` exception, because their graph cache is keyed by flow UUID rather than by the executing user. Users should upgrade to **1.10.1 or later**. The latest release is recommended. ### Workarounds If upgrading is not immediately possible, block `POST /api/v1/build/*/vertices` and `POST /api/v1/build/*/vertices/*` (and `GET /api/v1/build/*/*/stream`) at a reverse proxy. The Langflow UI does not use these routes.

  • PYSEC-2026-4238Langflow : Cross-user flow access and vertex execution via deprecated /api/v1/build/{flow_id}/vertices endpoints2026-10-15vendor · osvUS

    ### Summary Before **Langflow 1.10.1**, two deprecated but still-routed endpoints in the chat API did not check that the authenticated caller owns the flow referenced in the URL path: - `POST /api/v1/build/{flow_id}/vertices` (`retrieve_vertices_order`) - `POST /api/v1/build/{flow_id}/vertices/{vertex_id}` (`build_vertex`) Any authenticated user who knows (or obtains) another user's `flow_id` could load that user's private flow graph, enumerate its vertex IDs, and build (execute) individual vertices of it, receiving the vertex results in the response. Both routes are declared with `deprecated=True, include_in_schema=False`, so they do not appear in the OpenAPI docs, but they remained registered on the router. The Langflow UI no longer calls them (it uses `POST /api/v1/build/{flow_id}/flow`), so they are only reachable by direct HTTP requests. The issue is fixed in **Langflow 1.10.1** (`langflow-base` 0.10.1) by [#13153](https://github.com/langflow-ai/langflow/pull/13153). ### Details In affected versions, both handlers go straight to the graph loader: - `retrieve_vertices_order` (`src/backend/base/langflow/api/v1/chat.py`, lines 81-159 in 1.9.1) only required authentication via `dependencies=[Depends(get_current_active_user)]`. The user was never injected into the handler, and the flow was loaded with `build_graph_from_db(flow_id=flow_id, ...)`. - `build_vertex` (`chat.py`, lines 320-491 in 1.9.1) receives `current_user`, but only uses it for variable resolution (`user_id=str(current_user.id)`). It is never used to scope the flow lookup. The graph is taken from the chat-service cache keyed by `flow_id`, or rebuilt with `build_graph_from_db` on a cache miss. - `build_graph_from_db_no_cache` (`src/backend/base/langflow/api/utils/flow_utils.py`) does a bare primary-key lookup, `session.get(Flow, flow_id)`, with no owner filter. The supported replacement, `POST /api/v1/build/{flow_id}/flow`, already restricted the lookup to the owner or a `PUBLIC` flow (added in #12305 for GHSA-qj98-rhf8-v93f). The deprecated siblings were not covered by that fix, nor by the `_read_flow` fix for GHSA-8c4j-f57c-35cf. Additional side effects in affected versions: - `retrieve_vertices_order` stores the graph in the chat-service cache under the victim's `flow_id` (`chat_service.set_cache(str(flow_id), graph)`). When the request includes a `data` body, the cached graph is attacker-supplied. - `build_vertex` schedules `log_vertex_build` for the victim's `flow_id`, so attacker-triggered builds are recorded in the victim flow's vertex build history. Note on older versions: up to and including **1.7.1**, these two routes had no authentication dependency at all. Authentication was added in 1.7.2 by #10977, but no ownership check was added. This advisory covers the missing ownership check, which is present in every release from 1.0.0 (when the routes were introduced) through 1.10.0. ### Attack scenario 1. The attacker authenticates as any valid user. 2. The attacker obtains a victim `flow_id` (shared URLs, exported flow files, logs, screenshots, etc.). 3. `POST /api/v1/build/{victim_flow_id}/vertices` returns **200 OK** with `{"ids": [...], "run_id": "...", "vertices_to_run": [...]}` listing the victim flow's vertex IDs (component type plus suffix, e.g. `ChatInput-abc12`). 4. The attacker calls `POST /api/v1/build/{victim_flow_id}/vertices/{vertex_id}` for a returned ID. The victim's graph is loaded and the vertex is built. Its results, outputs and artifacts are returned to the attacker. ### Impact - **Confidentiality (Low):** Discloses the structure of private flows (vertex IDs and component types) and the outputs of vertices the attacker chooses to build. That includes values hardcoded in node configuration, such as prompt text or fixed inputs. - Global variables and credentials in the variable store are **not** exposed, because variable resolution uses the caller's `user_id`. - The victim's stored flow definition is not returned wholesale. - **Integrity (Low):** The attacker can trigger execution of the victim's nodes, including any side effects baked into their configuration (fixed endpoints, webhooks, hardcoded API keys). Build records are written under the victim's `flow_id`. The attacker cannot modify the stored flow. - **Availability:** None. The attacker must be authenticated and must know the target flow UUID. Flow UUIDs are random v4 values, so blind enumeration is not practical. ### Proof of concept Observed on `langflow==1.9.1` using the project's test client and in-memory SQLite fixtures (see the attached `poc.zip`): | Request | Expected (hardened) | Observed on 1.9.1 | |---|---|---| | Attacker → `POST /api/v1/build/{victim_flow_id}/vertices` | `404 Not Found` | `200 OK` with vertex order payload | | Attacker → `POST /api/v1/build/{victim_flow_id}/vertices/<bogus-id>` | `404 Not Found` | `500` `{"detail":"Vertex <id> not found"}`: the victim graph was loaded before the vertex lookup failed | | Owner (control) → same endpoints | non-404 | non-404 | On 1.10.1 and later, the attacker requests return `404 Not Found`. This is covered by regression tests in `src/backend/tests/unit/test_endpoints.py`: - `test_get_vertices_returns_404_for_other_users_private_flow` - `test_get_vertices_with_supplied_data_returns_404_for_other_users_private_flow` - `test_build_vertex_returns_404_for_other_users_private_flow` ### Patches Fixed in **Langflow 1.10.1** (`langflow-base` 0.10.1) by [#13153](https://github.com/langflow-ai/langflow/pull/13153) (merge commit `fb3d6ec90b`). Both handlers now: 1. inject `current_user` (for `retrieve_vertices_order`, this replaces the dependencies-only declaration), 2. load the flow with an owner-scoped query and return `404` when it is not found, so a flow you don't own looks the same as a missing flow, and 3. call `ensure_flow_permission(current_user, FlowAction.EXECUTE, ...)` before building or caching any graph. ```python # retrieve_vertices_order / build_vertex (1.10.1) stmt = ( select(Flow) .where(Flow.id == flow_id) .where((Flow.user_id == current_user.id) | (Flow.access_type == AccessTypeEnum.PUBLIC)) ) flow = (await session.exec(stmt)).first() if not flow: raise HTTPException(status_code=404, detail=f"Flow with id {flow_id} not found") await ensure_flow_permission( current_user, FlowAction.EXECUTE, flow_id=flow_id, flow_user_id=flow.user_id, workspace_id=flow.workspace_id, folder_id=flow.folder_id, ) ``` Related hardening in later releases: - [#14342](https://github.com/langflow-ai/langflow/pull/14342) (1.11.2) applies the same guard to the sibling `GET /api/v1/build/{flow_id}/{vertex_id}/stream` route. - [#14497](https://github.com/langflow-ai/langflow/pull/14497) (1.12.0) makes all three deprecated vertex routes owner-only, dropping the `PUBLIC` exception, because their graph cache is keyed by flow UUID rather than by the executing user. Users should upgrade to **1.10.1 or later**. The latest release is recommended. ### Workarounds If upgrading is not immediately possible, block `POST /api/v1/build/*/vertices` and `POST /api/v1/build/*/vertices/*` (and `GET /api/v1/build/*/*/stream`) at a reverse proxy. The Langflow UI does not use these routes.

06

auch bekannt als (3)

Weitere Namen und Kennungen dieser Entität.

07

quellen

Welche Quellen diesen Datensatz belegen und wann.

veröffentlicht 2026-10-05geändert 2026-10-06
08

Referenzen (4) nvd

Externe Belege — Patches, Meldungen, Analysen.

scry

Angreifer nutzen Schwachstellen wie diese gegen im Internet exponierte Dienste aus. Sehen Sie mit einem kostenlosen Passiv-Scan, was exponiert ist.

Kostenloser Scan