{"id":"CVE-2026-55255","title":"Langflow: IDOR Vulnerability in `/api/v1/responses` Endpoint Allows Authenticated Attackers to Access Another User's Flow","summary":"Langflow: IDOR Vulnerability in `/api/v1/responses` Endpoint Allows Authenticated Attackers to Access Another User's Flow","severity":"critical","cvss":9.9,"cwe":["CWE-639"],"vendor":"langflow","product":"langflow","ecosystem":"pip","affected":["langflow < 1.9.1"],"patched":["langflow 1.9.1"],"published":"2026-06-19","updated":"2026-06-19","source":"GHSA","sourceUrl":"https://github.com/advisories/GHSA-qrpv-q767-xqq2","references":[{"url":"https://github.com/langflow-ai/langflow/security/advisories/GHSA-qrpv-q767-xqq2"},{"url":"https://github.com/langflow-ai/langflow/pull/12832"},{"url":"https://github.com/advisories/GHSA-qrpv-q767-xqq2"}],"tags":["ghsa","pip","kev","in-the-wild","exploit-available"],"epss":0.00887,"epssPercentile":0.57256,"ingestedAt":"2026-06-22T13:35:24.306Z","kev":true,"exploited":true,"kevDateAdded":"2026-07-07","kevDueDate":"2026-07-10","kevRansomware":false,"exploits":{"github":1,"githubRepos":["https://github.com/rootdirective-sec/CVE-2026-55255-Lab"],"checkedAt":"2026-09-21T15:29:35.326Z"},"exploitAvailable":true,"slug":"CVE-2026-55255","body":"## Overview\n\n## Summary\n\nInsecure Direct Object Reference (IDOR) vulnerability in `/api/v1/responses` endpoint allows an authenticated attacker to execute any flow belonging to another user by specifying the victim's flow ID in the request.\n\n## Details\n\nThe vulnerability exists in the `get_flow_by_id_or_endpoint_name` helper function in [`src/backend/base/langflow/helpers/flow.py` (lines 399-414)](https://github.com/langflow-ai/langflow/blob/v1.9.0/src/backend/base/langflow/helpers/flow.py#L399C1-L414C67).\n\nWhen a flow is accessed via UUID (flow_id), the function queries the database directly without verifying if the authenticated user owns that flow:\n\n```python\n# src/backend/base/langflow/helpers/flow.py:399-414\nasync def get_flow_by_id_or_endpoint_name(flow_id_or_name: str, user_id: str | UUID | None = None) -> FlowRead:\n    async with session_scope() as session:\n        try:\n            flow_id = UUID(flow_id_or_name)\n            # When using UUID, query directly WITHOUT checking user_id\n            flow = await session.get(Flow, flow_id)  # ❌ No user_id check!\n        except ValueError:\n            endpoint_name = flow_id_or_name\n            stmt = select(Flow).where(Flow.endpoint_name == endpoint_name)\n            # Only when using endpoint_name is user_id checked\n            if user_id:\n                stmt = stmt.where(Flow.user_id == uuid_user_id)\n```\n\nThis function is used by the `/api/v1/responses` endpoint (defined in [`src/backend/base/langflow/api/v1/openai_responses.py:589`](https://github.com/langflow-ai/langflow/blob/v1.9.0/src/backend/base/langflow/api/v1/openai_responses.py#L589)).\n\n## PoC (Proof of Concept)\n\n```bash\n# Attacker (user A) with API_KEY_A tries to execute victim (user B)'s flow\ncurl -X POST \"http://localhost:7860/api/v1/responses\" \\\n  -H \"x-api-key: sk-ATTACKER_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"model\": \"VICTIM_FLOW_ID\",\n    \"input_value\": \"test\",\n    \"stream\": false\n  }'\n# Returns 200 and executes the victim's flow\n```\n\n## Impact\n\nAny authenticated user can:\n1. Execute any flow in the system by knowing its flow ID\n2. Access potentially sensitive data processed by victim's flows\n3. Consume victim's resources\n\n## Fixes\n\nFixed in **PR #12832** (`fix(security): close IDOR in get_flow_by_id_or_endpoint_name`), merged 2026-04-22, released in **Langflow 1.9.1**.\n\nThe helper normalizes `user_id` once and enforces ownership on **both** lookup branches (UUID *and* `endpoint_name`):\n\n```python\nflow_id = UUID(flow_id_or_name)\nflow = await session.get(Flow, flow_id)\nif flow is not None and uuid_user_id is not None and flow.user_id != uuid_user_id:\n    flow = None  # cross-user lookup falls through to the shared 404\n```\n\nKey points:\n- Cross-user lookups return **404** (not 403), so flow existence is not disclosed via a 403-vs-404 oracle.\n- `/api/v1/responses` and `/api/v2/workflow` pass `user_id` explicitly, so fixing the helper closes them directly; the `/api/v1/run*` routes were additionally moved from a bare `Depends(get_flow_by_id_or_endpoint_name)` to auth-aware wrapper dependencies (defense in depth).\n- A malformed `user_id` now fails closed (404 instead of a raw 500).\n- Webhook routes intentionally keep the unscoped lookup (public by design / explicit ownership check elsewhere).\n- Regression tests cover the cross-user UUID case and reproduce the original PoC against `/api/v1/responses`.\n\n\n\n\n\n## Acknowledgements\n\nThanks to the security researchers who responsibly disclosed this vulnerability:\n* @yzeirnials\n* @johnatzeropath\n* @LeftenantZero\n* @Zwique\n\n## Affected packages\n\n- `langflow < 1.9.1`\n\n## Remediation\n\nUpgrade to a patched release:\n\n- `langflow 1.9.1`","depth":"hadal","depthScore":80,"depthScoreParts":{"impact":54.5,"likelihood":0.2,"exploitation":25,"ransomware":0},"changes":[{"seq":5351,"id":"CVE-2026-55255","ts":1788887269864,"field":"exploit_available","old":"false","new":"true"},{"seq":4234,"id":"CVE-2026-55255","ts":1788886384740,"field":"exploit_available","old":"true","new":"false"},{"seq":2990,"id":"CVE-2026-55255","ts":1788883048391,"field":"exploit_available","old":"false","new":"true"},{"seq":2019,"id":"CVE-2026-55255","ts":1788882452811,"field":"exploit_available","old":"true","new":"false"},{"seq":1095,"id":"CVE-2026-55255","ts":1788881889680,"field":"exploit_available","old":"false","new":"true"},{"seq":177,"id":"CVE-2026-55255","ts":1787603660750,"field":"epss","old":"0.29052","new":"0.00887"},{"seq":92,"id":"CVE-2026-55255","ts":1784920493527,"field":"epss","old":"0.0056","new":"0.29052"},{"seq":57,"id":"CVE-2026-55255","ts":1783533111670,"field":"exploited","old":"false","new":"true"},{"seq":56,"id":"CVE-2026-55255","ts":1783533111670,"field":"kev","old":"false","new":"true"},{"seq":53,"id":"CVE-2026-55255","ts":1783532625146,"field":"exploited","old":"true","new":"false"},{"seq":52,"id":"CVE-2026-55255","ts":1783532625146,"field":"kev","old":"true","new":"false"},{"seq":49,"id":"CVE-2026-55255","ts":1783529207812,"field":"exploited","old":"false","new":"true"},{"seq":48,"id":"CVE-2026-55255","ts":1783529207812,"field":"kev","old":"false","new":"true"}]}