Blog

Langflow Vulnerabilities: CVE-2025-3248 and 5 More Exploited Bugs

Six exploited Langflow vulnerabilities, CVE-2025-3248 to CVE-2026-9198: what each gives an attacker, fixed versions, and how to keep Langflow off the internet.

9 min read
Karolis Rusenas
On this page

Langflow has had at least six vulnerabilities that attackers exploited in under two years, starting with CVE-2025-3248, an unauthenticated remote code execution flaw in /api/v1/validate/code. Patch to the latest release, then stop exposing the server: the only Langflow path an outside service needs is the webhook endpoint, POST /api/v1/webhook/{flow_id}, and an outbound-only relay can deliver exactly that while the rest of the API stays private.

AI builder tools tend to go from pip install to a public URL in an afternoon, with the editor, the API and the code-validation endpoints all reachable by anyone. Each Langflow flow can hold Python components and API keys for model providers and databases, so a Langflow server is a credential store that also executes code. This post lists the exploited Langflow vulnerabilities, shows which endpoints they hit, and explains how to expose only what a webhook needs.

The Langflow vulnerabilities attackers have exploited

All six are in CISA's Known Exploited Vulnerabilities catalog. Each CVE links to its Threat Watch record.

CVEWhat an attacker getsAuth neededExploited in the wildFixed in
CVE-2025-3248, the /api/v1/validate/code RCECode execution on the server through Python exec()NoneYes (Flodrix botnet, ransomware flag)1.3.0
CVE-2025-34291, CORS and cookie account takeoverFresh tokens for a logged-in user, then code executionA victim's logged-in browser visiting a malicious pageYes (first seen 2026-01-23)1.7.0
CVE-2026-0770, exec_globals code executionAttacker-chosen Python run by the Langflow processNoneYes (KEV 2026-07-21)Not named in the advisories (affects up to 1.7.3)
CVE-2026-33017, build_public_tmp RCECode execution; environment variables and .env theft observedNoneYes (first attempt about 20 hours after the advisory)1.9.0
CVE-2026-55255, flow IDOR via /api/v1/responsesRun any other user's flowAny valid account or API keyYes (Sysdig, 2026-06-25)1.9.1
CVE-2026-9198, auto_login plus code validationSuperuser token, then code executionNoneYes (KEV 2026-08-04)1.10.1

A few details worth knowing:

  • CVE-2025-3248 is the original. Horizon3 showed that code hidden in function decorators or default arguments runs the moment the function is defined. Trend Micro reported the Flodrix botnet arriving through it.
  • CVE-2026-33017 is distinct from CVE-2025-3248. It abuses the route meant for building public flows without a login, and it trusts attacker-supplied node definitions. Sysdig documented environment-variable and .env theft.
  • CVE-2026-9198 is described in IBM's bulletin for Langflow OSS: versions 1.0.0 through 1.10.0, /api/v1/auto_login issues superuser bearer tokens to any network caller, and /api/v1/validate/code executes submitted Python. IBM lists no workaround besides upgrading.
  • CVE-2026-0770 has no fixed version named in the sources we could verify, so check the current Langflow release notes and keep the validate endpoint unreachable.

Not one of these needs the webhook endpoint. They hit the code-validation route, the public-flow build route, the responses API, the auto-login route, or the browser session.

Why exposure is the multiplier

Look at the pattern: four of six need no credentials, and the fifth needs any account. CVE-2026-33017 was attempted roughly 20 hours after its advisory, before any public proof of concept existed. Patch windows measured in days are longer than the time attackers need.

A Langflow server also tends to sit on valuable ground: it holds model-provider keys, vector database credentials and whatever the flows connect to. Sysdig saw .env and environment-variable theft on CVE-2026-33017. So a reachable, unpatched Langflow turns one HTTP request into a set of secrets for other systems. Reachability is the one variable you control regardless of which CVE comes next.

What to expose and what not to

Langflow's webhook documentation says a flow with a Webhook component is triggered by a POST to /api/v1/webhook/FLOW_ID, that webhook authentication is on by default (LANGFLOW_WEBHOOK_AUTH_ENABLE=True), and that the caller passes a Langflow API key as an x-api-key header or query parameter. The response only confirms the task started in the background.

Path or surfaceNeeds to be reachable from the internet?
POST /api/v1/webhook/{flow_id}Yes, if outside services trigger flows. Only through a relay or proxy that forwards just this path
The editor UI and loginNo. Reach it over VPN or from the private network
/api/v1/validate/codeNo
/api/v1/build_public_tmp/...No
/api/v1/responses, /api/v1/flows/No
/api/v1/auto_login, /api/v1/refreshNo

