Skip to content

命令安全分级系统 ​

本文引用的源码文件

本文引用的文件

目录 ​

  1. 引言
  2. 项目结构与安全边界
  3. 核心组件总览
  4. 架构概览
  5. 详细组件分析
  6. 依赖关系分析
  7. 性能与资源控制
  8. 安全策略配置指南
  9. 常见威胁与防护措施
  10. 故障排查
  11. 结论

引言 ​

本文件系统性地梳理 Agent 端的命令安全分级能力,重点覆盖以下目标:

  • 命令白名单机制:内置安全命令、动态白名单扩展、自定义命令注册。
  • 危险命令检测算法:敏感操作识别、路径遍历防护、参数注入检测、命令拼接攻击防护。
  • 执行权限控制模型:用户角色权限、命令级别授权、沙箱环境隔离、资源访问限制。
  • 安全策略配置:白名单维护、风险等级定义、审计日志记录、违规处理机制。
  • 实际安全配置示例与常见威胁防护说明。

需要特别说明的是,当前仓库中“命令安全”的核心实现集中在 Agent 端,主要包含两类能力:

  1. 文件路径沙箱:通过 checkPath 控制文件类工具可访问的目录,防止越权读取或写入。
  2. 命令分级管控:通过 checkCommand 对 shell 命令进行黑名单/灰名单判定,输出 allow、confirm、deny 三级结果。

此外,Agent 还实现了命令执行器(executor.js),负责子进程创建、流式输出、超时控制、进程终止与环境变量白名单;配置文件(config.js)提供工作目录、允许路径、命令超时等运行时参数;服务端(server.js)将安全检查接入具体 API;技能执行器(skill/executor.js)在技能场景下复用路径与命令安全检查。

项目结构与安全边界 ​

从安全视角看,Agent 端的安全相关代码分布在以下位置:

  • agent/src/security.js:路径沙箱与命令分级核心逻辑。
  • agent/src/executor.js:命令执行器、超时策略、环境变量白名单、进程生命周期管理。
  • agent/src/config.js:默认配置、工作目录、允许路径、命令超时、内存缓存与写锁。
  • agent/src/server.js:HTTP/WebSocket 接口入口,调用 checkPath 与 checkCommand。
  • agent/src/skill/executor.js:技能执行时调用路径检查与命令检查。
  • agent/test/unit/command-security-check.unit.test.js:命令黑白名单单元测试。
  • agent/test/unit/path-security.unit.test.js:路径格式规整与硬阻止单元测试。
graph TB
Server["服务端<br/>agent/src/server.js"] --> Security["安全检查<br/>agent/src/security.js"]
Server --> Executor["命令执行器<br/>agent/src/executor.js"]
Server --> Config["配置中心<br/>agent/src/config.js"]
SkillExecutor["技能执行器<br/>agent/src/skill/executor.js"] --> Security
SkillExecutor --> Executor
Tests["单元测试<br/>command-security-check / path-security"] --> Security

图表来源

章节来源

核心组件总览 ​

本节按职责划分,说明命令安全分级系统的核心组件及其交互方式。

路径沙箱组件 ​

路径沙箱由 security.js 中的 checkPath 实现,主要职责包括:

  • 路径格式归一化:统一 Windows MSYS 风格、盘符大小写、反斜杠、前导斜杠盘符。
  • 硬阻止目录:.ai-helper-agent 下的配置文件、配对记录、MCP 配置、日志、回收站、技能状态等不可访问。
  • 工作目录放行:用户当前工作目录始终可访问,即使未显式加入允许列表。
  • 允许路径校验:基于 allowedPaths 做前缀匹配,并通过 realpath 解析符号链接后再次校验。
  • 错误消息国际化:通过 translate 返回可读原因。

命令分级组件 ​

