前言
JiuwenSwarm 基于 openJiuwen 框架实现了多 Agent 分布式协作机制。在 Team Agent 模式下,Leader 和 Teammate 通过共享工作空间协作完成任务。然而,当 Agent 需要执行系统命令、读写敏感目录时,缺乏有效的安全边界会导致不可控的风险。本文深入解析 JiuwenSwarm 在本地执行环境中的权限隔离设计:命令工具层的危险命令检测、分层策略(tiered_policy)的权限机制、外部目录访问控制,以及内置安全规则的触发逻辑。
一、为什么需要权限隔离与风险防控
在 Agent 执行环境里,"命令执行"是一个核心能力。Agent 需要调用 shell 脚本操作文件系统、需要通过 git 提交代码、需要启动子进程完成编译任务。这些操作在带来灵活性的同时,也引入了显著的安全风险。
执行上下文的双重性 是最根本的问题。当 LLM 调用一个工具(如 Bash 或 mcp_exec_command)时,这个工具运行在宿主机的操作系统上下文中。如果没有任何限制,Agent 可以执行任意命令,包括删除系统文件、格式化磁盘、窃取敏感数据。"你的 AI 助手可以删除你的整个 home 目录"------这不是假设,而是一个真实需要防范的风险。
Teammate 的信任层级进一步复杂化了这个问题。在 JiuwenSwarm 的分布式协作中,Leader 创建的 Teammate 运行在独立进程中。Teammate 收到的任务来自 Leader,但任务内容本身可能包含恶意指令。如果 Teammate 盲目执行来自不可信源的命令,同样会造成安全问题。
开放生态的副产品也是考量因素。JiuwenSwarm 支持 Swarm Skills Hub,开发者可以上传和共享团队技能。这些技能中可能包含需要执行系统命令的工具。如果技能提供者是恶意的,或者技能在传播过程中被篡改,使用该技能的 Agent 就可能受到攻击。
JiuwenSwarm 的答案是建立多层安全边界:
- 命令工具层危险检测 :在命令工具(如
bash、mcp_exec_command)中内嵌危险命令模式检测,直接拦截高危操作 - 分层策略引擎 :通过
tiered_policy机制对工具调用进行精细化权限控制 - 外部目录访问控制:对 workspace 以外的路径进行额外校验
- 内置安全规则 :预置的高危命令拦截规则(
builtin_rules.yaml)

二、命令工具层的危险命令检测
2.1 危险命令模式列表
JiuwenSwarm 在命令执行工具中内嵌了危险命令模式检测。command_tools.py 文件中定义了 _DANGEROUS_COMMAND_PATTERNS 列表,用于在命令执行前进行模式匹配:
python
_DANGEROUS_COMMAND_PATTERNS: list[tuple[re.Pattern[str], str]] = [
(re.compile(r"\brm\s+-rf\b", re.IGNORECASE), "blocked pattern: rm -rf"),
(re.compile(r"\bdel\s+/[a-z]*[fsq][a-z]*\b", re.IGNORECASE), "blocked pattern: del /f /s /q"),
(re.compile(r"\brd\s+/s\s+/q\b", re.IGNORECASE), "blocked pattern: rd /s /q"),
(re.compile(r"\bformat\s+[a-z]:", re.IGNORECASE), "blocked pattern: format drive"),
(re.compile(r"\bshutdown\b", re.IGNORECASE), "blocked pattern: shutdown"),
(re.compile(r"\breboot\b", re.IGNORECASE), "blocked pattern: reboot"),
(re.compile(r"\bdiskpart\b", re.IGNORECASE), "blocked pattern: diskpart"),
(re.compile(r"\bmkfs\b", re.IGNORECASE), "blocked pattern: mkfs"),
(re.compile(r"\breg\s+delete\b", re.IGNORECASE), "blocked pattern: reg delete"),
(
re.compile(r"\bremove-item\b[^\n\r]*-recurse[^\n\r]*-force", re.IGNORECASE),
"blocked pattern: Remove-Item -Recurse -Force",
),
]
这些模式覆盖了文件删除、磁盘格式化、系统关机重启等高危操作。
2.2 安全检查函数
_check_command_safety 函数负责对每条待执行的命令进行安全检查:
python
def _check_command_safety(command: str) -> str | None:
for pattern, message in _DANGEROUS_COMMAND_PATTERNS:
if pattern.search(command):
return message
return None
在 mcp_exec_command 工具中,这个检查会在命令执行前被调用:
python
blocked_reason = _check_command_safety(command)
if blocked_reason:
return f"[ERROR]: command rejected for safety ({blocked_reason})."
2.3 工作目录限制
除了危险命令检测,命令工具还限制了执行时的工作目录范围,防止 Agent 操作 workspace 以外的文件:
python
try:
resolved_workdir = _resolve_command_workdir(workdir)
except Exception:
return "[ERROR]: workdir is outside project workspace."
这确保了 Agent 的操作被限制在项目工作区内。

