我们的 AI 引擎 Neutron 在加州大学伯克利分校的 CyberGym 基准测试中取得了 97.1% 的成绩。 了解更多

深度解析

深度解析

Greeter 框架利用 Flowise RCE(CVE-2024-58351)

Flowise 2.1.4 之前允许 overrideConfig 替换 Custom JS Function 节点的 JavaScript,Greeter 框架已利用;2.1.4 已修复。

TL;DR

  • CVE-2024-58351 允许一个预测请求替换 Flowise 中 Custom JS Function 节点的 JavaScript,服务器随后执行这段代码。缺陷在于请求的 overrideConfig 字段没有允许列表。
  • Flowise 2.1.4 之前的所有版本都受影响。Era 统计到 4,372 个暴露在互联网上的 Flowise 实例,在能读取版本的 3,277 个中,有 703 个没有启用认证。
  • VulnCheck 将该漏洞评为 CVSS v3.1 9.8 Critical。Greeter 框架在 2026 年 7 月至 10 月期间对蜜罐发起了利用,VulnCheck 的 KEV 目录已收录;截至 2026 年 11 月 8 日,CISA 的 KEV 目录尚未收录。
  • 升级到 2.1.4 或更高版本,最好使用 3.1.4,它还包含 2026 年对同一代码路径的加固。请参阅“如何修复?”。

我受影响吗?

如果您运行 2.1.4 之前的 Flowise,且不受信任的用户能够访问其预测 API,就会受影响。以下条件必须全部满足:

  • 您运行 2.1.4 之前的 Flowise,形式可以是 npm 包 flowise、官方 Docker 镜像,或包含它的产品。
  • 不受信任的用户能够访问预测端点 POST /api/v1/prediction/<chatflow-id>,可以直接访问,也可以通过嵌入的聊天组件访问。
  • 这些用户能访问的聊天流中包含 Custom JS Function 节点,或者因为应用级认证未启用,他们可以自行创建一个。

受影响的 1.x 和 2.0.x 系列中,应用级认证使用 FLOWISE_USERNAME 和 FLOWISE_PASSWORD 这一对变量,两个变量都未设置时认证关闭。Era 的蜜罐在未设置这两个变量的情况下运行 Flowise 1.8.2,记录到的攻击使用了包含 Custom JS Function 节点的聊天流。

在暴露的群体中,未认证的情况很常见。Era 的普查在互联网上找到 4,372 个 Flowise 实例,从 3,277 个实例读到了版本,其中 703 个没有启用认证;703 个中有 46 个与其复现的易受攻击配置相符。

4,372 个已观测 Flowise 实例、3,277 个可读取版本、703 个无认证、46 个符合易受攻击配置的柱状图
图 1:Era 观测到的暴露 Flowise 群体,以及与该漏洞相符的无认证子集。来源:Era Security,2026 年 11 月 3 日

系列 受影响版本 修复版本
1.x 所有版本 2.1.4(2024-11-13)
2.0.x 所有版本 2.1.4(2024-11-13)
2.1.x 2.1.0 至 2.1.3 2.1.4(2024-11-13)
2.1.4 及以后 不受 CVE-2024-58351 影响 运行 3.1.4 或更高版本以获得 2026 年的加固

请检查每个安装的包版本,包括容器以及打包在其他产品中的副本:

# Global npm install
npm ls -g flowise

# Project install
npm ls flowise

# Docker: read the version inside the running container
docker exec <container> cat /usr/local/lib/node_modules/flowise/package.json | grep '"version"'

# Running instance
curl -s http://localhost:3000/api/v1/version

版本端点读取服务器上最近的 package.json,因此它显示进程实际运行的包。当镜像由较旧的包构建时,只看容器镜像标签是不够的。

如何修复?

