From b08c335bb4431a5d067c27364772ec809c62cf97 Mon Sep 17 00:00:00 2001 From: jxxghp Date: Mon, 25 May 2026 07:58:10 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E4=BC=98=E5=8C=96=20execute=5Fcommand?= =?UTF-8?q?=20=E5=B7=A5=E5=85=B7=E7=9A=84=20rm=20-rf=20=E6=8B=A6=E6=88=AA?= =?UTF-8?q?=E9=80=BB=E8=BE=91=EF=BC=8C=E4=BB=85=E7=A6=81=E6=AD=A2=E5=88=A0?= =?UTF-8?q?=E9=99=A4=E6=A0=B9=E7=9B=AE=E5=BD=95=E6=88=96=E4=B8=80=E7=BA=A7?= =?UTF-8?q?=E7=9B=AE=E5=BD=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/agent/tools/impl/execute_command.py | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/app/agent/tools/impl/execute_command.py b/app/agent/tools/impl/execute_command.py index cc25eeb8..69d58927 100644 --- a/app/agent/tools/impl/execute_command.py +++ b/app/agent/tools/impl/execute_command.py @@ -30,7 +30,6 @@ READ_CHUNK_SIZE = 4096 KILL_GRACE_SECONDS = 3 COMMAND_CONCURRENCY_LIMIT = 2 COMMAND_FORBIDDEN_KEYWORDS = ( - "rm -rf / ", ":(){ :|:& };:", "dd if=/dev/zero", "mkfs", @@ -258,6 +257,29 @@ class ExecuteCommandTool(MoviePilotTool): if keyword in command: raise ValueError(f"命令包含禁止使用的关键字 '{keyword}'") + # 检查是否使用了 rm -r/R 删除根目录或一级目录,防止误杀多级目录 + import re + import os.path + tokens = re.split(r'\s+', command.strip()) + if any(t == "rm" or t.endswith("/rm") for t in tokens): + has_r = False + for token in tokens: + if token.startswith("-") and ("r" in token or "R" in token): + has_r = True + break + + if has_r: + for token in tokens: + # 提取可能包含目标路径的部分(去除重定向、管道、分号等末尾干扰) + m = re.match(r'^([^;\|&><]+)', token) + if m: + clean_token = m.group(1).strip('"\'') + # 仅对绝对路径进行一级目录限制 + if clean_token.startswith('/'): + norm_path = os.path.normpath(clean_token) + if re.match(r'^/[^/]*$', norm_path) or re.match(r'^/[^/]*/$', norm_path): + raise ValueError(f"不允许使用 rm 命令删除根目录或一级目录: {clean_token}") + @staticmethod def _normalize_timeout(timeout: Optional[int]) -> tuple[int, Optional[str]]: """限制一次性执行命令的最长运行时间。"""