命令分级由 security.js 中的 checkCommand 实现,主要职责包括:

  • 黑名单判定:绝对禁止的命令,如格式化磁盘、破坏系统目录、覆盖关键系统文件、fork bomb、恶意管道执行等。
  • 灰名单判定:需要确认的危险命令,如 sudo、rm -rf、chmod 777、git push -f、全局安装、网络外联、进程终止、系统服务等。
  • 链式命令拆分:支持 &&、;、|、\n 等控制符,逐段检测,避免敏感命令藏在非开头位置。
  • 包装器剥壳:剥离 nohup、time、timeout、env、exec、xargs、sudo、doas 等前缀,暴露真实命令。
  • 解释器内联载荷:解析 POSIX -c/-e、cmd /c /k、PowerShell -Command/-EncodedCommand。
  • 命令替换检测:提取 $( … ) 与反引号内部子命令,结合只读头命令豁免降低误报。
  • 路径变形归一化:折叠 //、/.、..,防止通过路径写法绕过系统目录黑名单。

命令执行器组件 ​

命令执行器由 executor.js 实现,主要职责包括:

  • Shell 选择:根据平台与环境变量选择 bash、zsh、fish、cmd、powershell 等。
  • 子进程创建:使用 child_process.spawn,设置工作目录、安全环境变量、标准输入输出管道。
  • 流式输出:stdout/stderr 实时广播给 WebSocket 客户端,并限制缓冲区上限。
  • 超时策略:支持受管模式与非受管模式,有输出才延长,无输出则直接终止。
  • 进程终止:跨平台递归终止进程组,Windows 使用 taskkill /T /PID,Unix 使用负 PID 信号。
  • 运行进程缓存:记录 execId、pid、command、startTime、duration,便于调试与监控。

配置组件 ​

配置组件由 config.js 实现,主要职责包括:

  • 默认值:端口、主机、工作目录、允许路径、命令超时、文件大小限制、RAG 网络策略、记忆嵌入配置。
  • 内存缓存:按 mtime 刷新,避免频繁读取磁盘。
  • 写锁:并发写保护,防止 TOCTOU 问题。
  • 自动允许:skills 目录与工作目录自动加入允许列表。
  • 敏感信息落盘混淆:apiKey、token 落盘前加密。

服务端集成 ​

服务端 server.js 在多个 API 中调用 checkPath 与 checkCommand,例如:

  • 文件读写 API:先校验路径,再执行操作。
  • 命令执行 API:先校验命令,再交给 executor 执行。
  • 技能执行 API:技能脚本中涉及文件与命令时,同样走安全检查。

章节来源

架构概览 ​

下图展示命令安全分级系统在 Agent 端的整体架构:

sequenceDiagram
participant Client as "调用方"
participant Server as "服务端<br/>server.js"
participant Security as "安全检查<br/>security.js"
participant Executor as "命令执行器<br/>executor.js"
participant Config as "配置中心<br/>config.js"
Client->>Server : "请求执行命令或访问文件"
Server->>Config : "加载 workdir / allowedPaths / commandTimeout"
Server->>Security : "checkPath(path)"
Security-->>Server : "{ allowed, reason, resolved }"
alt 路径被拒绝
Server-->>Client : "返回路径拒绝原因"
else 路径允许
Server->>Security : "checkCommand(command, force)"
Security-->>Server : "{ safe, level, reason }"
alt 命令 deny
Server-->>Client : "返回命令被拒绝"
else 命令 confirm
Server-->>Client : "请求用户确认"
Client-->>Server : "确认或取消"
opt 用户确认
Server->>Security : "checkCommand(command, true)"
Security-->>Server : "{ safe : true, level : 'allow' }"
Server->>Executor : "executeCommand(command)"
Executor-->>Server : "execId + 流式输出"
Server-->>Client : "转发 stdout/stderr/exit"
end
else 命令 allow
Server->>Executor : "executeCommand(command)"
Executor-->>Server : "execId + 流式输出"
Server-->>Client : "转发 stdout/stderr/exit"
end
end

图表来源

详细组件分析 ​

路径沙箱与白名单机制 ​