GitHub, Stripe, Slack and monitoring tools deliver to a single URL. That is the whole reason most of these servers are public.

Receive Langflow webhooks without exposing Langflow

Webhook Relay runs an agent beside Langflow. The agent opens an outbound connection, the provider posts to a public bucket input URL, and the relay streams each request down that connection to a destination you configure. This is the same pattern described in triggering a self-hosted AI agent with webhooks and the localhost forwarding docs.

GitHub / Stripe / monitoring
          |
          | HTTPS POST
          v
 public bucket input URL
          |
          | outbound agent connection (no inbound rule)
          v
 private Langflow  http://localhost:7860/api/v1/webhook/FLOW_ID

1. Install the CLI and log in

curl https://my.webhookrelay.com/webhookrelay/downloads/install-cli.sh | bash
relay login -k YOUR_TOKEN_KEY -s YOUR_TOKEN_SECRET

Create the token on the tokens page.

2. Create the bucket and point the output at the webhook URL

relay bucket create langflow-hooks
relay input create --bucket langflow-hooks "public endpoint"
relay output create langflow --bucket langflow-hooks \
  --destination http://localhost:7860/api/v1/webhook/FLOW_ID

Replace FLOW_ID with your flow's ID (the Webhook component shows the exact URL). Lock the destination path. By default an output appends any extra path the sender adds to the input URL (a POST to <input URL>/anything goes to <destination>/anything). Outputs created in the dashboard have Destination URL path locked switched on; outputs created with the CLI or API do not, so open the output and turn it on (API/MCP field lock_path: true). With the path locked, every delivery goes to exactly the destination URL and nothing else on Langflow is reachable through the relay. Lock it so the sender cannot choose any part of the path Langflow receives. relay forward (next step) prints the public input URL; paste it into the provider.

3. Keep the agent running

relay forward -b langflow-hooks