升级到 2.1.4 或更高版本,并使用当前的 3.1.4,因为它包含同一函数的两个后续加固提交。然后确认每个聊天流的配置覆盖都已关闭。

  1. 升级软件包。全局安装运行 npm install -g flowise@3.1.4。项目安装运行 npm install flowise@3.1.4。Docker 部署拉取当前的 flowiseai/flowise 镜像,保留数据卷并重新创建容器。
  2. 打开每个聊天流,依次检查设置、配置和 Security 标签页。2.1.4 之后配置覆盖默认关闭。只启用确实需要覆盖的节点参数,因为允许列表按聊天流和节点类型保存。
  3. 在实例前增加认证。在受影响系列上设置 FLOWISE_USERNAME 和 FLOWISE_PASSWORD,或在 3.x 上创建管理员账户,并将预测 API 限制在需要的网络内。
  4. 如果暂时无法升级,请在反向代理上阻止不受信任客户端访问 POST /api/v1/prediction,关闭公开聊天流,并从这些客户端可访问的所有流程中移除 Custom JS Function 节点。这些措施减少入口,但不能修复代码。

临时措施有局限。仅靠认证不能消除缺陷:任何能创建聊天流的账户都可以添加 Custom JS Function 节点并发送覆盖;在受影响的 1.x 和 2.0.x 系列中,应用认证只有一个管理员账户。因此一个泄露的管理员密码就足够,这也是升级才是修复、代理阻止只是临时措施的原因。

根本原因是什么?

预测 API 把请求字段当作可信配置,而该配置可以替换可执行代码。Flowise 聊天流是节点图,Custom JS Function 节点有一个名为 javascriptFunction 的输入,其值是 JavaScript 源代码。2.1.4 之前,请求体中的 overrideConfig 对象在没有任何允许列表的情况下被应用到每个节点输入。以下引用自 Flowise 2.1.3 的 packages/server/src/utils/index.ts:

export const replaceInputsWithConfig = (flowNodeData: INodeData, overrideConfig: ICommonObject) => {
    const types = 'inputs'

    const getParamValues = (inputsObj: ICommonObject) => {
        for (const config in overrideConfig) {
            // If overrideConfig[key] is object
            if (overrideConfig[config] && typeof overrideConfig[config] === 'object') {
                const nodeIds = Object.keys(overrideConfig[config])
                if (nodeIds.includes(flowNodeData.id)) {
                    inputsObj[config] = overrideConfig[config][flowNodeData.id]
                    continue
                } else if (nodeIds.some((nodeId) => nodeId.includes(flowNodeData.name))) {
                    /*
                     * "systemMessagePrompt": {
                     *   "chatPromptTemplate_0": "You are an assistant" <---- continue for loop if current node is chatPromptTemplate_1
                     * }
                     */
                    continue
                }
            }

            let paramValue = inputsObj[config]
            const overrideConfigValue = overrideConfig[config]
            if (overrideConfigValue) {
                if (typeof overrideConfigValue === 'object') {
                    switch (typeof paramValue) {
                        case 'string':
                            if (paramValue.startsWith('{') && paramValue.endsWith('}')) {
                                try {
                                    paramValue = Object.assign({}, JSON.parse(paramValue), overrideConfigValue)
                                    break
                                } catch (e) {
                                    // ignore
                                }
                            }
                            paramValue = overrideConfigValue
                            break
                        case 'object':
                            paramValue = Object.assign({}, paramValue, overrideConfigValue)
                            break
                        default:
                            paramValue = overrideConfigValue
                            break
                    }
                } else {
                    paramValue = overrideConfigValue
                }
            }
            // Check if boolean
            if (paramValue === 'true') paramValue = true
            else if (paramValue === 'false') paramValue = false
            inputsObj[config] = paramValue
        }
    }

    const inputsObj = flowNodeData[types] ?? {}

    getParamValues(inputsObj)

    return flowNodeData
}

