mateclaw/mateclaw-server/src/main/java/vip/mate/tool/guard/DefaultToolGuard.java
matevip 579d60125b Initial commit: MateClaw — Java + Vue 3 AI Assistant System
Full-stack AI assistant built on Spring AI Alibaba.
Features: ReAct Agent, Plan-and-Execute, MCP Protocol, Multi-Model, Multi-Channel.

Apache-2.0 License
2026-04-04 19:03:49 +08:00

208 lines
8.3 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package vip.mate.tool.guard;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import java.util.List;
import java.util.Set;
/**
* 默认工具安全守卫
* 基于正则模式匹配检测危险操作,采用规则驱动的安全守卫模式
* <p>
* 对于本地命令执行工具(如 execute_shell_command分为两级处理
* <ul>
* <li>BLOCK极端破坏性模式如 rm -rf /、dd if=xxx of=/dev/、mkfs——直接拒绝不允许审批覆盖</li>
* <li>NEEDS_APPROVAL一般高风险命令如 git push --force、chmod 777、DROP TABLE——需要用户审批后才能执行</li>
* </ul>
* 非 shell 工具仍使用原 BLOCK 策略。
*
* @author MateClaw Team
*/
@Slf4j
@Component
public class DefaultToolGuard implements ToolGuard {
/** 被视为本地命令执行工具的工具名集合 */
private static final Set<String> SHELL_TOOL_NAMES = Set.of(
"execute_shell_command",
"shell_execute",
"run_command"
);
/** 文件写入类工具 —— 默认需要用户审批 */
private static final Set<String> FILE_WRITE_TOOL_NAMES = Set.of(
"write_file",
"edit_file"
);
/** 极端破坏性模式 —— 即使是 shell 工具也直接 BLOCK不允许审批覆盖 */
private final List<DangerousPattern> absoluteBlockPatterns;
/** 一般高风险模式 —— 对 shell 工具走 NEEDS_APPROVAL对其他工具走 BLOCK */
private final List<DangerousPattern> highRiskPatterns;
public DefaultToolGuard() {
this.absoluteBlockPatterns = loadAbsoluteBlockPatterns();
this.highRiskPatterns = loadHighRiskPatterns();
}
@Override
public ToolGuardResult check(String toolName, String arguments) {
if (arguments == null || arguments.isEmpty()) {
return ToolGuardResult.allow();
}
String combined = (toolName != null ? toolName + " " : "") + arguments;
boolean isShellTool = toolName != null && SHELL_TOOL_NAMES.contains(toolName);
// 第一层:极端破坏性模式 —— 无论什么工具都直接 BLOCK
for (DangerousPattern pattern : absoluteBlockPatterns) {
if (pattern.matches(combined)) {
log.warn("[ToolGuard] BLOCKED (absolute): tool={}, pattern={}, reason={}",
toolName, pattern.regex(), pattern.reason());
return ToolGuardResult.block(pattern.reason(), pattern.regex());
}
}
// 第二层:高风险模式
for (DangerousPattern pattern : highRiskPatterns) {
if (pattern.matches(combined)) {
if (isShellTool) {
// Shell 工具命中高风险模式 → 需要用户审批
log.info("[ToolGuard] NEEDS_APPROVAL: tool={}, pattern={}, reason={}",
toolName, pattern.regex(), pattern.reason());
return ToolGuardResult.needsApproval(pattern.reason(), pattern.regex());
} else {
// 非 shell 工具命中高风险模式 → 直接 BLOCK
log.warn("[ToolGuard] BLOCKED: tool={}, pattern={}, reason={}",
toolName, pattern.regex(), pattern.reason());
return ToolGuardResult.block(pattern.reason(), pattern.regex());
}
}
}
// Shell 工具即使未命中任何模式,也需要审批(任何本地命令执行都是敏感操作)
if (isShellTool) {
log.info("[ToolGuard] NEEDS_APPROVAL (shell tool default): tool={}", toolName);
return ToolGuardResult.needsApproval("本地命令执行需要用户确认", "shell_tool_default");
}
// 文件写入/编辑工具需要审批
if (toolName != null && FILE_WRITE_TOOL_NAMES.contains(toolName)) {
log.info("[ToolGuard] NEEDS_APPROVAL (file write tool): tool={}", toolName);
return ToolGuardResult.needsApproval("文件写入/编辑操作需要用户确认", "file_write_tool_default");
}
return ToolGuardResult.allow();
}
/**
* 极端破坏性模式 —— 直接 BLOCK不允许审批覆盖
* 这些命令一旦执行可能造成不可逆的系统级损坏
*/
private List<DangerousPattern> loadAbsoluteBlockPatterns() {
return List.of(
new DangerousPattern(
"rm\\s+-(rf|fr)\\s+/\\s*$",
"filesystem_destroy",
"递归强制删除根目录"),
new DangerousPattern(
"mkfs\\b",
"filesystem_destroy",
"文件系统格式化命令"),
new DangerousPattern(
"dd\\s+if=.+of=/dev/",
"filesystem_destroy",
"直接磁盘写入操作"),
new DangerousPattern(
"\\bkill\\s+-9\\s+1\\b",
"system_danger",
"杀死 init/systemd 进程"),
new DangerousPattern(
"curl.*\\|\\s*(sh|bash|zsh)",
"code_injection",
"管道下载内容到 Shell 执行"),
new DangerousPattern(
"wget.*\\|\\s*(sh|bash|zsh)",
"code_injection",
"管道下载内容到 Shell 执行")
);
}
/**
* 一般高风险模式 —— shell 工具走 NEEDS_APPROVAL其他工具走 BLOCK
*/
private List<DangerousPattern> loadHighRiskPatterns() {
return List.of(
// 文件系统
new DangerousPattern(
"rm\\s+-(rf|fr)",
"filesystem_destroy",
"递归强制删除操作"),
new DangerousPattern(
"rm\\s+/",
"filesystem_destroy",
"从根路径删除文件"),
new DangerousPattern(
"rmdir\\s+/",
"filesystem_destroy",
"从根路径删除目录"),
// SQL
new DangerousPattern(
"DROP\\s+(TABLE|DATABASE|INDEX|VIEW|SCHEMA)",
"sql_destroy",
"SQL DROP 语句"),
new DangerousPattern(
"TRUNCATE\\s+TABLE",
"sql_destroy",
"SQL TRUNCATE TABLE 语句"),
new DangerousPattern(
"DELETE\\s+FROM\\s+\\w+\\s*;",
"sql_destroy",
"无条件 DELETE缺少 WHERE 子句)"),
new DangerousPattern(
"ALTER\\s+TABLE\\s+\\w+\\s+DROP",
"sql_destroy",
"ALTER TABLE DROP 操作"),
// 系统
new DangerousPattern(
"\\bshutdown\\b",
"system_danger",
"系统关机命令"),
new DangerousPattern(
"\\breboot\\b",
"system_danger",
"系统重启命令"),
new DangerousPattern(
"chmod\\s+777",
"system_danger",
"过度宽松的权限设置"),
// 代码注入
new DangerousPattern(
"eval\\s*\\(",
"code_injection",
"动态代码执行eval"),
// 凭据
new DangerousPattern(
"(password|secret|api[_-]?key|token)\\s*=\\s*['\"]?\\S{8,}",
"credential_exposure",
"可能的凭据信息暴露"),
// Git
new DangerousPattern(
"git\\s+push\\s+.*--force",
"git_danger",
"Git 强制推送"),
new DangerousPattern(
"git\\s+reset\\s+--hard",
"git_danger",
"Git 硬重置")
);
}
}