路径沙箱的核心是 checkPath,其流程如下:

flowchart TD
Start(["函数入口"]) --> ValidateInput["校验输入是否为字符串"]
ValidateInput --> InputValid{"输入有效?"}
InputValid --> |否| ReturnInvalid["返回路径无效"]
InputValid --> |是| ExpandHome["展开 ~ 到主目录"]
ExpandHome --> NormalizeFormat["统一路径格式"]
NormalizeFormat --> ResolvePath["解析绝对路径"]
ResolvePath --> HardBlocked["检查硬阻止目录"]
HardBlocked --> IsHardBlocked{"命中硬阻止?"}
IsHardBlocked --> |是| ReturnForbidden["返回禁止访问代理文件"]
IsHardBlocked --> |否| CheckMemoryDir["检查记忆存储目录"]
CheckMemoryDir --> MemoryAllowed{"是否记忆目录?"}
MemoryAllowed --> |是| ReturnAllowed["返回允许"]
MemoryAllowed --> |否| CheckWorkdir["检查工作目录"]
CheckWorkdir --> WorkdirAllowed{"是否工作目录?"}
WorkdirAllowed --> |是| RealpathCheck["realpath 硬阻止检查"]
RealpathCheck --> ReturnWorkdirAllowed["返回允许"]
WorkdirAllowed --> |否| CheckAllowedPaths["检查 allowedPaths"]
CheckAllowedPaths --> PrefixMatch{"前缀匹配?"}
PrefixMatch --> |否| ReturnNotAllowed["返回不在允许目录"]
PrefixMatch --> |是| RealpathAgain["realpath 二次校验"]
RealpathAgain --> FinalCheck["最终硬阻止与前缀检查"]
FinalCheck --> ReturnFinal["返回允许或拒绝"]

图表来源

关键设计要点 ​

  • 硬阻止目录不可绕过:.ai-helper-agent 下的配置文件、日志、回收站等绝对禁止访问。
  • 工作目录永远放行:即使用户未把 workdir 加入 allowedPaths,也允许访问。
  • 符号链接防护:通过 realpath 解析真实路径后再校验,防止通过软链接绕过。
  • 跨平台兼容:Windows 盘符大小写不敏感比较,MSYS 路径转换,反斜杠统一为正斜杠。
  • 允许路径动态扩展:allowedPaths 来自配置,默认包含工作目录与 skills 目录。

章节来源

命令白名单机制 ​

当前系统中,“白名单”主要体现在两个层面:

  1. 路径白名单:allowedPaths 配置项决定文件类工具可访问的目录。
  2. 命令白名单:并非传统意义上的“允许列表”,而是通过黑名单/灰名单反向推导“允许”——未被拦截的命令视为允许。

内置安全命令 ​

内置安全命令是指那些未被黑名单或灰名单捕获的命令,例如:

  • ls -la
  • git status
  • npm run build
  • cat README.md
  • ps aux | grep node

这些命令在单元测试中被明确断言为 allow。

动态白名单扩展 ​

动态白名单扩展主要通过以下方式实现:

  • 工作目录放行:workdir 始终允许,无需显式加入 allowedPaths。
  • 记忆目录放行:MEMORY_DIR 始终允许,供 Agent 内部管理。
  • skills 目录自动加入:配置加载时自动将 skills 目录加入 allowedPaths。

自定义命令注册 ​

当前仓库中没有显式的“自定义命令注册表”。但可以通过以下方式间接实现:

  • 技能系统:通过 SKILL.md 定义技能,技能执行器会调用 checkPath 与 checkCommand。
  • MCP 工具注册:MCP 协议可扩展工具,但命令执行仍走安全检查。
  • 配置扩展:通过 allowedPaths 扩展文件访问范围,但不改变命令分级逻辑。

章节来源

危险命令检测算法 ​

危险命令检测由 checkCommand 实现,核心算法如下:

flowchart TD
Start(["函数入口"]) --> ValidateCommand["校验命令是否为字符串且非空"]
ValidateCommand --> Valid{"命令有效?"}
Valid --> |否| ReturnDeny["返回 deny"]
Valid --> |是| CollectScopes["收集子命令范围"]
CollectScopes --> SubstScopes["计算命令替换送检集合"]
SubstScopes --> BlacklistCheck["黑名单逐段检查"]
BlacklistCheck --> Blocked{"命中黑名单?"}
Blocked --> |是| ReturnBlocked["返回 deny"]
Blocked --> |否| CheckAgentFiles["检查是否引用代理敏感文件"]
CheckAgentFiles --> Forbidden{"命中硬阻止?"}
Forbidden --> |是| ReturnForbidden["返回 deny"]
Forbidden --> |否| ForceMode{"force 模式?"}
ForceMode --> |是| ReturnAllow["返回 allow"]
ForceMode --> |否| GraylistCheck["灰名单逐段检查"]
GraylistCheck --> GrayHit{"命中灰名单?"}
GrayHit --> |是| ReturnConfirm["返回 confirm"]
GrayHit --> |否| ReturnSafe["返回 allow"]

图表来源

敏感操作识别 ​

黑名单与灰名单覆盖了以下敏感操作:

  • 删除操作:rm -rf /、rm -rf /usr、rm -rf /etc、rm -rf /var 等。
  • 提权操作:sudo、doas、runas。
  • 权限变更:chmod 777、chmod 000、chown。
  • 网络外联:curl、wget、nc、ssh。
  • 进程操作:kill、pkill、killall。
  • 系统服务:systemctl、launchctl、crontab、sysctl。
  • 脚本执行:外部脚本解释器执行 .sh、.py、.js 等。
  • Windows 特定:rmdir /s、del /f、icacls、reg add/delete/import/load/restore、net user/localgroup、sc stop/delete/config、taskkill /f、PowerShell Remove-Item -Recurse、-EncodedCommand。

路径遍历防护 ​

路径遍历防护主要通过以下方式实现:

  • 路径归一化:折叠 //、/.、..,防止通过路径写法绕过系统目录黑名单。
  • realpath 校验:文件访问时解析真实路径后再校验,防止符号链接绕过。
  • 硬阻止目录:.ai-helper-agent 下的关键文件绝对禁止访问。

参数注入检测 ​

参数注入检测主要通过以下方式实现:

  • 命令替换提取:提取 $( … ) 与反引号内部子命令,单独送检。
  • 引号内扫描:即使拆分器不拆引号内容,也会扫描引号内的替换表达式。
  • 只读头命令豁免:echo、printf、cat、head、tail、wc、ls、pwd、date、whoami、hostname、uname、id、env、printenv、which、type 等只读命令的替换直接放行。

命令拼接攻击防护 ​

命令拼接攻击防护主要通过以下方式实现:

  • 链式命令拆分:支持 &&、;、|、\n 等控制符,逐段检测。
  • 包装器剥壳:剥离 nohup、time、timeout、env、exec、xargs、sudo、doas 等前缀。
  • 解释器内联载荷:解析 POSIX -c/-e、cmd /c /k、PowerShell -Command/-EncodedCommand。
  • 深度限制:嵌套解释器最多递归 3 层,防止死循环。

章节来源

执行权限控制模型 ​

当前系统中的执行权限控制模型主要包括:

  • 用户角色权限:未实现细粒度角色权限控制,主要通过 force 参数模拟“用户已确认”。
  • 命令级别授权:通过 checkCommand 返回 allow、confirm、deny 三级结果。
  • 沙箱环境隔离:通过 checkPath 限制文件访问范围,通过 buildSafeEnv 限制环境变量。
  • 资源访问限制:通过 MAX_OUTPUT_BUFFER 限制输出缓冲区大小,通过超时策略限制命令执行时间。

用户角色权限 ​

当前系统未实现多角色权限模型,但可通过以下方式模拟:

  • 管理员模式:通过 force=true 跳过灰名单检查,但仍保留黑名单。
  • 普通用户模式:默认行为,所有灰名单命令需用户确认。

