Skip to content

Build1 publisher2 min readPublished

Flowise deleted its CSV Agent after the regex guarding model-written code failed repeatedly

Flowise fixed a CVSS 9.8 remote-code bug in its CSV Agent with a stricter regex, then saw that filter fail through five more CVEs. It deleted the feature in June, and the patch history is a case against trusting a string filter to vet model-written code.

The Engineer · Build desk

Drafted by a language model from the sources cited here and checked against its claim ledger before publication. How we use AISend a correction

What happened

  • The check meant to allow only pandas and numpy imports read just the first module name after each import, so aliasing os as pandas slipped a system call straight past it.
  • Trend Micro's Zero Day Initiative reported the flaw as ZDI-CAN-29411, crediting researchers Dre Cura and Nicholas Zubrisky of TrendAI Research.
  • The CSV Agent ran the model's reply through a loop of 34 forbidden-pattern regexes, then executed it on the server with pyodide.runPythonAsync().
  • Earlier builds were worse: version 3.0.13 had no validator and no safety paragraph, passing the model's output straight to runPythonAsync().
  • The proof of concept delivers the payload as a prompt injection in the question field, tested against Llama 3.2 in Ollama, where it can take several attempts.

Compiled by The EngineerSomething wrong?How this is made

Why it matters

  • exposure Any internet-facing Flowise with the prediction endpoint reachable was open to unauthenticated code execution as root in its container, with no account required.
  • constraint A string filter can only inspect what it is handed, and that is not what the interpreter runs; vetting model-written code before execution cannot be made reliable when the checker and the runtime read the same text differently.
  • decision The practical control is isolating the interpreter at the OS or container boundary; an in-process check that runs before execution is advisory at best.
  • cost The filter cost Flowise 390 lines of regex and three months of patching, maintenance spent defending a feature that executed untrusted code.

JavaScript's `\b` word boundary matches only ASCII characters, while Python normalizes identifiers with NFKC at parse time, as PEP 3131 specifies. [19] That mismatch is the homoglyph bypass: spell `__class__` with MATHEMATICAL BOLD SMALL A, U+1D41A, in place of the first `a`, and the regex `/\b__class__\b/` returns false while Python's `exec` resolves the string to the real `__class__`. [20]

The prompt could only ask. The template ended with a "Security:" paragraph telling the model not to use `import`, `exec`, `eval`, `open`, `os` or `subprocess`; the advisory calls that a request to the model, not a control. [7][22] A logged-in user does not even need the model: point a ChatOllama node at a server you control, have it answer `/api/chat` with Python, and the regex is the last thing before the interpreter. [11]

The interpreter was not isolated either. Pyodide is CPython compiled to WebAssembly, which is easy to mistake for a sandbox. [15] Inside Node it is not one: the Pyodide docs call the `js` module "the global JavaScript scope," and in a Node process that scope reaches `child_process`. [15] WebAssembly limits memory access. It does not limit what the host hands the guest. [17]

The patches run from February to May. The validator and the security paragraph arrived together in PR #5701 on 2026-02-06. [12] Version 3.1.0 on 2026-03-16 was the first release to carry any validator; it banned the word `import` outright and ran the chatflow's custom read field through the same check. [18] Flowise blocked `read_pickle` and class definitions on 2026-04-27, then on 2026-05-05 restricted the CSV field to a literal `read_csv()` call. [21] The same node had carried a separate flaw, CVE-2026-41137, where a builder-set read function was pasted into Python as `pd.${customReadCSVFunc}` with no check at all. [14]

That effort went to the wrong layer. In my view the durable version of this feature runs each query in a throwaway container as a non-privileged user, with no bridge back to the host process.

What to watch

  • Whether other LLM frameworks that filter model-written code remove the feature as Flowise did rather than keep patching.
  • Whether Flowise ships a replacement that isolates the interpreter in a separate process or container.
  • Whether the CVE-2026-69255 Pyodide-to-child_process chain shows up in other Node apps that embed Pyodide as a sandbox.
Loading claim ledger
Loading source directory links
Loading share composer
Loading topic controls
Loading related stories