From 1f37cd3268c6b7db4fc41d081b945b44390207aa Mon Sep 17 00:00:00 2001 From: cnbugs Date: Sat, 25 Jul 2026 13:52:19 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20etcdutl=20snapshot=20=E6=9C=AA=E7=9F=A5?= =?UTF-8?q?=E5=AD=90=E5=91=BD=E4=BB=A4=E5=BA=94=E6=8B=92=E7=BB=9D=E8=80=8C?= =?UTF-8?q?=E9=9D=9E=E9=BB=98=E8=AE=A4=E5=BD=93=E5=86=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 修复验证中发现的安全漏洞: - etcdutl snapshot 原会默认返回 write (需审批), 现改为显式拒绝 (ValueError) - 新增 _ETCDUTL_SNAPSHOT_WRITE = {restore, make} 显式枚举写子命令 - 同时补充 etcdctl defrag 为写操作 (需审批) 验证: 65 项 ad-hoc 检查全部通过, 56 个单元测试通过 --- backend/agent_tools.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/backend/agent_tools.py b/backend/agent_tools.py index 514c1de..fc414ff 100644 --- a/backend/agent_tools.py +++ b/backend/agent_tools.py @@ -133,7 +133,7 @@ SHELL_READ_ONLY_COMMANDS: dict[str, set[str] | None] = { # etcdctl 单段式只读 verb _ETCDCTL_READ_VERBS = {"get", "watch", "version", "lock", "lease", "move-leader", "leader"} # etcdctl 单段式写 verb (需人工审批) -_ETCDCTL_WRITE_VERBS = {"put", "del", "delete", "compact", "txn", "snapshot"} +_ETCDCTL_WRITE_VERBS = {"put", "del", "delete", "compact", "txn", "snapshot", "defrag"} # etcdctl 两段式 (verb, subverb) 只读组合 _ETCDCTL_READ_SUBVERBS = { "endpoint": {"status", "health", "hashkv"}, @@ -154,6 +154,8 @@ _ETCDCTL_WRITE_SUBVERBS = { } # etcdutl snapshot 只读子命令 _ETCDUTL_SNAPSHOT_READ = {"status", "hash"} +# etcdutl snapshot 写子命令 (需人工审批) +_ETCDUTL_SNAPSHOT_WRITE = {"restore", "make"} # 系统修改命令白名单:需要人工审批 SHELL_WRITE_COMMANDS: dict[str, set[str] | None] = { @@ -233,7 +235,9 @@ def classify_shell_command(command: str) -> CommandDecision: if ev == "snapshot": if esub in _ETCDUTL_SNAPSHOT_READ: return CommandDecision("read", False, ev, parts[1:]) - return CommandDecision("write", True, ev, parts[1:]) + if esub in _ETCDUTL_SNAPSHOT_WRITE: + return CommandDecision("write", True, ev, parts[1:]) + raise ValueError(f"etcdutl snapshot 不支持子命令: {esub}") if ev == "version": return CommandDecision("read", False, ev, parts[1:]) raise ValueError(f"etcdutl 不支持该子命令: {ev}")