循环读取调用方发送的每个键。当键为 javascriptFunction 时,最后的赋值会用调用方的字符串替换节点的 JavaScript。流程从已存储的聊天流构建,覆盖在内存中应用到节点数据,然后节点用攻击者的代码初始化。没有任何内容写回聊天流,因此存储的定义看起来可能无害。

Custom JS Function 节点把该字符串包在异步函数中,并在 vm2 的 NodeVM 中执行。以下引用自 Flowise 1.8.2 的节点源码:

const nodeVMOptions = {
    console: 'inherit',
    sandbox,
    require: {
        external: { modules: deps },
        builtin: builtinDeps
    }
} as any

const vm = new NodeVM(nodeVMOptions)
const response = await vm.run(`module.exports = async function() {${javascriptFunction}}()`, __dirname)

内置允许列表包括 http、net 和 path 等模块,但不包括 child_process。厂商公告仍将沙箱逃逸列为该功能的影响,Era 的复现显示载荷通过 child_process.execSync() 执行 shell 命令。vm2 不是抵御恶意 JavaScript 的安全边界。由于逃逸不断出现,其维护者在 2023 年停止了该项目。

如何被利用?

攻击者把利用代码作为普通预测请求发送,因此存储的聊天流无需包含恶意代码。请求体带有一个无害的问题,以及一个 overrideConfig 对象,其 javascriptFunction 键包含要执行的阶段:

{
  "question": "hello",
  "overrideConfig": {
    "javascriptFunction": "<JavaScript that returns the command output>"
  }
}

Era 根据蜜罐流量复现的步骤如下:

  1. 访问实例,在应用认证关闭时使用或创建一个包含 Custom JS Function 节点的聊天流。框架的流程名为 ghsa-5cph-wvm9-45gj-poc。
  2. 使用上面的请求体向 POST /api/v1/prediction/<chatflow-id> 发送请求,问题使用 hello。
  3. 服务器在节点初始化前把覆盖应用到节点的 javascriptFunction 输入。
  4. 节点在 vm2 沙箱中执行调用方的 JavaScript。该阶段逃逸沙箱并到达 child_process.execSync()。
  5. 命令输出随预测响应返回。框架约 3.5 秒后再次以 hello 发送下一条命令,并重复这个循环。
  6. 后续阶段枚举主机、读取环境变量和凭据文件、查询云元数据、检查 Docker 套接字,并准备持久化和仅内存载荷。

Era 在 2026 年 7 月至 10 月的两个半月内,对四个区域的七个 Flowise 1.8.2 蜜罐统计到 4,972 条此类消息。它记录的来源地址是 TOR 出口节点 185.246.188[.]74。

修复在 2024 年 11 月就已可用,比攻击活动开始早 20 个月。差距本身就是重点:从未应用 2.1.4 更新的部署在整个攻击活动期间都可被利用。

从 2024 年 11 月的 2.1.4 修复到 2026 年 Greeter 攻击和 Era 报告的时间线
图 2:修复于 2024 年 11 月发布,比 Greeter 攻击开始早 20 个月。来源:Flowise、VulnCheck 和 Era Security,2026 年 11 月 8 日核查

攻击如何展开?

一个预测请求携带攻击者的 JavaScript,服务器在没有允许列表的情况下把它替换进节点,代码随后逃逸沙箱并以 Flowise 用户身份执行命令。