On a server, run it as a container instead (use --network host when Langflow listens on the host's localhost):

docker run -d --name whr-relayd --restart always --network host \
  -e RELAY_KEY=YOUR_TOKEN_KEY -e RELAY_SECRET=YOUR_TOKEN_SECRET \
  -e BUCKETS=langflow-hooks \
  webhookrelay/webhookrelayd:latest

See the Docker install page for compose, Kubernetes and autostart options.

4. Close the inbound path

Bind Langflow to localhost or a private subnet and remove the public port forward or reverse-proxy route. Put human access to the editor behind a VPN or an identity-aware proxy.

5. Keep Langflow's API key on, and keep it off the provider

GitHub and Stripe cannot send an x-api-key header, which is why people switch LANGFLOW_WEBHOOK_AUTH_ENABLE off. Do not. Instead, attach a function to the output that checks the provider's signature and adds the Langflow key on the way through. The key lives in a secret service connection, not in the provider's settings:

local crypto = require('crypto')
local api_key = require("secret:langflow-key")

-- GitHub shown; change the header name for other providers
local signature_header = 'X-Hub-Signature-256'
local calculated_hmac, err = crypto.hmac('sha256', r.RequestBody, cfg:GetValue("WEBHOOK_SECRET"))
if err then error(err) end

if "sha256=" .. calculated_hmac ~= r.RequestHeader[signature_header] then
    r:SetResponseStatusCode(401)
    r:StopForwarding()
    return
end

r:SetRequestHeader("x-api-key", api_key)

The signature check follows the HMAC example; the header-setting call is from modifying requests. Now an anonymous POST to the public input URL is dropped at the relay, and Langflow still enforces its own API key.

Hardening that still matters

The relay removes network exposure. It does not make an old Langflow safe.

  • Patch. Upgrade to the latest release. The fixes above are spread across 1.3.0, 1.7.0, 1.9.0, 1.9.1 and 1.10.1, and one CVE names no fixed version.
  • Keep webhook auth on. LANGFLOW_WEBHOOK_AUTH_ENABLE=False makes webhook requests run as the flow owner.
  • Verify signatures. Check provider signatures before forwarding, as above. See how to verify a webhook signature and webhook security best practices.
  • Filter what you forward. Use forwarding rules or a function to pass only the event types and branches the flow expects.
  • Limit the blast radius. Run Langflow as a non-root user with only the credentials its flows need, and give each user only the flows they need on shared instances.
  • Rotate after exposure. If a pre-fix instance was internet-reachable, rotate every API key, database and cloud credential in its environment and rebuild the host rather than cleaning it.
  • Search logs. Look for POSTs to /api/v1/validate/code, /api/v1/build_public_tmp/ and /api/v1/responses from unknown sources.

The same approach applies to other self-hosted tools that are public only for webhooks; see securing Jenkins and webhooks in CI/CD.

Honest limits: when a relay does not help

  • CVE-2025-34291 is browser-driven. The attack runs through a logged-in user's browser: a malicious page calls the refresh endpoint cross-origin because of the wildcard CORS policy and a SameSite=None cookie. A victim's browser can reach a private Langflow server on a LAN or VPN, so removing public exposure does not stop it. Upgrade to 1.7.0 or later, restrict CORS origins to your front end, set REFRESH_SAME_SITE to Lax or Strict where front end and back end share a site, and sign users out after upgrading.
  • The webhook path itself. If a flaw lands in the webhook handler, or you disabled webhook auth, the relay forwards whatever reaches it. The signature check above runs at the relay, so unsigned requests get a 401 and never reach Langflow; only deliveries your provider signed get through. A flaw triggered by content inside a genuine delivery still needs the patch.
  • Authenticated abuse stays authenticated. CVE-2026-55255 needs a valid account or API key. A relay does not change who inside your network holds one.
  • People who need the UI from outside. The editor is not a webhook. Use a VPN or an identity-aware proxy for it; a relay forwards webhook deliveries, not interactive sessions.
  • What a flow does is yours to review. A webhook-triggered flow runs whatever its components do, with whatever credentials they hold.
  • Already compromised. If an exposed instance was vulnerable, closing the port afterward does not undo it.

More self-hosted tools that are public only for webhooks

Create a bucket, point it at your flow's webhook URL, and close the public port.

Frequently asked questions

What is CVE-2025-3248 in Langflow?

CVE-2025-3248 is an unauthenticated remote code execution flaw in Langflow versions before 1.3.0. The /api/v1/validate/code endpoint passed submitted code to Python exec() without requiring a login, so one crafted POST ran code on the server. It is fixed in Langflow 1.3.0, CISA lists it as exploited, and Trend Micro reported it being used to deliver the Flodrix botnet.

Which Langflow versions are affected by known exploited vulnerabilities?

It depends on the CVE. CVE-2025-3248 affects versions before 1.3.0, CVE-2025-34291 affects 1.6.9 and earlier (fixed in 1.7.0), CVE-2026-33017 affects 1.8.2 and earlier (fixed in 1.9.0), CVE-2026-55255 affects versions before 1.9.1, and CVE-2026-9198 affects 1.0.0 through 1.10.0 (fixed in 1.10.1). For CVE-2026-0770 the advisories list versions up to 1.7.3 and name no fixed release. Run the latest release.

Is it safe to expose Langflow to the internet?

No. Four of the six exploited Langflow bugs covered here need no login at all, and the others need only a user account or a logged-in user's browser. If the only reason Langflow is public is so outside services can trigger flows, receive those webhooks through an outbound-only relay and keep the server on a private network.

What is the Langflow webhook endpoint and does it need authentication?

A flow with a Webhook component is triggered by POST /api/v1/webhook/{flow_id}. According to the Langflow documentation, authentication is on by default (LANGFLOW_WEBHOOK_AUTH_ENABLE=True) and the caller sends a Langflow API key in the x-api-key header or query parameter. Setting it to False makes requests run as the flow owner and Langflow says to do that only in trusted environments.

Can a webhook relay protect Langflow from these vulnerabilities?

From the network-reachable ones, yes. A relay agent runs next to Langflow, connects outbound and forwards only webhook deliveries to the webhook URL, so /api/v1/validate/code, /api/v1/build_public_tmp and /api/v1/responses are not reachable from the internet. It does not help against CVE-2025-34291, which is driven through a logged-in user's browser, and it does not replace patching.

How do I check whether my Langflow server was compromised through CVE-2025-3248?

Search web and proxy logs for POST requests to /api/v1/validate/code from unknown sources, and look on the host for unexpected processes, a downloader script named docker, or an ELF binary such as e1x.x86_64, which Trend Micro lists as Flodrix indicators. If an instance older than 1.3.0 was internet-reachable, rotate every API key and credential it could read and rebuild the host.

How do I keep Langflow private but still trigger flows from GitHub or Stripe?

Run the Webhook Relay agent on the same private network as Langflow and create a bucket whose internal output points at http://localhost:7860/api/v1/webhook/FLOW_ID. Give the provider the bucket's public input URL. The agent opens only an outbound connection, so Langflow needs no public IP, port forward or reverse proxy.