ChatterBot任意写入漏洞CVE-2026-58198
ChatterBot 是一款开源的Python对话机器人库,轻量、开箱即用,不用复杂大模型,依靠传统机器学习 + 语料匹配实现自动对话回复。
一、基本情况
ChatterBot 是一款基于机器学习、用于开发聊天机器人的对话引擎,无真正上下文理解,因此可以用于快速搭建本地闲聊/问答机器人。

ChatterBot 是轻量离线Python聊天机器人工具,靠问答语料匹配实现自动回复,适合简易 FAQ、入门 NLP,不适合复杂深度对话场景。
栋科技漏洞库关注到 ChatterBot 在 1.2.14 之前版本中存在的符号链接跟随任意写入,现已追踪CVE-2026-58198,CVSS 3.X评分5.5。
二、漏洞分析
CVE-2026-58198安全漏洞是一个存在于 ChatterBot 相关版本中的可通过 UbuntuCorpusTrainer 进行本地符号链接跟随任意写入漏洞。
该漏洞源于ChatterBot 的 UbuntuCorpusTrainer.extract() 函数使用了用户家目录下可预测的输出路径 ~/ubuntu_data/ubuntu_dialogs,
它采用“先判断是否存在,不存在再创建目录”的竞态逻辑(`if not os.path.exists: os.makedirs`),
之后执行 `tar.extractall(path=self.data_path)` 解压归档包。
这就导致本地攻击者可以提前在该固定路径放置软链接时,os.path.exists() 会跟随软链接判定路径已存在,跳过目录创建步骤;
后续解压操作会顺着软链接,将归档内文件写入攻击者指定的任意目录。
项目内置 safe_extract 函数仅校验压缩包内文件名(防御压缩包路径穿越漏洞zip-slip),并未校验解压目标目录本身,
无法识别self.data_path为软链接,这也是本漏洞与压缩包路径穿越、不安全文件创建TOCTOU类漏洞的核心区别。
具体的漏洞逻辑如下:
1、漏洞详情
可预测输出目录相关代码(第535至546行)
home_directory = os.path.expanduser('~')
self.data_directory = kwargs.get(
'ubuntu_corpus_data_directory',
os.path.join(home_directory, 'ubuntu_data') # ~/ubuntu_data — predictable
)
self.data_path = os.path.join(
self.data_directory, 'ubuntu_dialogs' # ~/ubuntu_data/ubuntu_dialogs
)
2、先校验后创建逻辑(第621-622行)
def extract(self, file_path: str):
if not os.path.exists(self.data_path): # ← follows symlink → True → skips makedirs
os.makedirs(self.data_path) # ← never reached if symlink exists
3、通过软链接实现文件越界解压(第633至644行)
def safe_extract(tar, path='.', members=None, *, numeric_owner=False):
for member in tar.getmembers():
member_path = os.path.join(path, member.name)
if not is_within_directory(path, member_path): # ← validates MEMBER names only
raise Exception('Attempted Path Traversal in Tar File')
tar.extractall(path, members, numeric_owner=numeric_owner) # ← path is symlink → writes to target
safe_extract(tar, path=self.data_path, ...) # self.data_path = symlink → attacker dir
safe_extract会对self.data_path执行os.path.abspath(directory),
该方法会解析软链接真实路径,解压根目录就会变为攻击者指定目录。
压缩包内合规文件名都以解析后的受控目录为基准,可轻松通过目录边界校验。
三、POC概念验证
(一)验证步骤
1、运行环境
chatterbot 1.2.13 (pip install)
Python 3.11.0
2、利用步骤
管理员已设置登录后刷新可查看3、脚本输出结果

(二)修复建议
解压前判断目标输出目录,若为软链接则直接拒绝操作:
def extract(self, file_path: str):
if os.path.islink(self.data_path):
raise self.TrainerInitializationException(
f'Refusing to extract to symlink: {self.data_path}')
if not os.path.exists(self.data_path):
os.makedirs(self.data_path)
...
四、影响范围
ChatterBot ≤ 1.2.13
五、修复建议
ChatterBot ≥ 1.2.14
六、参考链接
管理员已设置登录后刷新可查看