mirror of
https://github.com/Ed1s0nZ/CyberStrikeAI.git
synced 2026-10-19 05:57:39 +02:00
fix: reject stale concurrent interception rule saves
This commit is contained in:
1 parent
4a1d0e114e
commit
1ecbd4054c
14 files changed
+295
-19
No files matched your search
@@ -12,6 +12,8 @@ Use **Test all rules** in the page header to check the configured order and enab
|
||||
|
||||
Saving validates every rule, including disabled rules, writes only the `tool_guard` YAML section, and applies the policy immediately. Validation or write failure preserves the existing protection. Manual YAML edits require a restart; a non-null `tool_guard` section must explicitly provide `enabled` and `rules` (use `[]` for no rules). The first matching enabled rule supplies the reminder. Rules use Go/RE2 syntax; lookarounds and backreferences are unsupported. Up to 100 rules are allowed, with patterns and reminder templates capped at 4096 bytes each.
|
||||
|
||||
When multiple users edit the same configuration version, only the first save succeeds. Stale saves report a conflict and retain the local draft. Copy any edits you need to keep, refresh to load the latest configuration, and edit again; repeating a stale save cannot overwrite another user's changes. Saving replaces the full rule list, so edits to different rules can also conflict.
|
||||
|
||||
Reminder placeholders are `{match}` (matched text), `{tool}` (tool name), and `{rule}` (rule name). An optional named group `(?P<match>...)` selects the matched text. Empty templates use a default reminder.
|
||||
|
||||
Checks inspect the tool name, serialized JSON, nested strings and keys, and up to three rounds of common URL percent decoding. Blocked calls use a separate **Blocked** status in the UI and execution records, with the reason preserved. Monitoring counts blocks separately and excludes them from failed calls and the success-rate denominator. At startup after an upgrade, clearly identifiable legacy guard-block records are migrated to this status. MCP results retain `isError: true` alongside `blocked: true` so the agent knows the request did not execute. External MCP policy blocks do not count as provider failures for circuit breaking. Updated rules cannot cancel calls already dispatched.
|
||||
@@ -22,6 +24,6 @@ Text matching cannot establish target ownership from IP addresses, DNS aliases,
|
||||
|
||||
API endpoints:
|
||||
|
||||
- `GET /api/tool-guard`: active `{enabled, rules}` configuration.
|
||||
- `PUT /api/tool-guard`: save that structure, explicitly providing both fields. Rules contain `id`, `name`, `enabled`, `pattern`, and `message`.
|
||||
- `GET /api/tool-guard`: active `{enabled, rules}` configuration with an `ETag` response header and `Cache-Control: no-store`.
|
||||
- `PUT /api/tool-guard`: save that structure, explicitly providing both fields. Rules contain `id`, `name`, `enabled`, `pattern`, and `message`. Send the complete ETag from the read (including quotes) in `If-Match`. Missing versions return HTTP 428 / `tool_guard_version_required`; stale versions return HTTP 409 / `tool_guard_conflict`, without saving. Successful saves return a new ETag. Existing API clients must adopt this protocol; `*` cannot bypass it. Read a new version after a server restart. Coordination is scoped to the current service instance, not multiple instances sharing configuration.
|
||||
- `POST /api/tool-guard/test`: accepts `{config, toolName, arguments}` and returns `{blocked, match?}`. Match fields are `ruleId`, `ruleName`, `matchedText`, and `message`.
|
||||
@@ -35,3 +35,9 @@ PUT 必须携带完整精确匹配的 If-Match;未提供返回 428/tool_guard_
|
||||
修改 internal/handler/config.go 一个字段、tool_guard.go 的版本协议;扩展专项 handler 测试验证真实并发单赢家、顺序旧草稿、无条件写拒绝、无变化保存、失败版本不变、manager 直接更新。修改 tool-guard.js 的版本状态和请求头,中英俄语言提示及 index.html 的 JS 缓存版本;扩展现有 VM 前端测试验证两个页面冲突、草稿保留、重试不换版本、成功更新版本、试匹配无副作用。更新中英文调用拦截文档、Unreleased changelog。
|
||||
|
||||
验证命令:go test -race ./internal/handler -run ToolGuard;node --test web/static/js/tool-guard.test.cjs;node --check web/static/js/tool-guard.js;git diff --check。必要时完整 handler 测试确认共享 ConfigHandler 无回归。测试只用临时目录和请求 fixture,不触碰线上业务数据。回滚需要前后端一起回滚,但会恢复覆盖风险;不执行部署。
|
||||
|
||||
## F4 Implementation
|
||||
|
||||
已实现持锁 ETag 比较与版本推进,强制条件保存;无条件写入 428,旧版本 409,成功保存返回新版本。前端独立记录基线版本,错误不会采用响应新版本,保留草稿;只在 GET/PUT 处理版本,试匹配不参与。中英俄提示及脚本缓存版本已更新。
|
||||
|
||||
专项 race 测试通过(3.246s),覆盖 12 个并发请求仅 1 成功、落盘/运行策略与成功回执一致、顺序旧草稿失败、缺版本/星号/弱版本拒绝、无变化保存推进版本、落盘失败可安全重试、manager 直接更新冲突。前端 36/36 通过(135ms),覆盖两个页面竞争、重试不偷偷换版本、草稿保留、重新读取后保存、失败版本保留及试匹配无版本头。JS syntax/diff check 通过;完整 handler 回归正在执行。
|
||||
@@ -9,7 +9,7 @@
|
||||
1. 打开「安全防护 → 调用拦截」。默认开启「政府网站保护」,匹配 `.gov`、`.gov.cn` 等政府域名及通配符写法,忽略大小写。旧配置没有 `tool_guard` 时也启用默认保护。
|
||||
2. 规则默认折叠,列表展示名称、提醒摘要和启停开关。点击规则展开编辑;「添加规则」打开独立弹窗,可以填写并验证尚未添加的规则。点击「添加到列表」通过正则校验后加入页面草稿,取消不会留下空规则。校验失败会定位到对应字段。可以单独启停规则,也可以关闭总开关。
|
||||
3. 点击页面顶部「全部规则验证」按当前顺序及启停状态检查全部规则。在已有规则编辑区点击「验证本条」,就在该规则下方输入工具名和 JSON 参数、查看命中文本与最终提醒;新增规则的单条验证直接在弹窗中完成。单条验证忽略总开关和该规则的启停状态,适合调试未启用规则。单条和全部验证分别保留输入与结果,均使用未保存的表单配置,不执行工具,也不改变运行中的规则。
|
||||
4. 点击保存。服务端校验全部规则后写入 `config.yaml` 的 `tool_guard`,立即生效,无需重启。校验或写入失败会保留原有规则。直接编辑 YAML 后需要重启服务;非空 `tool_guard` 必须明确填写 `enabled` 和 `rules`,清空规则使用 `[]`。
|
||||
4. 点击保存。服务端校验全部规则后写入 `config.yaml` 的 `tool_guard`,立即生效,无需重启。校验或写入失败会保留原有规则。多人基于同一版本编辑时,只有首次保存成功;后续旧版本保存会提示配置已被其他用户修改,并保留当前草稿。请先复制需要保留的修改,再刷新页面获取最新配置后重新编辑保存;直接重复提交不会覆盖他人修改。由于保存整个规则列表,编辑不同规则也会触发版本冲突。直接编辑 YAML 后需要重启服务;非空 `tool_guard` 必须明确填写 `enabled` 和 `rules`,清空规则使用 `[]`。
|
||||
|
||||
规则按列表顺序检查,首先命中的启用规则决定提醒。检查对象包括工具名称、参数的 JSON 表示、嵌套字符串和键名,以及最多三轮常见 URL 百分号解码后的文本。使用 Go/RE2 正则语法,例如 `(?i)` 表示忽略大小写;不支持回溯引用和环视。最多 100 条规则,正则和提醒各最多 4096 字节。禁用的规则也须通过校验。
|
||||
|
||||
@@ -33,6 +33,6 @@
|
||||
|
||||
## API
|
||||
|
||||
- `GET /api/tool-guard`:返回生效配置 `{enabled, rules}`。
|
||||
- `PUT /api/tool-guard`:保存相同结构;每条规则含 `id`、`name`、`enabled`、`pattern`、`message`。必须明确提供总开关和规则数组。
|
||||
- `GET /api/tool-guard`:返回生效配置 `{enabled, rules}`,响应头包含 `ETag`,并禁止缓存。
|
||||
- `PUT /api/tool-guard`:保存相同结构;每条规则含 `id`、`name`、`enabled`、`pattern`、`message`。必须明确提供总开关和规则数组,并将读取时的完整 `ETag`(包含引号)原样放入 `If-Match` 请求头。缺少版本返回 HTTP 428 / `tool_guard_version_required`;版本过期返回 HTTP 409 / `tool_guard_conflict`,均不保存。成功返回新的 `ETag`;服务重启后须重新读取版本。旧客户端也必须遵循此协议,不能使用 `*` 绕过检测。版本保护适用于当前服务实例,不提供多实例共享配置协调。
|
||||
- `POST /api/tool-guard/test`:请求 `{config, toolName, arguments}`,响应 `{blocked, match?}`;`match` 含 `ruleId`、`ruleName`、`matchedText`、`message`。
|
||||
Reference in new issue
Block a user