{"id":"CVE-2026-34046","aliases":["EUVD-2026-16850","GHSA-8c4j-f57c-35cf","PYSEC-2026-2567","PYSEC-2026-2570"],"status":"published","title":"Langflow: Authenticated Users Can Read, Modify, and Delete Any Flow via Missing Ownership Check","description":"Langflow is a tool for building and deploying AI-powered agents and workflows. Prior to version 1.5.1, 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 allowed any authenticated user to read any other user's flow, including embedded plaintext API keys; modify the logic of another user's AI agents, and/or 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. The fix in version 1.5.1 removes the `AUTO_LOGIN` conditional entirely and unconditionally scopes the query to the requesting user.","severity":{"version":"4.0","score":8.7,"vector":"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","level":"high","assessor":"cna","from":"cve"},"epss":{"day":"2026-11-09","score":0.00477,"percentile":0.41454,"model":"v2026.06.15"},"facts":{"in_kev":false,"known_exploited":false,"public_exploit":false,"fix_available":true},"cwes":["CWE-639","CWE-862"],"published":"2026-03-27T19:36:23Z","modified":"2026-11-03T22:13:23Z","fixes":[{"ecosystem":"PyPI","package":"langflow","fixed_in":["1.5.1"],"sources":["ghsa","osv"]},{"ecosystem":"PyPI","package":"langflow-base","fixed_in":["0.5.1"],"sources":["ghsa","osv"]}],"affected":[{"source":"ghsa","ecosystem":"PyPI","package":"langflow","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"last_affected":"1.5.0"},{"fixed":"1.5.1"}]}]},{"source":"ghsa","ecosystem":"PyPI","package":"langflow-base","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"last_affected":"0.5.0"},{"fixed":"0.5.1"}]}]},{"source":"osv","ecosystem":"PyPI","package":"langflow","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"1.5.1"}]}],"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"]},{"source":"osv","ecosystem":"PyPI","package":"langflow-base","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"0.5.1"}]}],"versions":["0.0.13","0.0.14","0.0.15","0.0.16","0.0.17","0.0.18","0.0.19","0.0.20","0.0.21","0.0.22","0.0.23","0.0.24","0.0.25","0.0.26","0.0.27","0.0.28","0.0.29","0.0.30","0.0.31","0.0.32","0.0.33","0.0.34","0.0.35","0.0.36","0.0.37","0.0.38","0.0.39","0.0.40","0.0.41","0.0.42","0.0.43","0.0.44","0.0.45","0.0.46","0.0.47","0.0.48","0.0.49","0.0.50","0.0.51","0.0.52","0.0.53","0.0.54","0.0.55","0.0.56","0.0.57","0.0.58","0.0.59","0.0.60","0.0.61","0.0.62","0.0.63","0.0.64","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.77","0.0.78","0.0.79","0.0.80","0.0.81","0.0.82","0.0.83","0.0.84","0.0.85","0.0.86","0.0.87","0.0.88","0.0.89","0.0.90","0.0.91","0.0.92","0.0.93","0.0.94","0.0.95","0.0.96","0.0.97","0.0.98","0.0.99","0.1.0","0.1.1","0.1.2","0.1.3","0.1.4","0.1.4.post1","0.2.0","0.3.0","0.3.1","0.3.2","0.3.3","0.3.4","0.4.0","0.4.1","0.4.2","0.4.3","0.5.0","0.5.0.post1","0.5.0.post2"]},{"source":"osv","ecosystem":"PyPI","package":"langflow","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"1.5.1"}]}],"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"]},{"source":"osv","ecosystem":"PyPI","package":"langflow-base","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"0.5.1"}]}],"versions":["0.0.13","0.0.14","0.0.15","0.0.16","0.0.17","0.0.18","0.0.19","0.0.20","0.0.21","0.0.22","0.0.23","0.0.24","0.0.25","0.0.26","0.0.27","0.0.28","0.0.29","0.0.30","0.0.31","0.0.32","0.0.33","0.0.34","0.0.35","0.0.36","0.0.37","0.0.38","0.0.39","0.0.40","0.0.41","0.0.42","0.0.43","0.0.44","0.0.45","0.0.46","0.0.47","0.0.48","0.0.49","0.0.50","0.0.51","0.0.52","0.0.53","0.0.54","0.0.55","0.0.56","0.0.57","0.0.58","0.0.59","0.0.60","0.0.61","0.0.62","0.0.63","0.0.64","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.77","0.0.78","0.0.79","0.0.80","0.0.81","0.0.82","0.0.83","0.0.84","0.0.85","0.0.86","0.0.87","0.0.88","0.0.89","0.0.90","0.0.91","0.0.92","0.0.93","0.0.94","0.0.95","0.0.96","0.0.97","0.0.98","0.0.99","0.1.0","0.1.1","0.1.2","0.1.3","0.1.4","0.1.4.post1","0.2.0","0.3.0","0.3.1","0.3.2","0.3.3","0.3.4","0.4.0","0.4.1","0.4.2","0.4.3","0.5.0","0.5.0.post1","0.5.0.post2"]}],"products":[{"vendor":"langflow","product":"langflow"},{"vendor":"langflow","product":"langflow-base"},{"vendor":"langflow-ai","product":"langflow"},{"vendor":"langflow-ai","product":"langflow-base"}],"references":[{"url":"https://github.com/langflow-ai/langflow/security/advisories/GHSA-8c4j-f57c-35cf","tags":["x_refsource_CONFIRM","Patch","Vendor Advisory","advisory","web"]},{"url":"https://github.com/langflow-ai/langflow/pull/8956","tags":["x_refsource_MISC","Issue Tracking","Patch","fix","web"]},{"url":"https://nvd.nist.gov/vuln/detail/CVE-2026-34046","tags":["advisory"]},{"url":"https://github.com/advisories/GHSA-8c4j-f57c-35cf","tags":["advisory"]},{"url":"https://github.com/CVEProject/cvelistV5/tree/main/cves/2026/34xxx/CVE-2026-34046.json","tags":["advisory"]},{"url":"https://github.com/langflow-ai/langflow","tags":["package"]},{"url":"https://pypi.org/project/langflow","tags":["package"]},{"url":"https://pypi.org/project/langflow-base","tags":["package"]}],"sources":{"cve":[{"id":"CVE-2026-34046","title":"Langflow: Authenticated Users Can Read, Modify, and Delete Any Flow via Missing Ownership Check","description":"Langflow is a tool for building and deploying AI-powered agents and workflows. Prior to version 1.5.1, 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 allowed any authenticated user to read any other user's flow, including embedded plaintext API keys; modify the logic of another user's AI agents, and/or 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. The fix in version 1.5.1 removes the `AUTO_LOGIN` conditional entirely and unconditionally scopes the query to the requesting user.","status":"published","published":"2026-03-27T20:06:35.836Z","modified":"2026-11-03T22:13:23.542Z","cvss":[{"version":"4.0","score":8.7,"vector":"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","level":"high","assessor":"cna"}],"cwes":["CWE-639","CWE-862"],"updated_at":"2026-11-03T23:33:09.822755Z"}],"euvd":[{"id":"EUVD-2026-16850","description":"Langflow is a tool for building and deploying AI-powered agents and workflows. Prior to version 1.5.1, 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 allowed any authenticated user to read any other user's flow, including embedded plaintext API keys; modify the logic of another user's AI agents, and/or 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. The fix in version 1.5.1 removes the `AUTO_LOGIN` conditional entirely and unconditionally scopes the query to the requesting user.","status":"published","published":"2026-03-27T20:06:35Z","modified":"2026-11-03T22:13:23Z","cvss":[{"version":"4.0","score":8.7,"vector":"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","level":"high"}],"updated_at":"2026-11-03T23:01:34.673315Z"}],"ghsa":[{"id":"GHSA-8c4j-f57c-35cf","title":"Langflow: Authenticated Users Can Read, Modify, and Delete Any Flow via Missing Ownership Check","description":"## 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 — 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's flow, including embedded plaintext API keys\n- **Modify** the logic of another user's 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 — 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.\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)**","status":"published","published":"2026-03-27T19:36:23Z","modified":"2026-03-27T21:52:40Z","cvss":[{"version":"4.0","score":8.7,"vector":"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","level":"high"}],"cwes":["CWE-639","CWE-862"],"updated_at":"2026-11-02T14:39:44.97342Z"}],"nvd":[{"id":"CVE-2026-34046","description":"Langflow is a tool for building and deploying AI-powered agents and workflows. Prior to version 1.5.1, 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 allowed any authenticated user to read any other user's flow, including embedded plaintext API keys; modify the logic of another user's AI agents, and/or 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. The fix in version 1.5.1 removes the `AUTO_LOGIN` conditional entirely and unconditionally scopes the query to the requesting user.","status":"published","published":"2026-03-27T21:17:27.753Z","modified":"2026-11-03T23:17:42.51Z","cvss":[{"version":"4.0","score":8.7,"vector":"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/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X","level":"high","assessor":"secondary"},{"version":"3.1","score":8.8,"vector":"CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H","level":"high","assessor":"primary"}],"cwes":["CWE-639","CWE-862"],"updated_at":"2026-11-04T01:48:27.339675Z"}],"osv":[{"id":"CVE-2026-34046","title":"Langflow: Authenticated Users Can Read, Modify, and Delete Any Flow via Missing Ownership Check","description":"Langflow is a tool for building and deploying AI-powered agents and workflows. Prior to version 1.5.1, 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 allowed any authenticated user to read any other user's flow, including embedded plaintext API keys; modify the logic of another user's AI agents, and/or 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. The fix in version 1.5.1 removes the `AUTO_LOGIN` conditional entirely and unconditionally scopes the query to the requesting user.","status":"published","published":"2026-03-27T20:06:35.836Z","modified":"2026-11-05T02:30:34.696406438Z","cvss":[{"version":"4.0","score":8.7,"vector":"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","level":"high"}],"cwes":["CWE-639","CWE-862"],"updated_at":"2026-11-07T03:08:04.213635Z"},{"id":"GHSA-8c4j-f57c-35cf","title":"Langflow: Authenticated Users Can Read, Modify, and Delete Any Flow via Missing Ownership Check","description":"## 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 — 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's flow, including embedded plaintext API keys\n- **Modify** the logic of another user's 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 — 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.\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)**","status":"published","published":"2026-03-27T19:36:23Z","modified":"2026-07-13T16:43:44.480752312Z","cvss":[{"version":"4.0","score":8.7,"vector":"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","level":"high"}],"cwes":["CWE-639","CWE-862"],"updated_at":"2026-11-02T15:46:42.077781Z"},{"id":"PYSEC-2026-2567","title":"Langflow: Authenticated Users Can Read, Modify, and Delete Any Flow via Missing Ownership Check","description":"## 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 — 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's flow, including embedded plaintext API keys\n- **Modify** the logic of another user's 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 — 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.\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)**","status":"published","published":"2026-07-13T14:36:45.466607Z","modified":"2026-07-13T16:43:44.480752312Z","cvss":[{"version":"4.0","score":8.7,"vector":"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","level":"high"}],"updated_at":"2026-11-02T15:52:55.961245Z"},{"id":"PYSEC-2026-2570","title":"Langflow: Authenticated Users Can Read, Modify, and Delete Any Flow via Missing Ownership Check","description":"## 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 — 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's flow, including embedded plaintext API keys\n- **Modify** the logic of another user's 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 — 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.\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)**","status":"published","published":"2026-07-13T14:36:45.537461Z","modified":"2026-07-13T16:43:44.480752312Z","cvss":[{"version":"4.0","score":8.7,"vector":"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","level":"high"}],"updated_at":"2026-11-02T15:52:55.961245Z"}]}}
