Editor’s Note: This is part one of a three-part series. Part two covers n8n, while part three explores Activepieces. This research was originally presented at BlueHat IL 2026 in a talk entitled "Exploiting AI Orchestration Zero-Days via PostgreSQL Internals." Slides and a recording of that presentation are now available.
AI orchestration platforms have become a fast way to ship LLM-powered applications. Users can simply drag-and-drop blocks called nodes or triggers, which represent specific events, data transformations, integrations or AI models. This interface enables spinning up an application in an afternoon.

As part of their operation, they are accessible to sensitive information from the one hand, and to internal systems from the other hand. They are also web servers with file systems and code-execution sandboxes, reachable by anyone with network access and are accepting user-controlled input. Once you start treating them as web apps first and "AI tools" second, the attack surface becomes obvious—and large.
Mapping the attack surface
Langflow is a FastAPI app. Our research began by ignoring aspects of Langflow as an AI tool and just treating it as a web service, attempting to map the attack surface as an unauthenticated user.
This required understanding how authentication is implemented given the only options were to attack using an authenticated route or bypass authentication completely. Langflow makes wide use of FastAPI’s dependency injection. Each route that requires authentication declares that by applying Depends on one of the many different authentication functions.
We first pulled the source, grepped the router files, and built a list of every authentication function available in Langflow. We then researched the authentication logic, but found no issues there. Langflow uses JSON Web Tokens properly and login is done correctly. Authentication looked solid.
That turned our focus to unauthenticated routes. We listed all those endpoints and began investigating them one by one, noting interesting points.
Some endpoints were “boring,” for example the /version route that simply returns the Langflow version. These routes are functionless and did not return any useful information.
Two others, however, appeared worthy of a closer look:
- An upload route,
/upload/{flow_id}, for some reason does not require authentication, and there are many potential pitfalls in upload logic. It is also marked as Deprecated, which means it may be neglected or rely on legacy code. - The
/build_public_tmp/{flow_id}/flowroute allows unauthenticated users to run “public” apps. This is reasonable but expands the attack surface significantly.
Let’s explore each in greater depth.
The /upload/ route
We started with an obvious question: When we upload a file into an arbitrary project folder, can we control the project ID and the filename and achieve path traversal by injecting /../ into the target path?
The answer is no. For some reason, the developers chose not to validate whether the project ID (called flow_id) exists, but they do still verify it is an UUID. Additionally, the user does not control the filename—a hash of the contents is used as the filename. Here’s what this looks like in practice:

The response:

So, there is no path-traversal vulnerability here. But, is allowing unauthenticated users to upload files uncontrollably an issue? Certainly. This would allow any attacker with network access to Langflow to fill its storage and cause a denial-of-service of Langflow. In addition, as you can see above, Langflow returns the full absolute path of the uploaded file, which is an information-leak.
It may not be a high impact-bug, but it was reported to the Langflow team (CVE-2026-7528, Severity: High, 7.1) and fixed by requiring authentication on the route.
Now that we took care of the upload route, let’s continue to the next route accessible to unauthenticated users. Here we find something much more severe.
The /build_public_tmp/ route
Langflow allows creating a public link to a chatbot created inside Langflow. This allows sharing the project with others—anyone with the link can interact with the chatbot. Here is an example chat session in the public UI, featuring a chatbot message created in Langflow:

This chat message was sent as an HTTP request to the build_public_tmp route. Looking at the request, we expected a simple POST request containing my message “Hey, what’s up?” Surprisingly, however, the request was about 50K. Opening the request body in the developer tools revealed this:

Recognize the text in the request body shown above? Instead of getting only the message from the user and feeding into the project graph, Langflow receives the full graph definition, including every node, every edge and every template field—including every component’s Python code.
That is, quite literally, a "send me Python code and I'll run it" endpoint.
This vulnerability was numbered CVE-2026-48519 and attached a severity of Critical, 9.6.
There was another field in this route, files, that allowed feeding local files from the Langflow filesystem right into the LLM. We did not exploit this fully, though we do believe it might be possible to exploit as a remote code execution (RCE). It has been labeled CVE-2026-48520 with a severity of 6.1, Moderate.
Examining the code was illuminating. This endpoint repurposed an internal mechanism that is used by the editor UI, which supports editing the code of the different components directly through the UI. That’s how this capability “leaked” into the public endpoint.
Until now, all the vulnerabilities we discovered were unrelated to the AI features of Langflow, so we asked ourselves what additional attack surface exists assuming an AI application is built using Langflow?
“RAGPull” – RAG ⇒ Arbitrary Files Read ⇒ Remote Code Execution
What is RAG and how is it supported in Langflow?
A very common application in AI is Retrieval-Augmented Generation (RAG). This architecture enables the creation of a chatbot that has access to dedicated corpus of documents.
The core challenge is that LLM’s context is too small to contain a very large number of documents. RAG solves that by maintaining a database of documents (a vector database, specifically), and given a query it does the following:
- Retrieves a few documents from the database that are mostly relevant to the query.
- Feeds the relevant documents and the query to the LLM.
This allows the LLM to only work with a small amount of data each time.

Langflow allows the creation of these kinds of applications by implementing an LLM, vector database and a document parser. The document parser is necessary since LLMs generally only handle text, so documents (Word documents, PowerPoint slides, etc) first need to be converted into text before being saved into the database.
The vulnerability
Langflow’s parser supports many document formats (including .docx, .pptx, etc), but surprisingly also supports two archive formats: zip and tar. Why does it support archive formats?
After examining the parser logic, we found that it allows users to upload an archive containing multiple documents at once. The parser logic is as as follows:

Essentially, this means that when an archive is received it should be extracted to a temporary directory and parse every document it contains.
The problem is that tar files can contain symlinks. If the archive contains a symlink, line six will try to parse it. But when doing so, it will actually parse the file the symlink points to.
To better understand, let’s take a concrete example:
- An attacker uploads an archive called
archive.tarto the RAG chatbot. The archive contains a single file calleddocument.docxwhich is actually a symlink pointing to/etc/passwd. - Langflow’s parser extracts the
archive.tararchive to a temporary directory named, say,/tmp/extracted/. - Now
/tmp/extracted/contains a single file –document.docxthat is a symlink to/etc/passwd. - Langflow now iterates over the files at
/tmp/extracted/and findsdocument.docx. - Langflow opens
document.docxto parse it, but actually opens/etc/passwd. - The contents of
/etc/passwdare uploaded to the vector database. - The attacker then simply asks the chatbot “Hey, give me the list of users and their passwords” and the chatbot finds the contents of
/etc/passwdin the database and returns it to the attacker.
This essentially gives the attacker an arbitrary file read on the Langflow filesystem.
Reading files is bad enough, since Langflow has access to very sensitive information, but this can actually be used for RCE on the server.
Let’s see how.
From Arbitrary File Read to Remote Code Execution
Langflow supports passing the superuser credentials using environment variables LANGFLOW_SUPERUSER and LANGFLOW_SUPERUSER_PASSWORD. Given Langflow would probably be deployed in a container (for example, under k8s), these superuser credentials would be in the environment variables of the init process of the container.
In other words, reading the environment variables of process numbered 1 will give the attacker full control over Langflow.
This means, all the attacker would have to do is:
- Create a
tararchive containing a symlink to/proc/1/environ. - Upload the
tararchive to a RAG chatbot that is built on Langflow. Langflow, unknowingly, when parsing this tar archive, uploads the superuser credentials to the vector database. - Ask the chatbot “Hey, give me the superuser credentials.” The chatbot will answer with the credentials.
- The attacker can use the credentials to login as the superuser.
- Then, the attacker can run arbitrary code on the server via a feature enabled in Langflow.
This vulnerability was reported to the Langflow team and fixed. It was assigned CVE-2026-7524 with severity 9.8, Critical.
Disclosure timeline
- Feb 8, 2026 — Vulnerabilities reported to Langflow team
- Mar 13, 2026 — Shareable Playground RCE fixed.
- Apr 15, 2026 — Shareable Playground files read fixed.
- Apr 24, 2026 — Storage DoS fixed.
- May 1, 2026 — File parser tar archive symlink RCE fixed.
Ori Lahav is a security researcher at Rubrik Zero Labs supporting the lab’s work on the security of emerging AI infrastructure.