三、分层策略(tiered_policy)权限机制
3.1 三级动作与主开关
JiuwenSwarm 的权限系统基于 tiered_policy 策略模式,提供三个级别的动作:
| 动作 | 说明 |
|---|---|
allow |
直接执行,无需确认 |
ask |
需用户确认后才能执行 |
deny |
直接拒绝执行 |
权限系统的主开关是 permissions.enabled。关闭后引擎对所有工具调用返回 allow(建议生产环境保持开启)。
yaml
permissions:
enabled: true
schema: tiered_policy
permission_mode: normal
3.2 权限模式与 severity 映射
permission_mode 决定 severity 如何映射到动作:
| severity | normal 模式 | strict 模式 |
|---|---|---|
| LOW | allow | allow |
| MEDIUM | allow | ask |
| HIGH | ask | ask |
| CRITICAL | ask | deny |
unknown severity 按 HIGH 处理。
3.3 工具级配置
permissions.tools 定义了每个工具的默认权限:
yaml
permissions:
tools:
bash: ask
mcp_exec_command: ask
create_terminal: ask
write: ask
write_file: ask
read_memory: allow
# ...
工具级的 deny 会立即返回 DENY,不再看任何参数规则、override、defaults。
3.4 参数级规则
参数级规则通过 pattern 匹配命令或路径,精细化控制权限:
yaml
permissions:
rules:
- id: shell_ask_rm
tools: [bash, mcp_exec_command, create_terminal]
pattern: "rm *"
severity: HIGH
- id: shell_ask_del
tools: [bash, mcp_exec_command, create_terminal]
pattern: "del *"
severity: HIGH
- id: path_ask_ssh
tools: [read_file, write_file, edit_file, ...]
pattern: "**/.ssh/**"
severity: HIGH
- id: path_ask_env
tools: [read_file, write_file, ...]
pattern: "**/.env*"
severity: HIGH
规则必须满足:
- 同一工具类:规则里列出的多个工具须属同一类(shell / path / network),否则该条规则被跳过
- Shell 类 :pattern 匹配
command/cmd整串(支持通配、re:正则等) - Path 类 :pattern 匹配从
tool_args里抽出的路径形字符串
3.5 参数级规则命中流程
evaluate_tiered_policy() 的完整决策流程:
- 整工具基线 :读
permissions.tools.<tool_name>。若为 deny,立即返回 DENY。 - 内置参数规则命中 :检查
builtin_rules.yaml中的规则。若任一命中为 DENY,立即返回。 - 用户参数规则命中 :检查
permissions.rules。若任一命中为 DENY,立即返回。 - approval_overrides :若存在
action: allow的匹配条目,立即返回 ALLOW。 - 合并命中 :若
builtin_hits非空,用_finalize_hits(builtin_hits)并返回;否则用user_hits。 - 回退 :若参数级全无命中,使用整工具基线;若未配置,使用
defaults.*;若都不存在,返回 ASK。
_finalize_hits:若命中列表含 DENY,结果为 DENY;否则取 strictest(deny > ask > allow)。
3.6 Shell 操作符升级
在拿到 tiered_policy 结果后,引擎还会做 maybe_escalate_shell_operators 检查:
若结果不是 来自 approval_overrides,且工具为 shell 类,allow 可能因命令中含链式/注入风险字符(;, |, &, &&, || 等)被升为 ask。

