PYSEC-2026-2567
Vulnerability from pysec - Published: 2026-07-13 14:36 - Updated: 2026-07-13 16:04Vulnerability
IDOR in GET/PATCH/DELETE /api/v1/flow/{flow_id}
The _read_flow helper in src/backend/base/langflow/api/v1/flows.py branched on the AUTO_LOGIN setting to decide whether to filter by user_id. When AUTO_LOGIN was False (i.e., authentication was enabled), neither branch enforced an ownership check — the query returned any flow matching the given UUID regardless of who owned it.
This exposed any authenticated user to:
- Read any other user's flow, including embedded plaintext API keys
- Modify the logic of another user's AI agents
- Delete flows belonging to other users
The vulnerability was introduced by the conditional logic that was meant to accommodate public/example flows (those with user_id = NULL) under auto-login mode, but inadvertently left the authenticated path without an ownership filter.
Fix (PR #8956)
The fix removes the AUTO_LOGIN conditional entirely and unconditionally scopes the query to the requesting user:
- auth_settings = settings_service.auth_settings
- stmt = select(Flow).where(Flow.id == flow_id)
- if auth_settings.AUTO_LOGIN:
- stmt = stmt.where(
- (Flow.user_id == user_id) | (Flow.user_id == None) # noqa: E711
- )
+ stmt = select(Flow).where(Flow.id == flow_id).where(Flow.user_id == user_id)
All three operations — read, update, and delete — route through _read_flow, so the single change covers the full attack surface. A cross-user isolation test (test_read_flows_user_isolation) was added to prevent regression.
Acknowledgements
Langflow thanks the security researcher who responsibly disclosed this vulnerability:
| Name | purl | langflow | pkg:pypi/langflow |
|---|
{
"affected": [
{
"package": {
"ecosystem": "PyPI",
"name": "langflow",
"purl": "pkg:pypi/langflow"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "1.5.1"
}
],
"type": "ECOSYSTEM"
}
],
"versions": [
"0.0.31",
"0.0.32",
"0.0.33",
"0.0.40",
"0.0.44",
"0.0.45",
"0.0.46",
"0.0.52",
"0.0.53",
"0.0.54",
"0.0.55",
"0.0.56",
"0.0.57",
"0.0.58",
"0.0.61",
"0.0.62",
"0.0.63",
"0.0.64",
"0.0.65",
"0.0.66",
"0.0.67",
"0.0.68",
"0.0.69",
"0.0.70",
"0.0.71",
"0.0.72",
"0.0.73",
"0.0.74",
"0.0.75",
"0.0.76",
"0.0.78",
"0.0.79",
"0.0.80",
"0.0.81",
"0.0.83",
"0.0.84",
"0.0.85",
"0.0.86",
"0.0.87",
"0.0.88",
"0.0.89",
"0.1.0",
"0.1.2",
"0.1.3",
"0.1.4",
"0.1.5",
"0.1.6",
"0.1.7",
"0.2.0",
"0.2.1",
"0.2.10",
"0.2.11",
"0.2.12",
"0.2.13",
"0.2.2",
"0.2.3",
"0.2.4",
"0.2.5",
"0.2.6",
"0.2.7",
"0.2.8",
"0.2.9",
"0.3.0",
"0.3.1",
"0.3.2",
"0.3.3",
"0.3.4",
"0.4.0",
"0.4.1",
"0.4.10",
"0.4.11",
"0.4.12",
"0.4.14",
"0.4.15",
"0.4.16",
"0.4.17",
"0.4.18",
"0.4.19",
"0.4.2",
"0.4.20",
"0.4.21",
"0.4.3",
"0.4.4",
"0.4.5",
"0.4.6",
"0.4.7",
"0.4.8",
"0.4.9",
"0.5.0",
"0.5.0a0",
"0.5.0a1",
"0.5.0a2",
"0.5.0a3",
"0.5.0a4",
"0.5.0a5",
"0.5.0a6",
"0.5.0b0",
"0.5.0b2",
"0.5.0b3",
"0.5.0b4",
"0.5.0b5",
"0.5.0b6",
"0.5.1",
"0.5.10",
"0.5.11",
"0.5.12",
"0.5.2",
"0.5.3",
"0.5.4",
"0.5.5",
"0.5.6",
"0.5.7",
"0.5.8",
"0.5.9",
"0.6.0",
"0.6.0rc1",
"0.6.1",
"0.6.10",
"0.6.11",
"0.6.12",
"0.6.14",
"0.6.15",
"0.6.16",
"0.6.17",
"0.6.18",
"0.6.19",
"0.6.2",
"0.6.3",
"0.6.3a0",
"0.6.3a1",
"0.6.3a2",
"0.6.3a3",
"0.6.3a4",
"0.6.3a5",
"0.6.3a6",
"0.6.3a7",
"0.6.4",
"0.6.4a0",
"0.6.4a1",
"0.6.5",
"0.6.5a0",
"0.6.5a1",
"0.6.5a10",
"0.6.5a11",
"0.6.5a12",
"0.6.5a13",
"0.6.5a2",
"0.6.5a3",
"0.6.5a4",
"0.6.5a5",
"0.6.5a6",
"0.6.5a7",
"0.6.5a8",
"0.6.5a9",
"0.6.6",
"0.6.7",
"0.6.7a1",
"0.6.7a2",
"0.6.7a3",
"0.6.7a5",
"0.6.8",
"0.6.9",
"1.0.0",
"1.0.0a0",
"1.0.0a1",
"1.0.0a10",
"1.0.0a11",
"1.0.0a12",
"1.0.0a13",
"1.0.0a14",
"1.0.0a15",
"1.0.0a17",
"1.0.0a18",
"1.0.0a19",
"1.0.0a2",
"1.0.0a20",
"1.0.0a21",
"1.0.0a22",
"1.0.0a23",
"1.0.0a24",
"1.0.0a25",
"1.0.0a26",
"1.0.0a27",
"1.0.0a28",
"1.0.0a29",
"1.0.0a3",
"1.0.0a30",
"1.0.0a31",
"1.0.0a32",
"1.0.0a33",
"1.0.0a34",
"1.0.0a35",
"1.0.0a36",
"1.0.0a37",
"1.0.0a38",
"1.0.0a39",
"1.0.0a4",
"1.0.0a40",
"1.0.0a41",
"1.0.0a42",
"1.0.0a43",
"1.0.0a44",
"1.0.0a45",
"1.0.0a46",
"1.0.0a47",
"1.0.0a48",
"1.0.0a49",
"1.0.0a5",
"1.0.0a50",
"1.0.0a51",
"1.0.0a52",
"1.0.0a53",
"1.0.0a55",
"1.0.0a56",
"1.0.0a57",
"1.0.0a58",
"1.0.0a59",
"1.0.0a6",
"1.0.0a60",
"1.0.0a61",
"1.0.0a7",
"1.0.0a8",
"1.0.0a9",
"1.0.0rc0",
"1.0.0rc1",
"1.0.1",
"1.0.10",
"1.0.11",
"1.0.12",
"1.0.13",
"1.0.14",
"1.0.15",
"1.0.16",
"1.0.17",
"1.0.18",
"1.0.19",
"1.0.19.post1",
"1.0.19.post2",
"1.0.2",
"1.0.3",
"1.0.4",
"1.0.5",
"1.0.6",
"1.0.7",
"1.0.8",
"1.0.9",
"1.1.0",
"1.1.1",
"1.1.2",
"1.1.3",
"1.1.4",
"1.1.4.post1",
"1.2.0",
"1.3.0",
"1.3.1",
"1.3.2",
"1.3.3",
"1.3.4",
"1.4.0",
"1.4.1",
"1.4.2",
"1.4.3",
"1.5.0",
"1.5.0.post1",
"1.5.0.post2"
]
}
],
"aliases": [
"CVE-2026-34046",
"GHSA-8c4j-f57c-35cf"
],
"details": "## Vulnerability\n\n### IDOR in `GET/PATCH/DELETE /api/v1/flow/{flow_id}`\n\nThe `_read_flow` helper in `src/backend/base/langflow/api/v1/flows.py` branched on the `AUTO_LOGIN` setting to decide whether to filter by `user_id`. When `AUTO_LOGIN` was `False` (i.e., authentication was enabled), neither branch enforced an ownership check \u2014 the query returned any flow matching the given UUID regardless of who owned it.\n\nThis exposed any authenticated user to:\n\n- **Read** any other user\u0027s flow, including embedded plaintext API keys\n- **Modify** the logic of another user\u0027s AI agents\n- **Delete** flows belonging to other users\n\nThe vulnerability was introduced by the conditional logic that was meant to accommodate public/example flows (those with `user_id = NULL`) under auto-login mode, but inadvertently left the authenticated path without an ownership filter.\n\n---\n\n## Fix (PR #8956)\n\nThe fix removes the `AUTO_LOGIN` conditional entirely and unconditionally scopes the query to the requesting user:\n\n```diff\n- auth_settings = settings_service.auth_settings\n- stmt = select(Flow).where(Flow.id == flow_id)\n- if auth_settings.AUTO_LOGIN:\n- stmt = stmt.where(\n- (Flow.user_id == user_id) | (Flow.user_id == None) # noqa: E711\n- )\n+ stmt = select(Flow).where(Flow.id == flow_id).where(Flow.user_id == user_id)\n```\n\nAll three operations \u2014 read, update, and delete \u2014 route through `_read_flow`, so the single change covers the full attack surface. A cross-user isolation test (`test_read_flows_user_isolation`) was added to prevent regression.\n\n---\n\n## Acknowledgements\n\nLangflow thanks the security researcher who responsibly disclosed this vulnerability:\n\n- **[@chximn-dt](https://github.com/chximn-dt)**",
"id": "PYSEC-2026-2567",
"modified": "2026-07-13T16:04:31.926847Z",
"published": "2026-07-13T14:36:45.466607Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/langflow-ai/langflow/security/advisories/GHSA-8c4j-f57c-35cf"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-34046"
},
{
"type": "WEB",
"url": "https://github.com/langflow-ai/langflow/pull/8956"
},
{
"type": "PACKAGE",
"url": "https://github.com/langflow-ai/langflow"
},
{
"type": "PACKAGE",
"url": "https://pypi.org/project/langflow"
},
{
"type": "ADVISORY",
"url": "https://github.com/advisories/GHSA-8c4j-f57c-35cf"
}
],
"severity": [
{
"score": "CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N",
"type": "CVSS_V4"
}
],
"summary": "Langflow: Authenticated Users Can Read, Modify, and Delete Any Flow via Missing Ownership Check"
}
Sightings
| Author | Source | Type | Date | Other |
|---|
Nomenclature
- Seen: The vulnerability was mentioned, discussed, or observed by the user.
- Confirmed: The vulnerability has been validated from an analyst's perspective.
- Published Proof of Concept: A public proof of concept is available for this vulnerability.
- Exploited: The vulnerability was observed as exploited by the user who reported the sighting.
- Patched: The vulnerability was observed as successfully patched by the user who reported the sighting.
- Not exploited: The vulnerability was not observed as exploited by the user who reported the sighting.
- Not confirmed: The user expressed doubt about the validity of the vulnerability.
- Not patched: The vulnerability was not observed as successfully patched by the user who reported the sighting.