AEV-2026-0032
Langflow MCP installer local-only gate satisfied by a caller supplied network origin (CVE-2026-9186)
Langflow's local-only MCP configuration installer gated a host filesystem write on the caller's IP resolving to loopback. Before a July 2026 fix, that resolution read a caller supplied X-Forwarded-For header unconditionally; a narrower, distinct residual variant then affected the pre-release 1.11.3 line under an explicit, non default trusted-proxy configuration. IBM's advisory states versions 1.0.0 through 1.11.2 are affected; this entry's own independently verified commit containment narrows that for the originally reported mechanism specifically.
Affected
- Organisation
- Langflow AI
- Product
- Langflow OSS
- Component
- The install_mcp_config route's locality check (get_client_ip / is_local_ip) in mcp_projects.py
- Versions
- IBM's advisory states 1.0.0 through 1.11.2 affected, 1.11.3 fixed. This entry's own independently verified commit containment narrows that for the originally reported bypass specifically: the fix for it, commit 1641b28f33e2c47b9a0c6855922d44d1b8418b9d, is already contained in v1.11.0, v1.11.1 and v1.11.2. A separate, narrower residual bypass affected the pre-release state of the 1.11.3 line, requiring an explicit, non default rate_limit_trust_proxy configuration against a header-appending proxy, and was closed by commit 425c4cb36ec3430145c0c12ce7f27fc50db2954e before v1.11.3 shipped.
- Configurations
- Any deployment running a version before commit 1641b28f33e2c47b9a0c6855922d44d1b8418b9d, for the originally reported, unconditional leftmost X-Forwarded-For read.; A deployment with rate_limit_trust_proxy explicitly enabled against a proxy that appends rather than extends X-Forwarded-For lines (HAProxy's own forwardfor option is the example upstream names), during the pre-release window before commit 425c4cb36ec3430145c0c12ce7f27fc50db2954e shipped, for the residual variant.; A same-host reverse proxy topology, acknowledged directly by upstream as unresolved by either fix, in which request.client.host reads loopback for every remote caller regardless of any header.
Execution authority facts
Fields the evidence does not establish are shown as unknown rather than guessed.
- Intended task
- An authenticated Langflow user installing an MCP server entry for their own project into a locally installed Cursor, Windsurf or Claude configuration file, a route Langflow's own design restricts to a caller physically or topologically local to the host.
- Agent
- Langflow's own backend process handling POST /api/v1/mcp/project/{project_id}/install
- Delegating actor
- The operator who deploys Langflow and decides whether to enable rate_limit_trust_proxy or place Langflow behind a reverse proxy
- Action
- Satisfied the route's loopback-only locality gate from a non-local network position, by a caller supplied X-Forwarded-For value (original bypass) or by a repeated-header parsing gap under an explicit trusted-proxy configuration (residual variant), reaching the host filesystem write the gate exists to restrict
- Target resource
- The host filesystem's own Cursor, Windsurf or Claude MCP configuration file, merged with a new mcpServers entry pointing at the caller's Langflow project
- Environment
- Wherever the operator deployed Langflow, on the host machine whose own local operator the install route's gate is designed to admit
- Credentials used
- An authenticated Langflow user session (CurrentActiveMCPUser); no credential beyond that is required by the route itself
- Privileges available
- Whatever privileges an authenticated Langflow user session carries, plus, once the gate is satisfied, a host-side filesystem write outside Langflow's own application data
- Authority presented
- An authenticated Langflow session combined with a network-origin value read as evidence of a local network position
- Authority required
- A verified grant that the specific principal calling is the one physically or topologically local to the host, distinct from mere authentication to Langflow itself
- Applicable policy
- unknown
- Approval mechanism
- unknown
- Required approver
- unknown
- Independent approval
- no
- Action binding
- The route's own authorization bound to an authenticated Langflow session plus a topological locality classification; the classification itself was not independently bound to the caller's actual physical or topological position until the July 2026 fix narrowed, and the August 2026 fix further narrowed, what could produce it
- Sequence context
- unknown
Impact
- Consequence
- A host-side MCP client configuration file is rewritten to include a server entry a local-only gate exists specifically to prevent a non-local, authenticated caller from installing, changing what an IDE agent on that host may connect to on its own next launch
- Reach
- Single: the one host machine and the one MCP client configuration file targeted by a given call
- Reversibility
- Recoverable: an operator inspecting the affected configuration file can remove the injected entry, though nothing in the evidence available describes a mechanism prompting that inspection
- Detectability
- unknown
- Propagation
- A documented, concrete path exists (the configuration change is read by the targeted IDE on its own next launch or reload), not established as observed operating against a real deployment
- Recovery
- Fixed by two sequential code changes, the second contained in the v1.11.3 release; no process is described for a configuration file that may have already been written on a given deployment before its own upgrade
Evidence
Primary sources
- IBM Security Advisory: Langflow OSS is vulnerable to Improper Access Control (CVE-2026-9186) (IBM (Support))
- fix(security): harden multi-tenant surfaces (langflow-ai/langflow#13530) (GitHub (langflow-ai/langflow))
- Commit 1641b28f33e2c47b9a0c6855922d44d1b8418b9d (GitHub (langflow-ai/langflow))
- fix(security): join repeated X-Forwarded-For lines before taking the last hop (langflow-ai/langflow#14425) (GitHub (langflow-ai/langflow))
- Commit 425c4cb36ec3430145c0c12ce7f27fc50db2954e (GitHub (langflow-ai/langflow))
Supporting sources
- mcp_projects.py at tag v1.10.2 (pre-fix) (GitHub (langflow-ai/langflow), raw source)
- mcp_projects.py at tag v1.11.3 (post both fixes) (GitHub (langflow-ai/langflow), raw source)
- rate_limit/service.py at tag v1.11.3 (GitHub (langflow-ai/langflow), raw source)
- test_mcp_install_xff_trust.py at tag v1.11.3 (GitHub (langflow-ai/langflow), raw source)
- Compare v1.11.0...1641b28f33e2c47b9a0c6855922d44d1b8418b9d (GitHub (langflow-ai/langflow))
- Compare v1.11.1...1641b28f33e2c47b9a0c6855922d44d1b8418b9d (GitHub (langflow-ai/langflow))
- Compare v1.11.2...1641b28f33e2c47b9a0c6855922d44d1b8418b9d (GitHub (langflow-ai/langflow))
- Release v1.11.3, langflow-ai/langflow (GitHub (langflow-ai/langflow))
- Reproduction status
- This entry independently read the vulnerable pre-fix code, the fixed code and the residual variant's own fix directly from the project's public source at three tags, and independently confirmed commit containment using GitHub's own compare tool against the exact commit upstream's own pull request names. This is a direct reading of the real, unmodified source and commit graph, not an executed exploit against a running instance.
- Evidence state
- Confirmed
Known unknowns
- Which of the two mechanisms this entry traces IBM's own CVE-2026-9186 is formally scoped to describe.
- The literal default declaration for rate_limit_trust_proxy in the settings source, corroborated here only through the shipped test suite's own naming and assertions.
- Whether either mechanism, or the acknowledged same-host reverse proxy limitation, was ever reached by a party other than the researcher or maintainer verifying it.
- How many production deployments ran a vulnerable configuration before either fix, or sit today behind a same-host reverse proxy with rate_limit_trust_proxy at its default.
- Whether the 1.10.3 backport pull request 14425 itself names was independently verified by anyone beyond Langflow's own maintainers.
Limitations
- IBM's own advisory page at ibm.com was blocked to direct fetch in this session on every attempt, and no GitHub Security Advisory mirroring this specific CVE could be located against langflow-ai/langflow, so IBM's own CVSS score, CWE classification and precise affected range are recorded as the vendor's claim rather than independently confirmed by a direct read of the primary advisory.
- This entry's own attempt to independently locate rate_limit_trust_proxy's literal default value declaration in the settings source it read was unsuccessful; the default of false is corroborated instead through the shipped test suite's own naming and assertions and through get_client_ip's own docstring.
Claim provenance
- vendor-claim
IBM's advisory assigns CVE-2026-9186, states CVSS 3.1 6.5 under CWE-284, and states versions 1.0.0 through 1.11.2 affected with 1.11.3 fixed. IBM's own page was blocked to direct fetch in this session; this claim is recorded as the vendor's stated position, narrowed for the originally reported mechanism specifically by this entry's own independently verified commit containment, recorded separately below.
The Caller Was Remote. A Header Made It Local Enough to Rewrite the Agent's MCP Configuration. - verified
This entry read the vulnerable pre-fix locality check directly at v1.10.2, confirming an unconditional, leftmost X-Forwarded-For read, and read the fixed function directly at v1.11.3, confirming it defaults to the TCP peer and gates X-Forwarded-For behind an explicit trusted-proxy opt-in, matching pull request 13530's own stated fix.
The Caller Was Remote. A Header Made It Local Enough to Rewrite the Agent's MCP Configuration. - verified
This entry independently confirmed, using GitHub's own compare tool rather than pull request prose alone, that the fixing commit is contained in the v1.11.0, v1.11.1 and v1.11.2 tags, the same versions IBM's advisory names as affected for the originally reported bypass.
The Caller Was Remote. A Header Made It Local Enough to Rewrite the Agent's MCP Configuration. - verified
This entry read pull request 14425's own body, its own repeated-header fix and its own regression tests directly, and confirmed the fix ships as part of the v1.11.3 release. The same pull request states directly, and this entry preserves rather than resolves, that its fix does not address a same-host reverse proxy making every remote caller's TCP peer appear loopback by ordinary topology.
The Caller Was Remote. A Header Made It Local Enough to Rewrite the Agent's MCP Configuration.