四、内置安全规则(builtin_rules.yaml)
4.1 内置规则的位置与优先级
内置安全规则位于 jiuwenswarm/resources/builtin_rules.yaml。用户可创建同名文件覆盖(放在 ~/.jiuwenswarm/config/builtin_rules.yaml),优先加载用户版本。
内置规则在用户规则之前执行,且内置的 DENY 优先于同层其它级别。用户 rules 不能覆盖内置的 deny。
4.2 内置规则分类
内置规则覆盖以下高危场景:
递归/强制删除:
yaml
- id: shell_fs_recursive_or_forced_delete
description: "递归、强制或批量删除关键路径,可能造成不可恢复的数据破坏"
tools: [bash, mcp_exec_command, create_terminal]
match_type: command
pattern: 're:(?i)(^|[\s;&|()])((rm\s+[^;&|]*(-[A-Za-z]*[rR][A-Za-z]*[fF]|-[A-Za-z]*[fF][A-Za-z]*[rR]|--recursive|--force)[^;&|]*(/[^;&|\s]*|\*|~[^;&|\s]*|\$HOME[^;&|\s]*|\.{1,2}(/[^;&|\s]*)?)(\s|$))|(find\s+[^;&|]*\s-delete\b)|(shred\b)|(del\s+[^;&|]*/[A-Za-z]*[fqs][A-Za-z]*)|(rd\s+[^;&|]*/s\b[^;&|]*/q\b))'
severity: CRITICAL
磁盘分区/设备写入:
yaml
- id: shell_disk_partition_or_raw_device_write
description: "格式化、分区或直接写入块设备,可能破坏磁盘和文件系统"
tools: [bash, mcp_exec_command, create_terminal]
match_type: command
pattern: 're:(?i)(^|[\s;&|()])((mkfs(\.[A-Za-z0-9_]+)?|mke2fs|fdisk|parted|diskpart|format)\b|(dd\b[^;&|]*(\bof=/dev/|\\\.\\PhysicalDrive))|(>\s*/dev/(sd[a-z][0-9]*|vd[a-z][0-9]*|xvd[a-z][0-9]*|nvme[0-9]+n[0-9]+(p[0-9]+)?|disk[0-9]+)))'
severity: CRITICAL
下载并执行:
yaml
- id: shell_download_and_execute
description: "从网络下载内容后直接交给 shell、PowerShell 或动态执行器执行"
tools: [bash, mcp_exec_command, create_terminal]
match_type: command
pattern: 're:(?i)(^|[\s;&|()])(((curl|wget|fetch|ftp)\b[^;&]*\|\s*(bash|sh|zsh|dash|ash|source)\b)|(iwr|irm|Invoke-WebRequest|Invoke-RestMethod)\b[^;&|]*\|\s*(iex|Invoke-Expression)\b|((bash|sh|zsh|pwsh|powershell)\b[^;&|]*<\s*<\s*\(?\s*(curl|wget)\b))'
severity: CRITICAL
混淆/动态执行:
yaml
- id: shell_obfuscated_or_dynamic_execution
description: "编码载荷、解码后执行、eval/iex 或内联解释器执行,命令难以审计"
tools: [bash, mcp_exec_command, create_terminal]
match_type: command
pattern: 're:(?i)(^|[\s;&|()])((base64\s+(-d|--decode)\b[^;&|]*\|\s*(bash|sh|zsh|dash|ash)\b)|(certutil\s+-decode\b)|(-EncodedCommand\b|-[Ee]nc\b)|(\[Convert\]::FromBase64String\()|(eval\s+[`$])|(\b(iex|Invoke-Expression)\b)|((python3?|perl|ruby|node)\s+(-c|-e)\b[^;&|]*(socket|subprocess|exec|eval|child_process)))'
severity: CRITICAL
反向shell/绑定shell:
yaml
- id: shell_reverse_shell_or_bind_shell
description: "反向 shell、绑定 shell 或可疑网络执行通道"
tools: [bash, mcp_exec_command, create_terminal]
match_type: command
pattern: 're:(?i)(/dev/(tcp|udp)/|(^|[\s;&|()])((nc|ncat)\b[^;&|]*\s(-e|--exec)\s|\bsocat\b[^;&|]*(EXEC:|SYSTEM:|PTY)|\bbash\s+-i\b[^;&|]*/dev/tcp/|\bpython3?\b[^;&|]*(socket|pty\.spawn|subprocess)|\bperl\b[^;&|]*Socket)'
severity: CRITICAL
提权操作:
yaml
- id: shell_privilege_escalation
description: "通过 sudo、su、doas、pkexec、runas 或管理员启动方式提升权限"
tools: [bash, mcp_exec_command, create_terminal]
match_type: command
pattern: 're:(?i)(^|[\s;&|()])((sudo|doas|pkexec)\s+|su\s+(-|root|\w)|runas\b|Start-Process\b[^;&|]*-Verb\s+RunAs\b|psexec\b|schtasks\b[^;&|]*/ru\s+SYSTEM\b)'
severity: CRITICAL
数据泄露:
yaml
- id: shell_data_exfiltration
description: "通过 HTTP、scp、rsync、ftp、nc 等方式上传本地文件或命令输出"
tools: [bash, mcp_exec_command, create_terminal]
match_type: command
pattern: 're:(?i)(^|[\s;&|()])(((curl|wget|Invoke-WebRequest|iwr|Invoke-RestMethod|irm)\b[^;&|]*(--data|--data-binary|--upload-file|-d\b|-F\b|-T\b|POST|PUT))|(scp\b[^;&|]+\s+\S+:)|(rsync\b[^;&|]+\s+\S+:)|(sftp|ftp)\b|\bnc\b[^;&|]*\s(443|80|8080|53)\b)'
severity: CRITICAL
远程执行/横向移动:
yaml
- id: shell_remote_execution_or_lateral_movement
description: "远程会话、远程进程创建或横向移动命令"
tools: [bash, mcp_exec_command, create_terminal]
match_type: command
pattern: 're:(?i)(^|[\s;&|()])((Invoke-Command|Enter-PSSession|New-PSSession)\b|winrs\b|wmic\b[^;&|]*process\s+call\s+create|psexec\b|ssh\b[^;&|]*\s\S+\s+["''][^"'']+["''])'
severity: CRITICAL
资源滥用:
yaml
- id: shell_fork_bomb_or_resource_abuse
description: "fork bomb、解除进程限制或批量终止关键进程"
tools: [bash, mcp_exec_command, create_terminal]
match_type: command
pattern: 're:(?i)(:\s*\(\s*\)\s*\{\s*:\s*\|\s*:\s*&\s*\}\s*;\s*:|(^|[\s;&|()])kill\s+-9\s+(-1|1)\b|(^|[\s;&|()])ulimit\s+-u\s+unlimited\b)'
severity: CRITICAL
系统关机/重启:
yaml
- id: shell_system_shutdown_or_reboot
description: "关机、重启或切换到关机/重启运行级别,属于明显破坏系统可用性的行为"
tools: [bash, mcp_exec_command, create_terminal]
match_type: command
pattern: 're:(?i)(^|[\s;&|()])((shutdown|reboot|halt|poweroff)\b|(init|telinit)\s+(0|6)\b)'
action: deny
4.3 内置规则与用户规则的关系
内置规则在评估流程中优先于用户规则:
- 内置 DENY 会立即返回,不执行后续的用户规则检查
- 用户规则里的 deny 可以拦住后续的
approval_overrides - 只有在内置层无参数级命中时,用户层才会参与最终合并
五、外部目录访问控制
5.1 external_directory 配置
当工具调用涉及 agent workspace 以外的路径 时,由 ExternalDirectoryChecker 根据 permissions.external_directory 再判一层:
yaml
permissions:
external_directory:
"*": "ask"
配置为字典格式:
"*": ask表示默认对外部路径需要确认- 具体前缀可设为
allow/deny/ask
yaml
permissions:
external_directory:
"C:/Users/me/documents": allow
"/etc/ssh": deny
"*": ask
5.2 路径前缀匹配规则
- 键为路径前缀(建议正斜杠形式,如
C:/Users/me/data) - 过短键(如仅盘符且无
/)在实现中可能被跳过,避免误匹配整盘
5.3 参与检查的工具类型
外部目录检查会作用于:
Shell 类工具 :bash、mcp_exec_command、create_terminal(从命令行中按规则抽取路径)
路径类工具 :read_file、write_file、list_dir、grep 等(从参数中收集路径)
5.4 与 tiered 结果的合并
外部目录检查的结果会与当前权限级别做 strictest 合并:
plain
tiered_result = ask
external_directory_result = deny
final_result = deny (strictest wins)
matched_rule 可能拼上 |external_directory.* 后缀。