命令级别授权 ​

命令级别授权由 checkCommand 实现:

  • allow:安全命令,直接执行。
  • confirm:危险命令,需用户确认。
  • deny:绝对禁止命令,不可绕过。

沙箱环境隔离 ​

沙箱环境隔离由 checkPath 与 buildSafeEnv 共同实现:

  • 文件沙箱:限制文件访问范围为 workdir 与 allowedPaths。
  • 环境变量沙箱:仅允许白名单中的环境变量,防止泄露宿主敏感信息。

资源访问限制 ​

资源访问限制由 executor.js 实现:

  • 输出缓冲区限制:最大 5MB,超过后截断并标记。
  • 超时策略:受管模式下,有输出才延长,无输出则直接终止。
  • 进程树终止:跨平台递归终止进程组,防止僵尸进程。

章节来源

安全策略配置 ​

安全策略配置主要由 config.js 提供,关键配置项包括:

  • workdir:工作目录,默认 .ai-helper-agent/workspace。
  • allowedPaths:允许路径列表,默认包含 workdir 与 skills 目录。
  • commandTimeout:命令超时时间,默认 300000ms(5分钟)。
  • fileMaxSize:文件大小限制,默认 50MB。
  • ragUrlIngest.allowPrivateNetwork:RAG URL 导入内网访问策略。
  • memoryEmbedding.enabled:长期记忆语义召回开关。

白名单维护指南 ​

  • 添加允许路径:通过 API 更新 allowedPaths,或使用 UI 切换工作目录。
  • 移除允许路径:通过 API 从 allowedPaths 中移除。
  • 注意:workdir 始终允许,无需显式加入 allowedPaths。

风险等级定义 ​

  • 低风险:allow,直接执行。
  • 中风险:confirm,需用户确认。
  • 高风险:deny,绝对禁止。

审计日志记录 ​

当前系统未实现完整的审计日志记录,但可通过以下方式间接获取:

  • 命令执行日志:executor.js 会记录 execId、command、startTime、duration。
  • 错误日志:security.js 与 executor.js 会抛出错误消息。
  • WebSocket 输出:stdout/stderr 实时广播,可用于外部审计。

违规处理机制 ​

  • 路径违规:返回 security.pathInvalid、security.forbiddenAgentFile、security.pathNotInAllowedDir、security.cannotResolvePath、security.pathOutOfRange、security.pathCheckError。
  • 命令违规:返回 security.commandInvalid、security.commandBlocked。
  • 用户确认失败:灰名单命令在未确认时被拒绝。

章节来源

依赖关系分析 ​

命令安全分级系统的依赖关系如下:

graph TB
Security["security.js"] --> Config["config.js"]
Security --> I18n["i18n.js"]
Executor["executor.js"] --> Config["config.js"]
Executor --> I18n["i18n.js"]
Server["server.js"] --> Security["security.js"]
Server --> Executor["executor.js"]
SkillExecutor["skill/executor.js"] --> Security["security.js"]
SkillExecutor --> Executor["executor.js"]
Tests["单元测试"] --> Security["security.js"]

图表来源

章节来源

性能与资源控制 ​

命令安全分级系统在性能与资源控制方面采取了以下措施:

  • 路径检查优化:先做前缀匹配,再做 realpath 校验,减少不必要的系统调用。
  • 命令检查优化:黑名单优先,快速拒绝高危命令;灰名单仅在必要时触发。
  • 输出缓冲区限制:最大 5MB,防止长时间命令占用过多内存。
  • 超时策略优化:受管模式下,有输出才延长,无输出则直接终止,避免僵尸进程。
  • 进程树终止:跨平台递归终止进程组,确保资源释放。

章节来源

常见威胁与防护措施 ​

本节列举常见安全威胁及对应的防护措施。

