Langflow: insecure direct object reference
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 viadependencies=[Depends(get_current_active_user)]. The user was never injected into the handler, and the flow was loaded withbuild_graph_from_db(flow_id=flow_id, ...).build_vertex...
Affected versions
| Package | Affected | Fixed in |
|---|---|---|
| langflow PyPI | >= 1.0.0, < 1.10.1 | 1.10.1 |
Details and references
### 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 wholes
- CVSS 3.1
- CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:L/A:N
- Severity from
- GitHub (reviewed advisory)
- Weakness
- CWE-639, CWE-862
- Also known as
- CVE-2026-105698
- github.com/langflow-ai/langflow/security/advisories/GHSA-gh98-4phw-6fmw
- nvd.nist.gov/vuln/detail/CVE-2026-105698
- github.com/langflow-ai/langflow/pull/13153
- github.com/langflow-ai/langflow/commit/fb3d6ec90b1e4d52eaa40915a64b1f86b6542f55
- github.com/langflow-ai/langflow
- github.com/langflow-ai/langflow/releases/tag/v1.10.1
More Langflow advisories
All Langflow| Date | Advisory | Severity | Fixed in |
|---|---|---|---|
| Oct 7 | Langflow: OS command injection (RCE) via arbitrary command in MCP stdio server configuration | Critical9.9 | 1.10.3 |
| Oct 7 | Langflow has Authenticated Cross-Project File Disclosure via Unscoped MCP Resource Handlers | High | 1.9.1 |
| Oct 7 | Langflow: IP Spoofing Bypass via `X-Forwarded-For` Allowing Remote Configuration Write | High7.1 | 1.10.3 |
| Oct 6 | Langflow: server-side request forgery | Medium | 1.10.3 |
| Oct 6 | Langflow: remote code execution | Critical9.9 | 1.10.1 |
| Oct 5 | Langflow: Weak Fernet Key via random.seed() | Critical9.1 | 1.10.1 |