六、approval_overrides 与权限持久化
6.1 权限确认后的持久化
在审批流程中选择记住规则 或等价持久化逻辑时,系统会向 permissions.approval_overrides 追加条目:
yaml
permissions:
approval_overrides:
- id: user_approval_rm_tmp
tools: [bash, mcp_exec_command]
match_type: command
pattern: "rm *.tmp"
action: allow
source: user_approval
字段说明:
id: 规则唯一标识tools: 适用的工具列表match_type: 匹配类型(path/command)pattern: 匹配模式action: 动作(如allow)source: 来源(如user_approval、cli_add_dir)
6.2 Shell 类 pattern 规则
Shell 类 pattern 若以 re: 开头,为正则匹配整条命令字符串 。路径类的 re: 模式会对待匹配路径做 \ → / 归一化后再匹配。
6.3 CLI /add-dir 的影响
终端 TUI 中 /add-dir <path> 会调用 persist_cli_trusted_directory,行为:
external_directory:为目录路径写入一条allow- **若
schema为 **tiered_policy:追加两条approval_overrides(路径类一条 + shell 类一条)
Shell 侧 pattern 仅生成正斜杠路径的字面匹配片段(如 re:.*C:/Users/me.*),避免 C:\Users 导致正则 \U 非法转义。运行时对命令文本做 反斜杠 → 正斜杠 再匹配。
七、实操演示:权限控制的完整验证
7.1 场景说明
本文通过一系列实操演示,验证 JiuwenSwarm 安全边界的工作方式。我们将测试:
- 危险命令的检测与拦截
- shell 类工具的权限分级
- 路径类工具的权限分级
- workspace 外目录的访问控制
- 权限持久化(approval_overrides)
7.2 步骤一:启动 JiuwenSwarm 并进入团队模式
确保 JiuwenSwarm 服务已启动。参考前文分布式文档的启动流程,启动 Leader 和 Teammate 节点(或使用单机模式)。
启动完成后,在 Web 前端底部的模式切换按钮组中,点击"团队模式"按钮,进入多 Agent 协作界面。
7.3 步骤二:验证危险命令拦截
在输入框中发送以下命令:
plain
帮我删除 /tmp 目录下的所有文件和子目录
- Agent 收到指令后,会调用 bash 或 mcp_exec_command 工具执行
- 如果命令匹配危险模式(如
rm -rf /tmp/*),会在命令工具层被直接拦截 - 拦截消息格式:
[ERROR]: command rejected for safety (blocked pattern: rm -rf)

7.4 步骤三:测试 ask 级别的正常命令
发送一个不危险但需要确认的命令:
plain
帮我查看当前目录的文件列表
观察:
- 由于
ls *在内置规则中 severity 为 LOW,normal 模式下会直接 allow - 如果命令包含
rm、del等关键词,severity 为 HIGH,会触发 ask

7.5 步骤四:测试 workspace 外目录访问
发送访问敏感目录的命令:
plain
读取一下 /etc/passwd 文件的内容
由于 /etc 在 workspace 外,且不属于白名单,应该触发 ask 或 deny。

7.6 步骤五:测试路径类规则匹配
发送涉及 SSH 配置或环境变量的命令:
plain
帮我查看一下 ~/.ssh/id_rsa 文件内容
由于 **/.ssh/** 路径在规则中 severity 为 HIGH,应该触发 ask。

7.7 场景总结
| 操作 | 预期结果 |
|---|---|
rm -rf /tmp/* |
命令工具层直接拦截,显示 blocked pattern |
ls -la |
直接执行(LOW severity in normal mode) |
rm *.log |
触发 ask(severity HIGH) |
读取 /etc/passwd |
workspace 外目录,触发 ask 或 deny |
读取 ~/.ssh/id_rsa |
匹配路径规则,触发 ask |
八、配置与部署
8.1 启用权限系统
在 config.yaml 中启用权限系统:
yaml
permissions:
enabled: true
schema: tiered_policy
permission_mode: normal
8.2 工具级配置
yaml
permissions:
tools:
bash: ask
mcp_exec_command: ask
create_terminal: ask
write: ask
write_file: ask
edit_file: ask
read_memory: allow
memory_search: allow
8.3 参数级规则配置
yaml
permissions:
rules:
- id: shell_allow_ls
tools: [bash, mcp_exec_command, create_terminal]
pattern: "ls *"
severity: LOW
- id: shell_ask_rm
tools: [bash, mcp_exec_command, create_terminal]
pattern: "rm *"
severity: HIGH
- id: path_ask_ssh
tools: [read_file, write_file, edit_file, ...]
pattern: "**/.ssh/**"
severity: HIGH
- id: path_ask_env
tools: [read_file, write_file, ...]
pattern: "**/.env*"
severity: HIGH
8.4 外部目录配置
yaml
permissions:
external_directory:
"C:/Users/me/trusted": allow
"/etc/ssh": deny
"*": ask
8.5 strict 模式配置
对于更高安全要求的环境,使用 strict 模式:
yaml
permissions:
permission_mode: strict
strict 模式下:
- MEDIUM → ask
- CRITICAL → deny
8.6 部署检查清单
| 检查项 | 说明 | 验证方式 |
|---|---|---|
| permissions.enabled | 确保权限系统已开启 | 检查 config.yaml |
| tiered_policy 生效 | 确认使用分层策略 | 查看日志中的 matched_rule |
| builtin_rules 加载 | 确认内置规则已加载 | 查看启动日志 |
| 危险命令拦截 | 测试 rm -rf 等命令 |
实际执行并观察结果 |
| 外部目录检查 | 测试 workspace 外路径 | 尝试读取 /etc/passwd |

九、写在最后
回顾 JiuwenSwarm 的安全边界设计,几个关键决策值得关注。
多层防御理念 贯穿整个设计。命令工具层的 _DANGEROUS_COMMAND_PATTERNS 是第一道防线,内置规则(builtin_rules.yaml)是第二道,tiered_policy 分层策略是第三道,外部目录检查是第四道。每道防线都有独立的职责,失效时不会导致全面崩溃。
精确匹配的规则设计。内置规则使用正则表达式精细匹配危险命令的不同变体,如递归删除、格式化、下载执行、反弹shell 等,覆盖了常见攻击向量。
可配置性与安全性的平衡。默认配置兼顾了安全性和可用性,但提供了多种配置选项:permission_mode(normal/strict)、工具级配置、参数级规则、approval_overrides、external_directory 等,让用户在安全性和功能性之间做合理取舍。
权限持久化机制。通过 approval_overrides,用户可以记住信任的命令,避免重复确认,提高工作效率。
当然,当前的安全边界还有一些可以改进的方向。跨节点一致性 在分布式模式下,不同节点的规则配置需要更好的同步机制。动态规则更新 目前依赖配置文件 reload,未来可以支持热更新。审计日志可以对权限决策进行更详细的记录,便于安全审计。
总的来说,JiuwenSwarm 的安全边界设计在实用性、灵活性和安全性之间找到了合理的平衡点。命令工具层检测、分层策略引擎、内置安全规则、外部目录控制------每一层都有明确的职责,组合起来就是一个可工作的安全体系。
参考资料: