diff --git a/mateclaw-server/src/main/java/vip/mate/tool/builtin/ShellExecuteTool.java b/mateclaw-server/src/main/java/vip/mate/tool/builtin/ShellExecuteTool.java
index 17a4dfd5..b34466a0 100644
--- a/mateclaw-server/src/main/java/vip/mate/tool/builtin/ShellExecuteTool.java
+++ b/mateclaw-server/src/main/java/vip/mate/tool/builtin/ShellExecuteTool.java
@@ -42,7 +42,7 @@ public class ShellExecuteTool {
@Tool(description = "在本地服务器上执行 Shell 命令。用于执行系统命令、查看文件、运行脚本等操作。"
+ "Windows 下使用 cmd.exe,Linux/macOS 下使用 /bin/sh。"
- + "注意:每次执行都需要用户审批确认。返回包含 exitCode、stdout、stderr、timedOut 的结构化结果。")
+ + "危险操作(如 rm -rf、格式化磁盘等)会触发安全审批。返回包含 exitCode、stdout、stderr、timedOut 的结构化结果。")
public String execute_shell_command(
@ToolParam(description = "要执行的 Shell 命令") String command,
@ToolParam(description = "超时秒数,默认 60 秒", required = false) Integer timeoutSeconds) {
diff --git a/mateclaw-server/src/main/java/vip/mate/tool/guard/config/ToolGuardSchemaMigration.java b/mateclaw-server/src/main/java/vip/mate/tool/guard/config/ToolGuardSchemaMigration.java
index 5da670c6..19f736f5 100644
--- a/mateclaw-server/src/main/java/vip/mate/tool/guard/config/ToolGuardSchemaMigration.java
+++ b/mateclaw-server/src/main/java/vip/mate/tool/guard/config/ToolGuardSchemaMigration.java
@@ -24,6 +24,7 @@ public class ToolGuardSchemaMigration implements ApplicationRunner {
createGuardRuleTable();
createGuardConfigTable();
createAuditLogTable();
+ migrateGuardConfigAuditColumns();
}
private void createGuardRuleTable() {
@@ -108,6 +109,16 @@ public class ToolGuardSchemaMigration implements ApplicationRunner {
}
}
+ /**
+ * 为 mate_tool_guard_config 补充审计配置列(向已有表兼容迁移)
+ */
+ private void migrateGuardConfigAuditColumns() {
+ safeExecute("ALTER TABLE mate_tool_guard_config ADD COLUMN audit_enabled BOOLEAN NOT NULL DEFAULT TRUE");
+ safeExecute("ALTER TABLE mate_tool_guard_config ADD COLUMN audit_min_severity VARCHAR(16) NOT NULL DEFAULT 'INFO'");
+ safeExecute("ALTER TABLE mate_tool_guard_config ADD COLUMN audit_retention_days INT NOT NULL DEFAULT 90");
+ log.info("[ToolGuardSchemaMigration] audit columns migration done");
+ }
+
private void safeExecute(String sql) {
try {
jdbcTemplate.execute(sql);
diff --git a/mateclaw-server/src/main/java/vip/mate/tool/guard/guardian/ShellCommandGuardian.java b/mateclaw-server/src/main/java/vip/mate/tool/guard/guardian/ShellCommandGuardian.java
index a0e3b406..63e21db4 100644
--- a/mateclaw-server/src/main/java/vip/mate/tool/guard/guardian/ShellCommandGuardian.java
+++ b/mateclaw-server/src/main/java/vip/mate/tool/guard/guardian/ShellCommandGuardian.java
@@ -186,6 +186,13 @@ public class ShellCommandGuardian implements ToolGuardGuardian {
"此命令可能被用于远程控制,请勿执行"));
// === 高风险(HIGH)===
+ list.add(new ShellRule("SHELL_RM",
+ "(^|[;&|]|\\s)rm\\s",
+ GuardSeverity.HIGH, GuardCategory.COMMAND_INJECTION,
+ "rm 删除命令",
+ "检测到 rm 删除操作,可能导致文件永久丢失",
+ "请确认要删除的文件列表,考虑使用 trash 替代 rm"));
+
list.add(new ShellRule("SHELL_RM_RF",
"rm\\s+-(rf|fr)",
GuardSeverity.HIGH, GuardCategory.COMMAND_INJECTION,
diff --git a/mateclaw-server/src/main/java/vip/mate/tool/guard/model/ToolGuardConfigEntity.java b/mateclaw-server/src/main/java/vip/mate/tool/guard/model/ToolGuardConfigEntity.java
index 0245f25c..b46ed8fd 100644
--- a/mateclaw-server/src/main/java/vip/mate/tool/guard/model/ToolGuardConfigEntity.java
+++ b/mateclaw-server/src/main/java/vip/mate/tool/guard/model/ToolGuardConfigEntity.java
@@ -22,6 +22,13 @@ public class ToolGuardConfigEntity {
private Boolean fileGuardEnabled;
private String sensitivePathsJson;
+ /** 审计日志总开关 */
+ private Boolean auditEnabled;
+ /** 最低记录等级(INFO/LOW/MEDIUM/HIGH/CRITICAL) */
+ private String auditMinSeverity;
+ /** 审计日志保留天数(0=永不清理) */
+ private Integer auditRetentionDays;
+
@TableField(fill = FieldFill.INSERT)
private LocalDateTime createTime;
diff --git a/mateclaw-server/src/main/java/vip/mate/tool/guard/service/ToolGuardAuditService.java b/mateclaw-server/src/main/java/vip/mate/tool/guard/service/ToolGuardAuditService.java
index d0b36c2b..fa3d7e22 100644
--- a/mateclaw-server/src/main/java/vip/mate/tool/guard/service/ToolGuardAuditService.java
+++ b/mateclaw-server/src/main/java/vip/mate/tool/guard/service/ToolGuardAuditService.java
@@ -8,16 +8,20 @@ import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Async;
+import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import vip.mate.tool.guard.model.*;
import vip.mate.tool.guard.repository.ToolGuardAuditLogMapper;
+import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 工具安全审计服务
+ *
+ * 支持审计开关、最低记录等级过滤、过期日志自动清理。
*/
@Slf4j
@Service
@@ -26,13 +30,33 @@ public class ToolGuardAuditService {
private final ToolGuardAuditLogMapper auditMapper;
private final ObjectMapper objectMapper;
+ private final ToolGuardConfigService configService;
/**
* 异步记录审计日志
+ *
+ * 受审计开关和最低等级过滤控制:
+ *
+ * - auditEnabled=false → 不记录
+ * - maxSeverity 低于 auditMinSeverity → 不记录
+ *
*/
@Async
public void record(ToolInvocationContext context, GuardEvaluation evaluation, String pendingId) {
try {
+ // 审计开关检查
+ if (!configService.isAuditEnabled()) {
+ return;
+ }
+
+ // 等级过滤:无 finding 时 maxSeverity 为 null,视为 INFO 级
+ GuardSeverity minSeverity = configService.getAuditMinSeverity();
+ GuardSeverity actualSeverity = evaluation.maxSeverity() != null
+ ? evaluation.maxSeverity() : GuardSeverity.INFO;
+ if (!actualSeverity.isAtLeast(minSeverity)) {
+ return;
+ }
+
ToolGuardAuditLogEntity entity = new ToolGuardAuditLogEntity();
entity.setConversationId(context.conversationId());
entity.setAgentId(context.agentId());
@@ -99,6 +123,27 @@ public class ToolGuardAuditService {
return stats;
}
+ /**
+ * 定时清理过期审计日志(每天凌晨 3 点)
+ */
+ @Scheduled(cron = "0 0 3 * * ?")
+ public void cleanExpiredAuditLogs() {
+ try {
+ int days = configService.getAuditRetentionDays();
+ if (days <= 0) return;
+
+ LocalDateTime cutoff = LocalDateTime.now().minusDays(days);
+ int deleted = auditMapper.delete(
+ new LambdaQueryWrapper()
+ .lt(ToolGuardAuditLogEntity::getCreateTime, cutoff));
+ if (deleted > 0) {
+ log.info("[ToolGuardAudit] Cleaned {} expired records (older than {} days)", deleted, days);
+ }
+ } catch (Exception e) {
+ log.warn("[ToolGuardAudit] Failed to clean expired logs: {}", e.getMessage());
+ }
+ }
+
private String serializeFindings(GuardEvaluation evaluation) {
try {
return objectMapper.writeValueAsString(evaluation.findingsToMapList());
diff --git a/mateclaw-server/src/main/java/vip/mate/tool/guard/service/ToolGuardConfigService.java b/mateclaw-server/src/main/java/vip/mate/tool/guard/service/ToolGuardConfigService.java
index ba6fb7c2..480cc522 100644
--- a/mateclaw-server/src/main/java/vip/mate/tool/guard/service/ToolGuardConfigService.java
+++ b/mateclaw-server/src/main/java/vip/mate/tool/guard/service/ToolGuardConfigService.java
@@ -11,6 +11,8 @@ import org.springframework.stereotype.Service;
import vip.mate.tool.guard.model.ToolGuardConfigEntity;
import vip.mate.tool.guard.repository.ToolGuardConfigMapper;
+import vip.mate.tool.guard.model.GuardSeverity;
+
import java.util.List;
import java.util.Set;
@@ -51,6 +53,9 @@ public class ToolGuardConfigService {
if (config.getDeniedToolsJson() != null) existing.setDeniedToolsJson(config.getDeniedToolsJson());
if (config.getFileGuardEnabled() != null) existing.setFileGuardEnabled(config.getFileGuardEnabled());
if (config.getSensitivePathsJson() != null) existing.setSensitivePathsJson(config.getSensitivePathsJson());
+ if (config.getAuditEnabled() != null) existing.setAuditEnabled(config.getAuditEnabled());
+ if (config.getAuditMinSeverity() != null) existing.setAuditMinSeverity(config.getAuditMinSeverity());
+ if (config.getAuditRetentionDays() != null) existing.setAuditRetentionDays(config.getAuditRetentionDays());
configMapper.updateById(existing);
// 通知 AgentService 刷新缓存(denied 工具列表变更需要重建 agent 的工具集)
eventPublisher.publishEvent(new ToolGuardConfigChangedEvent(this));
@@ -90,6 +95,27 @@ public class ToolGuardConfigService {
return parseJsonList(json);
}
+ // ==================== 审计配置 ====================
+
+ public boolean isAuditEnabled() {
+ return Boolean.TRUE.equals(getConfig().getAuditEnabled());
+ }
+
+ public GuardSeverity getAuditMinSeverity() {
+ String s = getConfig().getAuditMinSeverity();
+ if (s == null || s.isBlank()) return GuardSeverity.INFO;
+ try {
+ return GuardSeverity.valueOf(s);
+ } catch (IllegalArgumentException e) {
+ return GuardSeverity.INFO;
+ }
+ }
+
+ public int getAuditRetentionDays() {
+ Integer days = getConfig().getAuditRetentionDays();
+ return days != null ? days : 90;
+ }
+
// ==================== 内部方法 ====================
private ToolGuardConfigEntity createDefaultConfig() {
diff --git a/mateclaw-server/src/main/java/vip/mate/tool/guard/service/ToolGuardRuleSeedService.java b/mateclaw-server/src/main/java/vip/mate/tool/guard/service/ToolGuardRuleSeedService.java
index 9baea535..4f4daf5d 100644
--- a/mateclaw-server/src/main/java/vip/mate/tool/guard/service/ToolGuardRuleSeedService.java
+++ b/mateclaw-server/src/main/java/vip/mate/tool/guard/service/ToolGuardRuleSeedService.java
@@ -1,6 +1,7 @@
package vip.mate.tool.guard.service;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.ApplicationArguments;
@@ -9,17 +10,23 @@ import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import vip.mate.tool.guard.model.GuardCategory;
import vip.mate.tool.guard.model.GuardSeverity;
+import vip.mate.tool.guard.model.ToolGuardConfigEntity;
import vip.mate.tool.guard.model.ToolGuardRuleEntity;
+import vip.mate.tool.guard.repository.ToolGuardConfigMapper;
import vip.mate.tool.guard.repository.ToolGuardRuleMapper;
-import java.util.ArrayList;
-import java.util.List;
+import java.util.*;
+import java.util.stream.Collectors;
/**
* 规则种子服务
*
- * 首次启动时将内置规则写入 DB。
- * 已存在则跳过(通过 rule_id UNIQUE 约束)。
+ * 启动时完成三项工作:
+ *
+ * - 迁移旧版工具名(类名 → @Tool 方法名)+ 清理旧 legacy 规则
+ * - 按 rule_id 逐条 upsert 内置规则(不存在则插入,已存在则同步更新)
+ * - 迁移 guardedToolsJson 中的旧工具名
+ *
*/
@Slf4j
@Component
@@ -28,38 +35,176 @@ import java.util.List;
public class ToolGuardRuleSeedService implements ApplicationRunner {
private final ToolGuardRuleMapper ruleMapper;
+ private final ToolGuardConfigMapper configMapper;
+
+ /** 旧类名 → 新 @Tool 方法名 */
+ private static final Map TOOL_NAME_RENAMES = Map.of(
+ "ShellExecuteTool", "execute_shell_command",
+ "WriteFileTool", "write_file",
+ "EditFileTool", "edit_file"
+ );
+
+ /** 旧 SQL 种子中的 legacy rule_id,已被 Java 种子的新规则完全覆盖 */
+ private static final Set LEGACY_RULE_IDS = Set.of(
+ "write_file_any",
+ "edit_file_any",
+ "shell_rm_approval",
+ "shell_rm_rf_block",
+ "shell_write_system_file",
+ "shell_chmod_777"
+ );
@Override
public void run(ApplicationArguments args) {
+ migrateOldData();
seedBuiltinRules();
}
+ // ==================== 旧数据迁移 ====================
+
+ /**
+ * 将 DB 中旧版数据统一迁移:
+ *
+ * - rule 表旧工具名(类名 → @Tool 方法名)
+ * - 清理 legacy rule_id(旧 SQL 种子残留)
+ * - config 表 guardedToolsJson 中的旧工具名
+ *
+ */
+ private void migrateOldData() {
+ try {
+ // 1. 迁移 rule 表旧工具名
+ for (var entry : TOOL_NAME_RENAMES.entrySet()) {
+ int updated = ruleMapper.update(null,
+ new LambdaUpdateWrapper()
+ .eq(ToolGuardRuleEntity::getToolName, entry.getKey())
+ .set(ToolGuardRuleEntity::getToolName, entry.getValue()));
+ if (updated > 0) {
+ log.info("[RuleSeed] Migrated {} rules: {} -> {}", updated, entry.getKey(), entry.getValue());
+ }
+ }
+
+ // 2. 清理旧 SQL 种子残留的 legacy 规则
+ cleanupLegacyRules();
+
+ // 3. 迁移 config 表 guardedToolsJson
+ migrateGuardedToolsJson();
+ } catch (Exception e) {
+ log.warn("[RuleSeed] Migration failed (table may not exist): {}", e.getMessage());
+ }
+ }
+
+ /**
+ * 删除旧 SQL 种子中残留的 legacy builtin 规则。
+ * 这些规则的 rule_id 与新 Java 种子不重叠,增量升级后会形成冗余重复。
+ */
+ private void cleanupLegacyRules() {
+ for (String legacyId : LEGACY_RULE_IDS) {
+ int deleted = ruleMapper.delete(
+ new LambdaQueryWrapper()
+ .eq(ToolGuardRuleEntity::getRuleId, legacyId)
+ .eq(ToolGuardRuleEntity::getBuiltin, true));
+ if (deleted > 0) {
+ log.info("[RuleSeed] Removed legacy rule: {}", legacyId);
+ }
+ }
+ }
+
+ private void migrateGuardedToolsJson() {
+ try {
+ List configs = configMapper.selectList(null);
+ for (ToolGuardConfigEntity config : configs) {
+ String json = config.getGuardedToolsJson();
+ if (json == null || json.isBlank()) continue;
+
+ String updated = json;
+ for (var entry : TOOL_NAME_RENAMES.entrySet()) {
+ updated = updated.replace("\"" + entry.getKey() + "\"", "\"" + entry.getValue() + "\"");
+ }
+ if (!updated.equals(json)) {
+ config.setGuardedToolsJson(updated);
+ configMapper.updateById(config);
+ log.info("[RuleSeed] Migrated guardedToolsJson: {} -> {}", json, updated);
+ }
+ }
+ } catch (Exception e) {
+ log.debug("[RuleSeed] guardedToolsJson migration skipped: {}", e.getMessage());
+ }
+ }
+
+ // ==================== 规则种子 ====================
+
+ /**
+ * 按 rule_id 逐条 upsert 内置规则:
+ *
+ * - 不存在 → 插入
+ * - 已存在 → 同步更新 pattern / severity / decision / priority / toolName 等字段
+ *
+ * 这样后续版本修正了 regex 或 severity,已有部署也能在重启时自动拿到更新。
+ */
void seedBuiltinRules() {
try {
- Long existingCount = ruleMapper.selectCount(
+ // 加载已有 builtin 规则(按 rule_id 索引)
+ List existingList = ruleMapper.selectList(
new LambdaQueryWrapper()
.eq(ToolGuardRuleEntity::getBuiltin, true));
- if (existingCount > 0) {
- log.info("[RuleSeed] {} builtin rules already exist, skipping seed", existingCount);
- return;
- }
+ Map existingMap = existingList.stream()
+ .collect(Collectors.toMap(ToolGuardRuleEntity::getRuleId, e -> e, (a, b) -> a));
List rules = buildBuiltinRules();
int inserted = 0;
+ int updated = 0;
+ int unchanged = 0;
+
for (ToolGuardRuleEntity rule : rules) {
- try {
- ruleMapper.insert(rule);
- inserted++;
- } catch (Exception e) {
- log.debug("[RuleSeed] Rule {} already exists", rule.getRuleId());
+ ToolGuardRuleEntity existing = existingMap.get(rule.getRuleId());
+ if (existing == null) {
+ // 新规则 → 插入
+ try {
+ ruleMapper.insert(rule);
+ inserted++;
+ } catch (Exception e) {
+ log.debug("[RuleSeed] Rule {} insert failed: {}", rule.getRuleId(), e.getMessage());
+ }
+ } else if (needsUpdate(existing, rule)) {
+ // 已存在但内容有变化 → 更新
+ ruleMapper.update(null,
+ new LambdaUpdateWrapper()
+ .eq(ToolGuardRuleEntity::getRuleId, rule.getRuleId())
+ .set(ToolGuardRuleEntity::getName, rule.getName())
+ .set(ToolGuardRuleEntity::getDescription, rule.getDescription())
+ .set(ToolGuardRuleEntity::getPattern, rule.getPattern())
+ .set(ToolGuardRuleEntity::getSeverity, rule.getSeverity())
+ .set(ToolGuardRuleEntity::getCategory, rule.getCategory())
+ .set(ToolGuardRuleEntity::getDecision, rule.getDecision())
+ .set(ToolGuardRuleEntity::getToolName, rule.getToolName())
+ .set(ToolGuardRuleEntity::getRemediation, rule.getRemediation())
+ .set(ToolGuardRuleEntity::getPriority, rule.getPriority()));
+ updated++;
+ } else {
+ unchanged++;
}
}
- log.info("[RuleSeed] Seeded {} builtin rules", inserted);
+ log.info("[RuleSeed] Builtin rules: {} inserted, {} updated, {} unchanged",
+ inserted, updated, unchanged);
} catch (Exception e) {
log.warn("[RuleSeed] Failed to seed rules (table may not exist): {}", e.getMessage());
}
}
+ /**
+ * 判断已有 builtin 规则是否需要更新(任一核心字段有变化即需要)
+ */
+ private boolean needsUpdate(ToolGuardRuleEntity existing, ToolGuardRuleEntity expected) {
+ return !Objects.equals(existing.getPattern(), expected.getPattern())
+ || !Objects.equals(existing.getSeverity(), expected.getSeverity())
+ || !Objects.equals(existing.getCategory(), expected.getCategory())
+ || !Objects.equals(existing.getDecision(), expected.getDecision())
+ || !Objects.equals(existing.getToolName(), expected.getToolName())
+ || !Objects.equals(existing.getPriority(), expected.getPriority())
+ || !Objects.equals(existing.getName(), expected.getName())
+ || !Objects.equals(existing.getRemediation(), expected.getRemediation());
+ }
+
private List buildBuiltinRules() {
List rules = new ArrayList<>();
@@ -97,6 +242,10 @@ public class ToolGuardRuleSeedService implements ApplicationRunner {
"execute_shell_command", "此命令可能被用于远程控制", 200));
// === HIGH Shell Rules ===
+ rules.add(rule("SHELL_RM", "rm 删除命令", "(^|[;&|]|\\s)rm\\s",
+ GuardSeverity.HIGH, GuardCategory.COMMAND_INJECTION, "NEEDS_APPROVAL",
+ "execute_shell_command", "请确认要删除的文件列表,考虑使用 trash 替代 rm", 150));
+
rules.add(rule("SHELL_RM_RF", "递归强制删除", "rm\\s+-(rf|fr)",
GuardSeverity.HIGH, GuardCategory.COMMAND_INJECTION, "NEEDS_APPROVAL",
"execute_shell_command", "使用 rm -ri 或指定具体文件", 150));
diff --git a/mateclaw-server/src/main/resources/db/data-en.sql b/mateclaw-server/src/main/resources/db/data-en.sql
index ebf8d34c..b24c8cb5 100644
--- a/mateclaw-server/src/main/resources/db/data-en.sql
+++ b/mateclaw-server/src/main/resources/db/data-en.sql
@@ -1720,149 +1720,26 @@ VALUES (
-- ==================== ToolGuard Default Config & Rule Seed Data ====================
--- Global security config (single row)
-MERGE INTO mate_tool_guard_config (id, enabled, guard_scope, guarded_tools_json, denied_tools_json,
- file_guard_enabled, sensitive_paths_json, create_time, update_time)
-KEY (id)
-VALUES (
+-- Global security config (single row, insert only if not exists)
+-- Note: tool names in guarded_tools_json must match @Tool method names (execute_shell_command / write_file / edit_file)
+-- Use SELECT + INSERT to avoid overwriting user-modified config on restart (H2 MERGE would overwrite all columns)
+INSERT INTO mate_tool_guard_config (id, enabled, guard_scope, guarded_tools_json, denied_tools_json,
+ file_guard_enabled, sensitive_paths_json, audit_enabled, audit_min_severity, audit_retention_days,
+ create_time, update_time)
+SELECT
1000000001,
TRUE,
'all',
- '["WriteFileTool","EditFileTool","ShellExecuteTool"]',
+ '["write_file","edit_file","execute_shell_command"]',
'[]',
TRUE,
'["/etc","/usr","/bin","/sbin","/boot","/sys","/proc","/dev"]',
+ TRUE, 'INFO', 90,
NOW(), NOW()
-);
+FROM DUAL
+WHERE NOT EXISTS (SELECT 1 FROM mate_tool_guard_config WHERE id = 1000000001);
--- Security rule: WriteFileTool — any path write requires approval (HIGH)
-MERGE INTO mate_tool_guard_rule (id, rule_id, name, description, tool_name, param_name,
- category, severity, decision, pattern, exclude_pattern, remediation,
- builtin, enabled, priority, create_time, update_time, deleted)
-KEY (id)
-VALUES (
- 1000300001,
- 'write_file_any',
- 'File write requires approval',
- 'Any file write operation requires user confirmation to prevent accidental overwrite of important files',
- 'WriteFileTool',
- 'path',
- 'file_write',
- 'HIGH',
- 'NEEDS_APPROVAL',
- '.+',
- NULL,
- 'Please confirm write path and content are correct before allowing execution',
- TRUE, TRUE, 10,
- NOW(), NOW(), 0
-);
-
--- Security rule: EditFileTool — any file edit requires approval (HIGH)
-MERGE INTO mate_tool_guard_rule (id, rule_id, name, description, tool_name, param_name,
- category, severity, decision, pattern, exclude_pattern, remediation,
- builtin, enabled, priority, create_time, update_time, deleted)
-KEY (id)
-VALUES (
- 1000300002,
- 'edit_file_any',
- 'File edit requires approval',
- 'Any file content replacement operation requires user confirmation',
- 'EditFileTool',
- 'path',
- 'file_write',
- 'HIGH',
- 'NEEDS_APPROVAL',
- '.+',
- NULL,
- 'Please confirm edit path and replacement content are correct before allowing execution',
- TRUE, TRUE, 10,
- NOW(), NOW(), 0
-);
-
--- Security rule: ShellExecuteTool — delete commands require approval (HIGH)
-MERGE INTO mate_tool_guard_rule (id, rule_id, name, description, tool_name, param_name,
- category, severity, decision, pattern, exclude_pattern, remediation,
- builtin, enabled, priority, create_time, update_time, deleted)
-KEY (id)
-VALUES (
- 1000300003,
- 'shell_rm_approval',
- 'rm command requires approval',
- 'rm / rmdir commands may cause permanent file loss, requires user confirmation',
- 'ShellExecuteTool',
- 'command',
- 'shell_execution',
- 'HIGH',
- 'NEEDS_APPROVAL',
- '(?i)(^|[;&|]|\s)rm\s',
- NULL,
- 'Consider using trash command instead of rm, or confirm file list before allowing execution',
- TRUE, TRUE, 20,
- NOW(), NOW(), 0
-);
-
--- Security rule: ShellExecuteTool — forced recursive delete blocked (CRITICAL)
-MERGE INTO mate_tool_guard_rule (id, rule_id, name, description, tool_name, param_name,
- category, severity, decision, pattern, exclude_pattern, remediation,
- builtin, enabled, priority, create_time, update_time, deleted)
-KEY (id)
-VALUES (
- 1000300004,
- 'shell_rm_rf_block',
- 'rm -rf blocked',
- 'rm -rf forced recursive delete is extremely dangerous, blocked directly',
- 'ShellExecuteTool',
- 'command',
- 'shell_execution',
- 'CRITICAL',
- 'BLOCK',
- '(?i)rm\s+(-[a-z]*r[a-z]*f[a-z]*|-[a-z]*f[a-z]*r[a-z]*)\s+(/|~|\$HOME|\*|\.\s*$)',
- NULL,
- 'Absolutely forbidden to execute rm -rf on root directory, Home directory, or wildcards',
- TRUE, TRUE, 5,
- NOW(), NOW(), 0
-);
-
--- Security rule: ShellExecuteTool — writing system config files requires approval (HIGH)
-MERGE INTO mate_tool_guard_rule (id, rule_id, name, description, tool_name, param_name,
- category, severity, decision, pattern, exclude_pattern, remediation,
- builtin, enabled, priority, create_time, update_time, deleted)
-KEY (id)
-VALUES (
- 1000300005,
- 'shell_write_system_file',
- 'System file write requires approval',
- 'Writing to system directories like /etc or /usr via Shell requires user confirmation',
- 'ShellExecuteTool',
- 'command',
- 'shell_execution',
- 'HIGH',
- 'NEEDS_APPROVAL',
- '(?i)(>\s*|tee\s+|cp\s+.*\s+)(/etc/|/usr/|/bin/|/sbin/|/boot/)',
- NULL,
- 'Please confirm the system file and content to modify before allowing execution',
- TRUE, TRUE, 15,
- NOW(), NOW(), 0
-);
-
--- Security rule: ShellExecuteTool — chmod 777 requires approval (MEDIUM)
-MERGE INTO mate_tool_guard_rule (id, rule_id, name, description, tool_name, param_name,
- category, severity, decision, pattern, exclude_pattern, remediation,
- builtin, enabled, priority, create_time, update_time, deleted)
-KEY (id)
-VALUES (
- 1000300006,
- 'shell_chmod_777',
- 'chmod 777 requires approval',
- 'chmod 777 grants full permissions to all users, security risk',
- 'ShellExecuteTool',
- 'command',
- 'shell_execution',
- 'MEDIUM',
- 'NEEDS_APPROVAL',
- '(?i)chmod\s+(777|a\+rwx|o\+rwx)',
- NULL,
- 'Please confirm if full permissions for all users are truly needed',
- TRUE, TRUE, 30,
- NOW(), NOW(), 0
-);
+-- Security rules are managed by ToolGuardRuleSeedService (Java) as single source of truth.
+-- Removed 6 legacy SQL rules (rule_id: write_file_any, edit_file_any, shell_rm_approval,
+-- shell_rm_rf_block, shell_write_system_file, shell_chmod_777).
+-- Their superset is registered in ToolGuardRuleSeedService.buildBuiltinRules() with correct tool names.
diff --git a/mateclaw-server/src/main/resources/db/data-mysql-en.sql b/mateclaw-server/src/main/resources/db/data-mysql-en.sql
index fc6ae5d0..a3d476eb 100644
--- a/mateclaw-server/src/main/resources/db/data-mysql-en.sql
+++ b/mateclaw-server/src/main/resources/db/data-mysql-en.sql
@@ -1719,149 +1719,22 @@ ON DUPLICATE KEY UPDATE agent_id=VALUES(agent_id), filename=VALUES(filename), co
-- ==================== ToolGuard Default Config & Rule Seed Data ====================
--- Global security config (single row)
-INSERT INTO mate_tool_guard_config (id, enabled, guard_scope, guarded_tools_json, denied_tools_json,
- file_guard_enabled, sensitive_paths_json, create_time, update_time)
+-- Global security config (single row, insert only if not exists, never overwrite user config)
+-- Note: tool names in guarded_tools_json must match @Tool method names (execute_shell_command / write_file / edit_file)
+INSERT IGNORE INTO mate_tool_guard_config (id, enabled, guard_scope, guarded_tools_json, denied_tools_json,
+ file_guard_enabled, sensitive_paths_json, audit_enabled, audit_min_severity, audit_retention_days,
+ create_time, update_time)
VALUES (
1000000001,
TRUE,
'all',
- '["WriteFileTool","EditFileTool","ShellExecuteTool"]',
+ '["write_file","edit_file","execute_shell_command"]',
'[]',
TRUE,
'["/etc","/usr","/bin","/sbin","/boot","/sys","/proc","/dev"]',
+ TRUE, 'INFO', 90,
NOW(), NOW()
-)
-ON DUPLICATE KEY UPDATE enabled=VALUES(enabled), guard_scope=VALUES(guard_scope), guarded_tools_json=VALUES(guarded_tools_json), denied_tools_json=VALUES(denied_tools_json), file_guard_enabled=VALUES(file_guard_enabled), sensitive_paths_json=VALUES(sensitive_paths_json), update_time=VALUES(update_time);
+);
--- Security rule: WriteFileTool — any path write requires approval (HIGH)
-INSERT INTO mate_tool_guard_rule (id, rule_id, name, description, tool_name, param_name,
- category, severity, decision, pattern, exclude_pattern, remediation,
- builtin, enabled, priority, create_time, update_time, deleted)
-VALUES (
- 1000300001,
- 'write_file_any',
- 'File write requires approval',
- 'Any file write operation requires user confirmation to prevent accidental overwrite of important files',
- 'WriteFileTool',
- 'path',
- 'file_write',
- 'HIGH',
- 'NEEDS_APPROVAL',
- '.+',
- NULL,
- 'Please confirm write path and content are correct before allowing execution',
- TRUE, TRUE, 10,
- NOW(), NOW(), 0
-)
-ON DUPLICATE KEY UPDATE rule_id=VALUES(rule_id), name=VALUES(name), description=VALUES(description), tool_name=VALUES(tool_name), param_name=VALUES(param_name), category=VALUES(category), severity=VALUES(severity), decision=VALUES(decision), pattern=VALUES(pattern), exclude_pattern=VALUES(exclude_pattern), remediation=VALUES(remediation), builtin=VALUES(builtin), enabled=VALUES(enabled), priority=VALUES(priority), update_time=VALUES(update_time), deleted=VALUES(deleted);
-
--- Security rule: EditFileTool — any file edit requires approval (HIGH)
-INSERT INTO mate_tool_guard_rule (id, rule_id, name, description, tool_name, param_name,
- category, severity, decision, pattern, exclude_pattern, remediation,
- builtin, enabled, priority, create_time, update_time, deleted)
-VALUES (
- 1000300002,
- 'edit_file_any',
- 'File edit requires approval',
- 'Any file content replacement operation requires user confirmation',
- 'EditFileTool',
- 'path',
- 'file_write',
- 'HIGH',
- 'NEEDS_APPROVAL',
- '.+',
- NULL,
- 'Please confirm edit path and replacement content are correct before allowing execution',
- TRUE, TRUE, 10,
- NOW(), NOW(), 0
-)
-ON DUPLICATE KEY UPDATE rule_id=VALUES(rule_id), name=VALUES(name), description=VALUES(description), tool_name=VALUES(tool_name), param_name=VALUES(param_name), category=VALUES(category), severity=VALUES(severity), decision=VALUES(decision), pattern=VALUES(pattern), exclude_pattern=VALUES(exclude_pattern), remediation=VALUES(remediation), builtin=VALUES(builtin), enabled=VALUES(enabled), priority=VALUES(priority), update_time=VALUES(update_time), deleted=VALUES(deleted);
-
--- Security rule: ShellExecuteTool — delete commands require approval (HIGH)
-INSERT INTO mate_tool_guard_rule (id, rule_id, name, description, tool_name, param_name,
- category, severity, decision, pattern, exclude_pattern, remediation,
- builtin, enabled, priority, create_time, update_time, deleted)
-VALUES (
- 1000300003,
- 'shell_rm_approval',
- 'rm command requires approval',
- 'rm / rmdir commands may cause permanent file loss, requires user confirmation',
- 'ShellExecuteTool',
- 'command',
- 'shell_execution',
- 'HIGH',
- 'NEEDS_APPROVAL',
- '(?i)(^|[;&|]|\s)rm\s',
- NULL,
- 'Consider using trash command instead of rm, or confirm file list before allowing execution',
- TRUE, TRUE, 20,
- NOW(), NOW(), 0
-)
-ON DUPLICATE KEY UPDATE rule_id=VALUES(rule_id), name=VALUES(name), description=VALUES(description), tool_name=VALUES(tool_name), param_name=VALUES(param_name), category=VALUES(category), severity=VALUES(severity), decision=VALUES(decision), pattern=VALUES(pattern), exclude_pattern=VALUES(exclude_pattern), remediation=VALUES(remediation), builtin=VALUES(builtin), enabled=VALUES(enabled), priority=VALUES(priority), update_time=VALUES(update_time), deleted=VALUES(deleted);
-
--- Security rule: ShellExecuteTool — forced recursive delete blocked (CRITICAL)
-INSERT INTO mate_tool_guard_rule (id, rule_id, name, description, tool_name, param_name,
- category, severity, decision, pattern, exclude_pattern, remediation,
- builtin, enabled, priority, create_time, update_time, deleted)
-VALUES (
- 1000300004,
- 'shell_rm_rf_block',
- 'rm -rf blocked',
- 'rm -rf forced recursive delete is extremely dangerous, blocked directly',
- 'ShellExecuteTool',
- 'command',
- 'shell_execution',
- 'CRITICAL',
- 'BLOCK',
- '(?i)rm\s+(-[a-z]*r[a-z]*f[a-z]*|-[a-z]*f[a-z]*r[a-z]*)\s+(/|~|\$HOME|\*|\.\s*$)',
- NULL,
- 'Absolutely forbidden to execute rm -rf on root directory, Home directory, or wildcards',
- TRUE, TRUE, 5,
- NOW(), NOW(), 0
-)
-ON DUPLICATE KEY UPDATE rule_id=VALUES(rule_id), name=VALUES(name), description=VALUES(description), tool_name=VALUES(tool_name), param_name=VALUES(param_name), category=VALUES(category), severity=VALUES(severity), decision=VALUES(decision), pattern=VALUES(pattern), exclude_pattern=VALUES(exclude_pattern), remediation=VALUES(remediation), builtin=VALUES(builtin), enabled=VALUES(enabled), priority=VALUES(priority), update_time=VALUES(update_time), deleted=VALUES(deleted);
-
--- Security rule: ShellExecuteTool — writing system config files requires approval (HIGH)
-INSERT INTO mate_tool_guard_rule (id, rule_id, name, description, tool_name, param_name,
- category, severity, decision, pattern, exclude_pattern, remediation,
- builtin, enabled, priority, create_time, update_time, deleted)
-VALUES (
- 1000300005,
- 'shell_write_system_file',
- 'System file write requires approval',
- 'Writing to system directories like /etc or /usr via Shell requires user confirmation',
- 'ShellExecuteTool',
- 'command',
- 'shell_execution',
- 'HIGH',
- 'NEEDS_APPROVAL',
- '(?i)(>\s*|tee\s+|cp\s+.*\s+)(/etc/|/usr/|/bin/|/sbin/|/boot/)',
- NULL,
- 'Please confirm the system file and content to modify before allowing execution',
- TRUE, TRUE, 15,
- NOW(), NOW(), 0
-)
-ON DUPLICATE KEY UPDATE rule_id=VALUES(rule_id), name=VALUES(name), description=VALUES(description), tool_name=VALUES(tool_name), param_name=VALUES(param_name), category=VALUES(category), severity=VALUES(severity), decision=VALUES(decision), pattern=VALUES(pattern), exclude_pattern=VALUES(exclude_pattern), remediation=VALUES(remediation), builtin=VALUES(builtin), enabled=VALUES(enabled), priority=VALUES(priority), update_time=VALUES(update_time), deleted=VALUES(deleted);
-
--- Security rule: ShellExecuteTool — chmod 777 requires approval (MEDIUM)
-INSERT INTO mate_tool_guard_rule (id, rule_id, name, description, tool_name, param_name,
- category, severity, decision, pattern, exclude_pattern, remediation,
- builtin, enabled, priority, create_time, update_time, deleted)
-VALUES (
- 1000300006,
- 'shell_chmod_777',
- 'chmod 777 requires approval',
- 'chmod 777 grants full permissions to all users, security risk',
- 'ShellExecuteTool',
- 'command',
- 'shell_execution',
- 'MEDIUM',
- 'NEEDS_APPROVAL',
- '(?i)chmod\s+(777|a\+rwx|o\+rwx)',
- NULL,
- 'Please confirm if full permissions for all users are truly needed',
- TRUE, TRUE, 30,
- NOW(), NOW(), 0
-)
-ON DUPLICATE KEY UPDATE rule_id=VALUES(rule_id), name=VALUES(name), description=VALUES(description), tool_name=VALUES(tool_name), param_name=VALUES(param_name), category=VALUES(category), severity=VALUES(severity), decision=VALUES(decision), pattern=VALUES(pattern), exclude_pattern=VALUES(exclude_pattern), remediation=VALUES(remediation), builtin=VALUES(builtin), enabled=VALUES(enabled), priority=VALUES(priority), update_time=VALUES(update_time), deleted=VALUES(deleted);
+-- Security rules are managed by ToolGuardRuleSeedService (Java) as single source of truth.
+-- Removed 6 legacy SQL rules. Their superset is registered in ToolGuardRuleSeedService.buildBuiltinRules() with correct tool names.
diff --git a/mateclaw-server/src/main/resources/db/data-mysql-zh.sql b/mateclaw-server/src/main/resources/db/data-mysql-zh.sql
index 2c18ba96..0a5d77e3 100644
--- a/mateclaw-server/src/main/resources/db/data-mysql-zh.sql
+++ b/mateclaw-server/src/main/resources/db/data-mysql-zh.sql
@@ -1721,149 +1721,22 @@ ON DUPLICATE KEY UPDATE agent_id=VALUES(agent_id), filename=VALUES(filename), co
-- ==================== ToolGuard 默认配置与规则种子数据 ====================
--- 全局安全配置(只有一行)
-INSERT INTO mate_tool_guard_config (id, enabled, guard_scope, guarded_tools_json, denied_tools_json,
- file_guard_enabled, sensitive_paths_json, create_time, update_time)
+-- 全局安全配置(只有一行,仅首次初始化时插入,不覆盖用户修改)
+-- 注意:guarded_tools_json 中的工具名必须与 @Tool 方法名一致(execute_shell_command / write_file / edit_file)
+INSERT IGNORE INTO mate_tool_guard_config (id, enabled, guard_scope, guarded_tools_json, denied_tools_json,
+ file_guard_enabled, sensitive_paths_json, audit_enabled, audit_min_severity, audit_retention_days,
+ create_time, update_time)
VALUES (
1000000001,
TRUE,
'all',
- '["WriteFileTool","EditFileTool","ShellExecuteTool"]',
+ '["write_file","edit_file","execute_shell_command"]',
'[]',
TRUE,
'["/etc","/usr","/bin","/sbin","/boot","/sys","/proc","/dev"]',
+ TRUE, 'INFO', 90,
NOW(), NOW()
-)
-ON DUPLICATE KEY UPDATE enabled=VALUES(enabled), guard_scope=VALUES(guard_scope), guarded_tools_json=VALUES(guarded_tools_json), denied_tools_json=VALUES(denied_tools_json), file_guard_enabled=VALUES(file_guard_enabled), sensitive_paths_json=VALUES(sensitive_paths_json), update_time=VALUES(update_time);
+);
--- 安全规则:WriteFileTool — 任意路径写入需要审批(HIGH)
-INSERT INTO mate_tool_guard_rule (id, rule_id, name, description, tool_name, param_name,
- category, severity, decision, pattern, exclude_pattern, remediation,
- builtin, enabled, priority, create_time, update_time, deleted)
-VALUES (
- 1000300001,
- 'write_file_any',
- '文件写入需审批',
- '任何文件写入操作都需要用户确认,防止意外覆盖重要文件',
- 'WriteFileTool',
- 'path',
- 'file_write',
- 'HIGH',
- 'NEEDS_APPROVAL',
- '.+',
- NULL,
- '请确认写入路径和内容正确后再允许执行',
- TRUE, TRUE, 10,
- NOW(), NOW(), 0
-)
-ON DUPLICATE KEY UPDATE rule_id=VALUES(rule_id), name=VALUES(name), description=VALUES(description), tool_name=VALUES(tool_name), param_name=VALUES(param_name), category=VALUES(category), severity=VALUES(severity), decision=VALUES(decision), pattern=VALUES(pattern), exclude_pattern=VALUES(exclude_pattern), remediation=VALUES(remediation), builtin=VALUES(builtin), enabled=VALUES(enabled), priority=VALUES(priority), update_time=VALUES(update_time), deleted=VALUES(deleted);
-
--- 安全规则:EditFileTool — 任意文件编辑需要审批(HIGH)
-INSERT INTO mate_tool_guard_rule (id, rule_id, name, description, tool_name, param_name,
- category, severity, decision, pattern, exclude_pattern, remediation,
- builtin, enabled, priority, create_time, update_time, deleted)
-VALUES (
- 1000300002,
- 'edit_file_any',
- '文件编辑需审批',
- '任何文件内容替换操作都需要用户确认',
- 'EditFileTool',
- 'path',
- 'file_write',
- 'HIGH',
- 'NEEDS_APPROVAL',
- '.+',
- NULL,
- '请确认编辑路径和替换内容正确后再允许执行',
- TRUE, TRUE, 10,
- NOW(), NOW(), 0
-)
-ON DUPLICATE KEY UPDATE rule_id=VALUES(rule_id), name=VALUES(name), description=VALUES(description), tool_name=VALUES(tool_name), param_name=VALUES(param_name), category=VALUES(category), severity=VALUES(severity), decision=VALUES(decision), pattern=VALUES(pattern), exclude_pattern=VALUES(exclude_pattern), remediation=VALUES(remediation), builtin=VALUES(builtin), enabled=VALUES(enabled), priority=VALUES(priority), update_time=VALUES(update_time), deleted=VALUES(deleted);
-
--- 安全规则:ShellExecuteTool — 删除命令需审批(HIGH)
-INSERT INTO mate_tool_guard_rule (id, rule_id, name, description, tool_name, param_name,
- category, severity, decision, pattern, exclude_pattern, remediation,
- builtin, enabled, priority, create_time, update_time, deleted)
-VALUES (
- 1000300003,
- 'shell_rm_approval',
- 'rm 命令需审批',
- 'rm / rmdir 命令可能导致文件永久丢失,需要用户确认',
- 'ShellExecuteTool',
- 'command',
- 'shell_execution',
- 'HIGH',
- 'NEEDS_APPROVAL',
- '(?i)(^|[;&|]|\s)rm\s',
- NULL,
- '考虑使用 trash 命令替代 rm,或确认要删除的文件列表后再允许执行',
- TRUE, TRUE, 20,
- NOW(), NOW(), 0
-)
-ON DUPLICATE KEY UPDATE rule_id=VALUES(rule_id), name=VALUES(name), description=VALUES(description), tool_name=VALUES(tool_name), param_name=VALUES(param_name), category=VALUES(category), severity=VALUES(severity), decision=VALUES(decision), pattern=VALUES(pattern), exclude_pattern=VALUES(exclude_pattern), remediation=VALUES(remediation), builtin=VALUES(builtin), enabled=VALUES(enabled), priority=VALUES(priority), update_time=VALUES(update_time), deleted=VALUES(deleted);
-
--- 安全规则:ShellExecuteTool — 强制递归删除直接拦截(CRITICAL)
-INSERT INTO mate_tool_guard_rule (id, rule_id, name, description, tool_name, param_name,
- category, severity, decision, pattern, exclude_pattern, remediation,
- builtin, enabled, priority, create_time, update_time, deleted)
-VALUES (
- 1000300004,
- 'shell_rm_rf_block',
- 'rm -rf 直接拦截',
- 'rm -rf 强制递归删除极度危险,直接拦截',
- 'ShellExecuteTool',
- 'command',
- 'shell_execution',
- 'CRITICAL',
- 'BLOCK',
- '(?i)rm\s+(-[a-z]*r[a-z]*f[a-z]*|-[a-z]*f[a-z]*r[a-z]*)\s+(/|~|\$HOME|\*|\.\s*$)',
- NULL,
- '绝对禁止对根目录、Home 目录或通配符执行 rm -rf',
- TRUE, TRUE, 5,
- NOW(), NOW(), 0
-)
-ON DUPLICATE KEY UPDATE rule_id=VALUES(rule_id), name=VALUES(name), description=VALUES(description), tool_name=VALUES(tool_name), param_name=VALUES(param_name), category=VALUES(category), severity=VALUES(severity), decision=VALUES(decision), pattern=VALUES(pattern), exclude_pattern=VALUES(exclude_pattern), remediation=VALUES(remediation), builtin=VALUES(builtin), enabled=VALUES(enabled), priority=VALUES(priority), update_time=VALUES(update_time), deleted=VALUES(deleted);
-
--- 安全规则:ShellExecuteTool — 写入系统配置文件需审批(HIGH)
-INSERT INTO mate_tool_guard_rule (id, rule_id, name, description, tool_name, param_name,
- category, severity, decision, pattern, exclude_pattern, remediation,
- builtin, enabled, priority, create_time, update_time, deleted)
-VALUES (
- 1000300005,
- 'shell_write_system_file',
- '写入系统文件需审批',
- '通过 Shell 向 /etc / /usr 等系统目录写入内容需要用户确认',
- 'ShellExecuteTool',
- 'command',
- 'shell_execution',
- 'HIGH',
- 'NEEDS_APPROVAL',
- '(?i)(>\s*|tee\s+|cp\s+.*\s+)(/etc/|/usr/|/bin/|/sbin/|/boot/)',
- NULL,
- '请确认要修改的系统文件和内容后再允许执行',
- TRUE, TRUE, 15,
- NOW(), NOW(), 0
-)
-ON DUPLICATE KEY UPDATE rule_id=VALUES(rule_id), name=VALUES(name), description=VALUES(description), tool_name=VALUES(tool_name), param_name=VALUES(param_name), category=VALUES(category), severity=VALUES(severity), decision=VALUES(decision), pattern=VALUES(pattern), exclude_pattern=VALUES(exclude_pattern), remediation=VALUES(remediation), builtin=VALUES(builtin), enabled=VALUES(enabled), priority=VALUES(priority), update_time=VALUES(update_time), deleted=VALUES(deleted);
-
--- 安全规则:ShellExecuteTool — chmod 777 需审批(MEDIUM)
-INSERT INTO mate_tool_guard_rule (id, rule_id, name, description, tool_name, param_name,
- category, severity, decision, pattern, exclude_pattern, remediation,
- builtin, enabled, priority, create_time, update_time, deleted)
-VALUES (
- 1000300006,
- 'shell_chmod_777',
- 'chmod 777 需审批',
- 'chmod 777 给予所有用户完全权限,存在安全风险',
- 'ShellExecuteTool',
- 'command',
- 'shell_execution',
- 'MEDIUM',
- 'NEEDS_APPROVAL',
- '(?i)chmod\s+(777|a\+rwx|o\+rwx)',
- NULL,
- '请确认是否真的需要给予所有用户完全权限',
- TRUE, TRUE, 30,
- NOW(), NOW(), 0
-)
-ON DUPLICATE KEY UPDATE rule_id=VALUES(rule_id), name=VALUES(name), description=VALUES(description), tool_name=VALUES(tool_name), param_name=VALUES(param_name), category=VALUES(category), severity=VALUES(severity), decision=VALUES(decision), pattern=VALUES(pattern), exclude_pattern=VALUES(exclude_pattern), remediation=VALUES(remediation), builtin=VALUES(builtin), enabled=VALUES(enabled), priority=VALUES(priority), update_time=VALUES(update_time), deleted=VALUES(deleted);
+-- 安全规则由 ToolGuardRuleSeedService (Java) 统一种子化,不在 SQL 中重复维护
+-- 已移除旧的 6 条 SQL 规则,其超集已在 ToolGuardRuleSeedService.buildBuiltinRules() 中以正确的工具名注册。
diff --git a/mateclaw-server/src/main/resources/db/data-zh.sql b/mateclaw-server/src/main/resources/db/data-zh.sql
index b19f185e..fb4296b7 100644
--- a/mateclaw-server/src/main/resources/db/data-zh.sql
+++ b/mateclaw-server/src/main/resources/db/data-zh.sql
@@ -1724,149 +1724,26 @@ VALUES (
-- ==================== ToolGuard 默认配置与规则种子数据 ====================
--- 全局安全配置(只有一行)
-MERGE INTO mate_tool_guard_config (id, enabled, guard_scope, guarded_tools_json, denied_tools_json,
- file_guard_enabled, sensitive_paths_json, create_time, update_time)
-KEY (id)
-VALUES (
+-- 全局安全配置(只有一行,仅首次初始化时插入)
+-- 注意:guarded_tools_json 中的工具名必须与 @Tool 方法名一致(execute_shell_command / write_file / edit_file)
+-- 使用 SELECT + INSERT 确保已存在时不覆盖(H2 的 MERGE 会覆盖所有列,会重置用户修改的配置)
+INSERT INTO mate_tool_guard_config (id, enabled, guard_scope, guarded_tools_json, denied_tools_json,
+ file_guard_enabled, sensitive_paths_json, audit_enabled, audit_min_severity, audit_retention_days,
+ create_time, update_time)
+SELECT
1000000001,
TRUE,
'all',
- '["WriteFileTool","EditFileTool","ShellExecuteTool"]',
+ '["write_file","edit_file","execute_shell_command"]',
'[]',
TRUE,
'["/etc","/usr","/bin","/sbin","/boot","/sys","/proc","/dev"]',
+ TRUE, 'INFO', 90,
NOW(), NOW()
-);
+FROM DUAL
+WHERE NOT EXISTS (SELECT 1 FROM mate_tool_guard_config WHERE id = 1000000001);
--- 安全规则:WriteFileTool — 任意路径写入需要审批(HIGH)
-MERGE INTO mate_tool_guard_rule (id, rule_id, name, description, tool_name, param_name,
- category, severity, decision, pattern, exclude_pattern, remediation,
- builtin, enabled, priority, create_time, update_time, deleted)
-KEY (id)
-VALUES (
- 1000300001,
- 'write_file_any',
- '文件写入需审批',
- '任何文件写入操作都需要用户确认,防止意外覆盖重要文件',
- 'WriteFileTool',
- 'path',
- 'file_write',
- 'HIGH',
- 'NEEDS_APPROVAL',
- '.+',
- NULL,
- '请确认写入路径和内容正确后再允许执行',
- TRUE, TRUE, 10,
- NOW(), NOW(), 0
-);
-
--- 安全规则:EditFileTool — 任意文件编辑需要审批(HIGH)
-MERGE INTO mate_tool_guard_rule (id, rule_id, name, description, tool_name, param_name,
- category, severity, decision, pattern, exclude_pattern, remediation,
- builtin, enabled, priority, create_time, update_time, deleted)
-KEY (id)
-VALUES (
- 1000300002,
- 'edit_file_any',
- '文件编辑需审批',
- '任何文件内容替换操作都需要用户确认',
- 'EditFileTool',
- 'path',
- 'file_write',
- 'HIGH',
- 'NEEDS_APPROVAL',
- '.+',
- NULL,
- '请确认编辑路径和替换内容正确后再允许执行',
- TRUE, TRUE, 10,
- NOW(), NOW(), 0
-);
-
--- 安全规则:ShellExecuteTool — 删除命令需审批(HIGH)
-MERGE INTO mate_tool_guard_rule (id, rule_id, name, description, tool_name, param_name,
- category, severity, decision, pattern, exclude_pattern, remediation,
- builtin, enabled, priority, create_time, update_time, deleted)
-KEY (id)
-VALUES (
- 1000300003,
- 'shell_rm_approval',
- 'rm 命令需审批',
- 'rm / rmdir 命令可能导致文件永久丢失,需要用户确认',
- 'ShellExecuteTool',
- 'command',
- 'shell_execution',
- 'HIGH',
- 'NEEDS_APPROVAL',
- '(?i)(^|[;&|]|\s)rm\s',
- NULL,
- '考虑使用 trash 命令替代 rm,或确认要删除的文件列表后再允许执行',
- TRUE, TRUE, 20,
- NOW(), NOW(), 0
-);
-
--- 安全规则:ShellExecuteTool — 强制递归删除直接拦截(CRITICAL)
-MERGE INTO mate_tool_guard_rule (id, rule_id, name, description, tool_name, param_name,
- category, severity, decision, pattern, exclude_pattern, remediation,
- builtin, enabled, priority, create_time, update_time, deleted)
-KEY (id)
-VALUES (
- 1000300004,
- 'shell_rm_rf_block',
- 'rm -rf 直接拦截',
- 'rm -rf 强制递归删除极度危险,直接拦截',
- 'ShellExecuteTool',
- 'command',
- 'shell_execution',
- 'CRITICAL',
- 'BLOCK',
- '(?i)rm\s+(-[a-z]*r[a-z]*f[a-z]*|-[a-z]*f[a-z]*r[a-z]*)\s+(/|~|\$HOME|\*|\.\s*$)',
- NULL,
- '绝对禁止对根目录、Home 目录或通配符执行 rm -rf',
- TRUE, TRUE, 5,
- NOW(), NOW(), 0
-);
-
--- 安全规则:ShellExecuteTool — 写入系统配置文件需审批(HIGH)
-MERGE INTO mate_tool_guard_rule (id, rule_id, name, description, tool_name, param_name,
- category, severity, decision, pattern, exclude_pattern, remediation,
- builtin, enabled, priority, create_time, update_time, deleted)
-KEY (id)
-VALUES (
- 1000300005,
- 'shell_write_system_file',
- '写入系统文件需审批',
- '通过 Shell 向 /etc / /usr 等系统目录写入内容需要用户确认',
- 'ShellExecuteTool',
- 'command',
- 'shell_execution',
- 'HIGH',
- 'NEEDS_APPROVAL',
- '(?i)(>\s*|tee\s+|cp\s+.*\s+)(/etc/|/usr/|/bin/|/sbin/|/boot/)',
- NULL,
- '请确认要修改的系统文件和内容后再允许执行',
- TRUE, TRUE, 15,
- NOW(), NOW(), 0
-);
-
--- 安全规则:ShellExecuteTool — chmod 777 需审批(MEDIUM)
-MERGE INTO mate_tool_guard_rule (id, rule_id, name, description, tool_name, param_name,
- category, severity, decision, pattern, exclude_pattern, remediation,
- builtin, enabled, priority, create_time, update_time, deleted)
-KEY (id)
-VALUES (
- 1000300006,
- 'shell_chmod_777',
- 'chmod 777 需审批',
- 'chmod 777 给予所有用户完全权限,存在安全风险',
- 'ShellExecuteTool',
- 'command',
- 'shell_execution',
- 'MEDIUM',
- 'NEEDS_APPROVAL',
- '(?i)chmod\s+(777|a\+rwx|o\+rwx)',
- NULL,
- '请确认是否真的需要给予所有用户完全权限',
- TRUE, TRUE, 30,
- NOW(), NOW(), 0
-);
+-- 安全规则由 ToolGuardRuleSeedService (Java) 统一种子化,不在 SQL 中重复维护
+-- 已移除旧的 6 条 SQL 规则(rule_id: write_file_any, edit_file_any, shell_rm_approval,
+-- shell_rm_rf_block, shell_write_system_file, shell_chmod_777),
+-- 它们的超集已在 ToolGuardRuleSeedService.buildBuiltinRules() 中以正确的工具名注册。
diff --git a/mateclaw-server/src/main/resources/db/schema-mysql.sql b/mateclaw-server/src/main/resources/db/schema-mysql.sql
index de226ac1..d2036df6 100644
--- a/mateclaw-server/src/main/resources/db/schema-mysql.sql
+++ b/mateclaw-server/src/main/resources/db/schema-mysql.sql
@@ -347,6 +347,9 @@ CREATE TABLE IF NOT EXISTS mate_tool_guard_config (
denied_tools_json TEXT,
file_guard_enabled TINYINT(1) NOT NULL DEFAULT 1,
sensitive_paths_json TEXT,
+ audit_enabled TINYINT(1) NOT NULL DEFAULT 1,
+ audit_min_severity VARCHAR(16) NOT NULL DEFAULT 'INFO',
+ audit_retention_days INT NOT NULL DEFAULT 90,
create_time DATETIME NOT NULL,
update_time DATETIME NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
diff --git a/mateclaw-server/src/main/resources/db/schema.sql b/mateclaw-server/src/main/resources/db/schema.sql
index 99fe0986..6fb75a5f 100644
--- a/mateclaw-server/src/main/resources/db/schema.sql
+++ b/mateclaw-server/src/main/resources/db/schema.sql
@@ -357,6 +357,9 @@ CREATE TABLE IF NOT EXISTS mate_tool_guard_config (
denied_tools_json TEXT,
file_guard_enabled BOOLEAN NOT NULL DEFAULT TRUE,
sensitive_paths_json TEXT,
+ audit_enabled BOOLEAN NOT NULL DEFAULT TRUE,
+ audit_min_severity VARCHAR(16) NOT NULL DEFAULT 'INFO',
+ audit_retention_days INT NOT NULL DEFAULT 90,
create_time DATETIME NOT NULL,
update_time DATETIME NOT NULL
);
diff --git a/mateclaw-ui/src/i18n/locales/en-US.ts b/mateclaw-ui/src/i18n/locales/en-US.ts
index 6f8e9304..16be5a74 100644
--- a/mateclaw-ui/src/i18n/locales/en-US.ts
+++ b/mateclaw-ui/src/i18n/locales/en-US.ts
@@ -488,6 +488,15 @@ export default {
audit: {
title: 'Audit Logs',
desc: 'View tool security check records',
+ config: {
+ title: 'Audit Configuration',
+ enabled: 'Enable Audit Logging',
+ enabledHint: 'When disabled, tool invocation audit logs will not be recorded',
+ minSeverity: 'Minimum Severity',
+ minSeverityHint: 'Only record audit events at this severity level and above',
+ retentionDays: 'Retention Days',
+ retentionDaysHint: 'Audit logs older than this will be auto-cleaned (0=never)',
+ },
stats: {
total: 'Total Checks',
blocked: 'Blocked',
diff --git a/mateclaw-ui/src/i18n/locales/zh-CN.ts b/mateclaw-ui/src/i18n/locales/zh-CN.ts
index 33ddc1d8..0127a51f 100644
--- a/mateclaw-ui/src/i18n/locales/zh-CN.ts
+++ b/mateclaw-ui/src/i18n/locales/zh-CN.ts
@@ -488,6 +488,15 @@ export default {
audit: {
title: '审计日志',
desc: '查看工具安全检查记录',
+ config: {
+ title: '审计配置',
+ enabled: '启用审计日志',
+ enabledHint: '关闭后将不再记录工具调用审计日志',
+ minSeverity: '最低记录等级',
+ minSeverityHint: '仅记录达到此等级及以上的审计事件',
+ retentionDays: '保留天数',
+ retentionDaysHint: '超过此天数的审计日志将被自动清理(0=永不清理)',
+ },
stats: {
total: '总检查',
blocked: '已阻止',
diff --git a/mateclaw-ui/src/types/index.ts b/mateclaw-ui/src/types/index.ts
index f742091a..097e6b9a 100644
--- a/mateclaw-ui/src/types/index.ts
+++ b/mateclaw-ui/src/types/index.ts
@@ -584,6 +584,9 @@ export interface GuardConfig {
deniedToolsJson?: string
fileGuardEnabled: boolean
sensitivePathsJson?: string
+ auditEnabled?: boolean
+ auditMinSeverity?: string
+ auditRetentionDays?: number
}
export interface AuditLogEntry {
diff --git a/mateclaw-ui/src/views/Security/AuditLogs/index.vue b/mateclaw-ui/src/views/Security/AuditLogs/index.vue
index 26f3b01e..5efd9c71 100644
--- a/mateclaw-ui/src/views/Security/AuditLogs/index.vue
+++ b/mateclaw-ui/src/views/Security/AuditLogs/index.vue
@@ -7,6 +7,46 @@
+
+
+
{{ t('security.audit.config.title') }}
+
+
+
+
+
+
+
{{ t('security.audit.config.enabledHint') }}
+
+
+
+
+
{{ t('security.audit.config.minSeverityHint') }}
+
+
+
+
+
{{ t('security.audit.config.retentionDaysHint') }}
+
+
+
+
@@ -148,6 +188,37 @@ const auditTotal = ref(0)
const auditFilters = reactive({ toolName: '', decision: '' })
const expandedRows = ref(new Set())
+// Audit config
+const auditConfig = reactive({
+ auditEnabled: true,
+ auditMinSeverity: 'INFO',
+ auditRetentionDays: 90,
+})
+
+async function loadAuditConfig() {
+ try {
+ const res: any = await securityApi.getGuardConfig()
+ const data = res.data || {}
+ auditConfig.auditEnabled = data.auditEnabled ?? true
+ auditConfig.auditMinSeverity = data.auditMinSeverity || 'INFO'
+ auditConfig.auditRetentionDays = data.auditRetentionDays ?? 90
+ } catch {
+ // ignore
+ }
+}
+
+async function saveAuditConfig() {
+ try {
+ await securityApi.updateGuardConfig({
+ auditEnabled: auditConfig.auditEnabled,
+ auditMinSeverity: auditConfig.auditMinSeverity,
+ auditRetentionDays: auditConfig.auditRetentionDays,
+ })
+ } catch {
+ // ignore
+ }
+}
+
async function loadAuditLogs() {
try {
const params: any = {
@@ -183,7 +254,7 @@ function toggleExpand(id: number) {
}
onMounted(async () => {
- await Promise.all([loadAuditLogs(), loadAuditStats()])
+ await Promise.all([loadAuditConfig(), loadAuditLogs(), loadAuditStats()])
})
@@ -192,6 +263,95 @@ onMounted(async () => {