威胁 1:路径遍历攻击 ​

  • 威胁描述:通过 ../、//、/. 等路径写法绕过沙箱限制。
  • 防护措施:
    • 路径归一化:折叠冗余分隔符与相对路径段。
    • realpath 校验:解析真实路径后再校验。
    • 硬阻止目录:.ai-helper-agent 下的关键文件绝对禁止访问。

威胁 2:命令注入攻击 ​

  • 威胁描述:通过 $( … )、反引号、环境变量等方式注入恶意命令。
  • 防护措施:
    • 命令替换提取:提取 $( … ) 与反引号内部子命令,单独送检。
    • 引号内扫描:扫描引号内的替换表达式。
    • 只读头命令豁免:降低误报,避免正常用法被拦截。

威胁 3:命令拼接攻击 ​

  • 威胁描述:通过 &&、;、| 等控制符拼接敏感命令。
  • 防护措施:
    • 链式命令拆分:逐段检测,避免敏感命令藏在非开头位置。
    • 包装器剥壳:剥离 sudo、doas 等前缀,暴露真实命令。
    • 解释器内联载荷:解析 -c/-e、/c /k、-Command/-EncodedCommand。

威胁 4:提权绕过 ​

  • 威胁描述:通过 sudo、doas、runas 等提权包装器绕过黑名单。
  • 防护措施:
    • 包装器剥壳:剥离提权前缀,暴露真实命令。
    • 黑名单优先级:绝对禁止命令不受 force 影响。

威胁 5:系统文件破坏 ​

  • 威胁描述:通过 rm -rf /、mkfs、dd of=/dev/ 等命令破坏系统文件。
  • 防护措施:
    • 黑名单覆盖:绝对禁止破坏性命令。
    • 路径变形归一化:防止通过路径写法绕过。

章节来源

故障排查 ​

本节提供常见故障的排查思路。

问题 1:路径访问被拒绝 ​

  • 可能原因:
    • 路径不在 allowedPaths 中。
    • 路径命中硬阻止目录。
    • 路径包含符号链接,指向被禁止的位置。
  • 排查步骤:
    1. 检查 allowedPaths 配置。
    2. 检查路径是否属于 .ai-helper-agent 目录。
    3. 使用 realpath 检查真实路径。

问题 2:命令被拒绝 ​

  • 可能原因:
    • 命令命中黑名单。
    • 命令命中灰名单且未确认。
    • 命令引用了代理敏感文件。
  • 排查步骤:
    1. 检查命令是否属于黑名单。
    2. 检查是否需要用户确认。
    3. 检查命令是否引用 .ai-helper-agent 目录。

问题 3:命令执行超时 ​

  • 可能原因:
    • 命令长时间无输出。
    • 超时策略设置为严格模式。
  • 排查步骤:
    1. 检查命令是否有输出。
    2. 调整 commandTimeout 配置。
    3. 检查 executor.js 的超时策略。

章节来源

结论 ​

命令安全分级系统通过路径沙箱与命令分级两大核心机制,构建了较为完整的安全防护体系。其优势在于:

  • 路径沙箱:通过硬阻止目录、工作目录放行、允许路径校验、符号链接防护,有效防止文件越权访问。
  • 命令分级:通过黑名单/灰名单、链式命令拆分、包装器剥壳、解释器内联载荷解析、命令替换检测,有效识别危险命令。
  • 执行器安全:通过环境变量白名单、输出缓冲区限制、超时策略、进程树终止,保障执行环境安全。

然而,系统仍存在一定局限:

  • 未实现细粒度角色权限控制:仅通过 force 参数模拟用户确认。
  • 未实现完整审计日志:仅通过错误日志与 WebSocket 输出间接获取。
  • 未实现自定义命令注册表:需通过技能系统或 MCP 协议间接扩展。

未来改进方向包括:

  • 引入 RBAC 角色权限模型。
  • 完善审计日志记录与导出功能。
  • 支持自定义命令注册与动态白名单扩展。
  • 增强命令语义分析,减少误报与漏报。