flowchart LR A["带 overrideConfig.javascriptFunction
的 POST /api/v1/prediction"] --> B["replaceInputsWithConfig 把覆盖
应用到节点输入
没有允许列表"] B --> C["Custom JS Function 节点
在 vm2 中执行调用方的
JavaScript"] C --> D["vm2 沙箱逃逸"] D --> E["child_process.execSync
以 Flowise 用户身份执行"] E --> F["侦察、.env 和 SSH 密钥、
云元数据凭据"] F --> G["持久化和仅内存
载荷准备"]

攻击者能做什么?

能访问预测 API 的攻击者会以 Flowise 进程用户身份执行命令,并读取该进程能访问的所有机密。Era 的蜜罐证据显示:

  • 以服务账户执行命令。在 Era 的蜜罐中,进程以 root 运行并拥有不受限制的 sudo,这是部署选择,不是漏洞本身的属性。
  • 主机侦察:身份、内核、发行版、进程、监听端口、路由、环境、容器标识和 Linux 能力。
  • 凭据发现:.env 文件、SSH 私钥和 authorized_keys、TLS 客户端证书、SQL 和 SQLite 文件,以及 /root/.flowise/encryption.key 中的 Flowise 加密密钥。
  • 通过实例元数据服务窃取云凭据,随后使用工作负载云身份被允许的操作。
  • 利用挂载的 Docker 套接字,可能控制主机和其他容器。
  • 通过 cron 和 systemd 单元实现持久化,并通过 memfd_create() 准备从内存执行的载荷。

条件见“我受影响吗?”:2.1.4 之前的版本、可访问的预测 API,以及包含 Custom JS Function 节点的聊天流。之后的影响取决于进程用户、挂载的卷、Docker 套接字和工作负载绑定的云身份。Era 的报告没有公布对生产 Flowise 部署的成功入侵;利用证据来自其蜜罐。

为什么修复有效?

修复让每次覆盖都需要按聊天流和按节点参数显式启用,因此除非运维人员启用,请求不能再替换 javascriptFunction。Flowise 2.1.4 增加了 getAPIOverrideConfig(),它读取聊天流的 API 配置:

export const getAPIOverrideConfig = (chatflow: IChatFlow) => {
    try {
        const apiConfig = chatflow.apiConfig ? JSON.parse(chatflow.apiConfig) : {}
        const nodeOverrides = apiConfig.overrideConfig && apiConfig.overrideConfig.nodes ? apiConfig.overrideConfig.nodes : {}
        const variableOverrides = apiConfig.overrideConfig && apiConfig.overrideConfig.variables ? apiConfig.overrideConfig.variables : []
        const apiOverrideStatus = apiConfig.overrideConfig && apiConfig.overrideConfig.status ? apiConfig.overrideConfig.status : false

        return { nodeOverrides, variableOverrides, apiOverrideStatus }
    } catch (error) {
        return { nodeOverrides: {}, variableOverrides: [], apiOverrideStatus: false }
    }
}

replaceInputsWithConfig() 现在接收按节点的允许列表,并在写入任何输入前检查:

const isParameterEnabled = (nodeType: string, paramName: string): boolean => {
    if (!nodeOverrides[nodeType]) return false
    const parameter = nodeOverrides[nodeType].find((param: any) => param.name === paramName)
    return parameter?.enabled ?? false
}

// ...
if (!isParameterEnabled(flowNodeData.label, config)) {
    continue
}

现在覆盖需要两次确认:聊天流上的 overrideConfig.status 必须为 true,节点类型必须把该参数列为已启用。默认值为 false,除非运维人员添加,javascriptFunction 不在列表中。同样的检查应用于预测、代理图和 upsert 路径。

第一个允许列表并没有结束问题。提交 c8282c97fb(2026-02-06)移除了一个 FILE-STORAGE:: 例外,该例外允许值跳过启用检查,并把 NODE_OPTIONS 加入 MCP 工具拒绝的环境变量。提交 23b997ee5e(2026-05-07)停止把原始 overrideConfig 对象展开到流程数据中,此前这留下了调用方控制键的第二条路径。2026-07-29 发布的 Flowise 3.1.4 包含这两项,因此应运行该版本。

如何检查是否已遭入侵?

在 Flowise 请求日志和主机上查找框架的标记;即使聊天消息只包含 hello,攻击活动仍会留下特征字符串。Era 公布了以下指标:

  • JSON 正文包含 overrideConfig 和 javascriptFunction 的预测请求。
  • 名为 ghsa-5cph-wvm9-45gj-poc 的聊天流。
  • 包含 VP_DOCKER、VP_MEMFD、VP_W_OK 或 VP_INIT_OK 的聊天消息,匹配 vp-alive-[0-9a-f]{8} 的信标响应,以及匹配 __VP_EXIT_[0-9]+ 的退出报告。
  • 进程名 polld-keeper-{8-hex} 和 varrun-watcher-{8-hex}。
  • /etc/cron.d/syslog-cronrun-{8-hex} 的 cron 文件,或 /etc/systemd/system/taskd-sysrun-{8-hex}.service 的 systemd 单元。
  • 两个持久化组件共用的配置哈希 07f8464533b3446e918feff1ea14c4ae。
  • 来自 TOR 出口节点 185.246.188[.]74 的连接。

在 Flowise 主机以及容器能访问其 Docker 套接字的任何主机上运行以下检查:

# Flowise request logs (Docker example; adjust the container name)
docker logs <container> 2>&1 | grep -Ei 'overrideConfig|javascriptFunction|ghsa-5cph-wvm9-45gj'

# Persistence artifacts
sudo find /etc/cron.d /etc/systemd/system -maxdepth 1 \( -name 'syslog-cronrun-*' -o -name 'taskd-sysrun-*.service' \)

# Framework processes
ps -eo pid,user,args | grep -E 'polld-keeper-|varrun-watcher-'

命中是线索,不是证据。Flowise 自己在文档和 SDK 中使用 overrideConfig,所以提到该字段的请求可能是合法的。该字段与 javascriptFunction 同时出现,或与聊天流名称和 VP_ 标记同时出现,才是更强的信号。Era 的证据来自蜜罐;没有公布生产受害者的指标。

时间线

  • 2024-11-13:Flowise 2.1.4 发布,加入按聊天流的覆盖允许列表。
  • 2024-11-21:Flowise 公告 GHSA-5cph-wvm9-45gj 发布,评级为 High,CVSS v4.0 8.6。
  • 2026-02-06:提交 c8282c97fb 移除了允许列表的 FILE-STORAGE:: 绕过。
  • 2026-05-07:提交 23b997ee5e 停止把原始 overrideConfig 对象展开到流程数据中。
  • 2026-06-20:VulnCheck 发布 CVE-2024-58351,CVSS v3.1 9.8。
  • 2026-11-03:Era 发布对 Greeter 框架的分析,其蜜罐在 2026 年 7 月至 10 月记录了 4,972 个预测请求。
  • 2026-11-08:本文发布。

常见问题

Flowise 2.1.4 够用吗?

对 CVE-2024-58351 够用,因为 2.1.4 增加了漏洞所绕过的允许列表。仍应运行 3.1.4 或更高版本,因为 2026 年的两个提交关闭了第一个允许列表的绕过,并移除了调用方控制键的第二条路径。

认证能阻止攻击吗?

仅靠认证不能。认证消除了未认证的情况,但任何能创建聊天流的账户都可以添加 Custom JS Function 节点并发送覆盖。在受影响的 1.x 和 2.0.x 系列中,应用认证只有一个管理员账户,因此一个泄露的密码就足够。

聊天流中必须有 Custom JS Function 节点吗?

是。覆盖替换的是输入值,而 javascriptFunction 是 Custom JS Function 节点的输入。未认证的攻击者可以创建包含该节点的流程;Era 蜜罐中观察到的流程名为 ghsa-5cph-wvm9-45gj-poc。

是否被用于攻击真实组织?

Era 是在自己的蜜罐上观测到 Greeter 框架,而不是针对具名受害者。它还发现 4,372 个暴露在互联网上的 Flowise 实例,以及 46 个与其复现的易受攻击配置相符的无认证实例。这是暴露证据,不是入侵证明。

为什么 Flowise 评为 High,而 VulnCheck 评为 Critical?

Flowise 公告评级为 High,其 CVSS v4.0 向量使用 PR:H,假设攻击者已拥有高权限,评分为 8.6。CVE 编号机构 VulnCheck 使用 PR:N,在 CVSS v3.1 上评为 9.8,在 CVSS v4.0 上评为 9.3。本文描述的利用路径在应用认证关闭时只需要网络访问,与 VulnCheck 的向量一致。

如果本周无法升级怎么办?

在反向代理上阻止不受信任客户端访问 POST /api/v1/prediction,关闭公开聊天流,并从这些客户端可访问的所有流程中移除 Custom JS Function 节点。然后安排升级;如果主机曾暴露,轮换 Flowise 进程能读取的凭据。

使用 Ostorlab 发现暴露的 Flowise 实例

Ostorlab 的攻击面发现会清点组织中暴露在互联网上的服务,帮助您找到运行 Flowise 的公开主机并优先安排升级。

参考文献

  • Flowise 公告 GHSA-5cph-wvm9-45gj,2024-11-21 发布,包含 overrideConfig 影响列表和 2.1.4 修复:https://github.com/FlowiseAI/Flowise/security/advisories/GHSA-5cph-wvm9-45gj(2026 年 11 月 8 日核查)
  • CVE-2024-58351 记录,2026-06-20 发布,包含 CVSS v3.1 9.8 和 v4.0 9.3 评分以及 CISA ADP 的 SSVC 块:https://www.cve.org/CVERecord?id=CVE-2024-58351(2026 年 11 月 8 日核查)
  • VulnCheck 公告《Flowise - Remote Code Execution via overrideConfig Parameter》,2026-06-20 发布:https://www.vulncheck.com/advisories/flowise-remote-code-execution-via-overrideconfig-parameter(2026 年 11 月 8 日核查)
  • Flowise 2.1.4 修复提交《Enable/disable variables in override configuration》,2024-11-13:https://github.com/FlowiseAI/Flowise/commit/537aa51ef8(2026 年 11 月 8 日核查)
  • Flowise npm 包,2.1.4 于 2024-11-13 发布,当前 3.1.4 于 2026-07-29 发布:https://www.npmjs.com/package/flowise(2026 年 11 月 8 日核查)
  • Flowise 提交 c8282c97fb《Fix Paramater Override Bypass》,2026-02-06:https://github.com/FlowiseAI/Flowise/commit/c8282c97fb(2026 年 11 月 8 日核查)
  • Flowise 提交 23b997ee5e《remove ungated overrideConfig spread》,2026-05-07:https://github.com/FlowiseAI/Flowise/commit/23b997ee5e(2026 年 11 月 8 日核查)
  • Flowise 1.8.2 的 Custom JS Function 节点源码,包含 NodeVM 包装:https://github.com/FlowiseAI/Flowise/blob/5e4d640ed7/packages/components/nodes/utilities/CustomFunction/CustomFunction.ts(2026 年 11 月 8 日核查)
  • Era Security《You Had Me at Hello: Inside The Greeter, A Chinese-Language Framework Targeting AI Infrastructure》,2026-11-03,包含攻击阶段、暴露数字和指标:https://era.security/blog/greeter-flowise-ai-infrastructure-attack(2026 年 11 月 8 日核查)
  • Flowise 文档《Prediction》,包含端点、overrideConfig 字段和默认关闭的配置覆盖:https://docs.flowiseai.com/using-flowise/prediction(2026 年 11 月 8 日核查)
  • Flowise 文档《Application》认证,包含 FLOWISE_USERNAME 和 FLOWISE_PASSWORD 变量:https://docs.flowiseai.com/configuration/authorization/app-level(2026 年 11 月 8 日核查)
  • CISA 已知被利用漏洞目录,核查 CVE-2024-58351:https://www.cisa.gov/known-exploited-vulnerabilities-catalog(2026 年 11 月 8 日核查)