Server-Side ReDoS in skill import endpoint via unescaped GitHub URL path in RegExp constructor

在自托管 Docker 部署的 LobeChat 桌面应用(Electron)中,任何已认证用户调用 agentSkills.importFromGitHub tRPC 端点,并提交一个包含恶意正则模式(如 (a+)+ )的 GitHub URL 时触发。

Server-Side ReDoS in skill import endpoint via unescaped GitHub URL path in RegExp constructor

Server-Side ReDoS in skill import endpoint via unescaped GitHub URL path in RegExp constructor

快速结论:该问题发生在 LobeChat 自托管服务器中,当通过 agentSkills.importFromGitHub 端点导入技能时,用户提供的 GitHub URL 路径未经过正则转义,直接传入 RegExp 构造函数,导致可被恶意利用造成服务器端拒绝服务(ReDoS)。优先排查服务器版本是否已应用完整修复(escapeRegExp 或非正则匹配方式),而不仅仅是 PR #16332。

问题场景

在自托管 Docker 部署的 LobeChat 桌面应用(Electron)中,任何已认证用户调用 agentSkills.importFromGitHub tRPC 端点,并提交一个包含恶意正则模式(如 (a+)+)的 GitHub URL 时触发。

报错原文

// 恶意输入触发 ReDoS(服务器端无报错,但事件循环阻塞 50+ 秒)
// 调用: POST /trpc/agentSkills.importFromGitHub
// 请求体: {"json":{"gitUrl":"https://github.com/attacker/crafted-repo/tree/main/(a+)+"}}

// 内部构造的正则:
new RegExp('^[^/]+/(a+)+/SKILL\\.md$')

// 备选报错: 输入 [invalid 路径时抛出 SyntaxError
// SyntaxError: Unterminated character class

原因分析

src/server/services/skill/parser.tsfindSkillMd 方法中(第 204 行),用户提供的 basePath(来自 GitHub URL 路径)仅经过 replaceAll(/^\/|\/$/g, '') 去除首尾斜杠,而未对正则特殊字符进行转义。当 basePath 包含如 (a+)+ 这样的回溯模式时,new RegExp 构造的正则表达式在 .test() 调用时会对 ZIP 包内所有条目路径进行同步匹配,导致灾难性回溯,阻塞 Node.js 事件循环。

环境排查

  • LobeChat 版本:v2.1.57(问题存在版本,其他版本可能也存在)
  • 部署方式:Self hosting Docker
  • 认证状态:已认证用户(无需管理员权限)
  • 检查 PR #16332 是否已合并:该 PR 仅修复了斜杠修剪正则的 ReDoS,未添加 escapeRegExp 转义

解决步骤

  1. 确认当前代码状态:检查 src/server/services/skill/parser.tsfindSkillMd 方法是否已对 basePath 进行正则转义。若仅应用了 PR #16332,则修复不完整。
  2. 完整修复方案(需自行补丁):basePath 传入 new RegExp(...) 之前,添加转义逻辑,例如:
    const escapedBasePath = basePath.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
  3. 替代方案:将正则匹配替换为精确字符串匹配,避免使用 RegExp 构造函数。可参考使用 normalizedPath.startsWith(...) 或基于 path 模块的精确路径判断。
  4. 临时缓解措施:若无法立即修复,可限制 agentSkills.importFromGitHub 端点的调用频率,或仅允许受信任用户访问该功能(通过修改权限配置)。

验证方法

修复后,使用以下恶意 payload 进行测试:

POST /trpc/agentSkills.importFromGitHub
Authorization: Bearer 
Content-Type: application/json

{"json":{"gitUrl":"https://github.com/attacker/crafted-repo/tree/main/(a+)+"}}

确认服务器不再出现长时间阻塞(正常应快速返回错误或成功,而非 50+ 秒延迟)。同时测试 [invalid 路径是否返回 500 错误而非抛出未捕获异常。

参考来源

lobehub/lobe-chat #16494

相关安全公告:GHSA-35fp-xcr7-6v4h(非公开)

相关 PR(修复不完整):PR #16332 – Avoid OOM When Importing Skills from Large GitHub Repos

celebrityanime
celebrityanime
文章: 10761

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注