From b2079fea0a7b39dadec162753a82af13a8f684bc Mon Sep 17 00:00:00 2001 From: JianFeeeee Date: Tue, 3 Nov 2026 08:43:51 +0800 Subject: [PATCH] =?UTF-8?q?docs(security):=20=E5=86=85=E5=AE=B9=E5=AE=A1?= =?UTF-8?q?=E6=9F=A5=E6=8E=A5=E7=BA=BF=E5=B7=B2=E7=BB=93=E6=A1=88=EF=BC=8C?= =?UTF-8?q?=E5=90=8C=E6=AD=A5=E4=B8=A4=E5=BC=A0=E7=8A=B6=E6=80=81=E8=A1=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - kernel-secret-firewall-design.md 接线状态表:ScanContent 一行 从 🔴「配置里的敏感词一条不生效」改为 ✅ 2026-11-02 接通, 并写明两处落点与 B 档语义(标记+警示,不阻断)。 - future-plan.md §一 汇总表第 4 行同步为 ✅。 - §1.2 改写为「已结案」,保留两条教训: ① 第一版让 agent 自己解析档位 —— 正是 §1.1 收敛掉的第 2 层毛病, 盲试两轮才回去读设计文档;设计里早就写清了落点。 ② 最初 6 条判据只测辅助函数,删掉 task.go 的调用仍全绿 —— 与「实现完整、判据绿、生产零调用」的原始缺陷形态一模一样。 补了走真实入口 runInputTask 的那条才真的变红。 仍零生产调用方的:路径沙箱 CheckPath、网络闸 CheckNetwork(见 §1.3)。 --- docs/zh/future-plan.md | 72 +++++++++++++++++++----- docs/zh/kernel-secret-firewall-design.md | 5 +- 2 files changed, 61 insertions(+), 16 deletions(-) diff --git a/docs/zh/future-plan.md b/docs/zh/future-plan.md index c08c8dc7..01d5c7e9 100644 --- a/docs/zh/future-plan.md +++ b/docs/zh/future-plan.md @@ -39,7 +39,7 @@ | 1 | 工具黑白名单 `Policy.CheckTool` | 完整 | `Agent.security` 恒 nil,闸门恒放行 | ✅ 2026-10-30 修复(依赖图补 `FacSecurity`) | | 2 | 主体策略 `CheckToolFor` | 完整 | 0 生产调用方 | ✅ 2026-10-30 修复(父为子声明) | | 3 | 插件命名档位 `ActivateProfile` | 完整 | 曾 0 生产调用方 | ✅ 2026-10-31 修(见 §1.1,两次修才修对) | -| 4 | 敏感词 / 注入预警 `ScanContent` | 完整(254 行) | **0 生产调用方** | 🔴 **未修**,见 §1.2 | +| 4 | 敏感词 / 注入预警 `ScanContent` | 完整(254 行) | **0 生产调用方** | ✅ 2026-11-02 修复(见 §1.2) | | 5 | 沙箱 `CheckPath` / `CheckNetwork` | 完整 | **0 生产调用方** | 🔴 **未修**,见 §1.3 | **做任何新能力之前,先问一句:这条链的每一跳,生产里真的有人调吗?** @@ -107,24 +107,68 @@ session 是"这一轮的事实",必须能盖住 long-time 默认值(否则 --- -### 1.2 🔴 敏感词 / 提示词注入预警从未运行 +### 1.2 ✅ 敏感词 / 提示词注入预警已接通(2026-11-02) -**现状**:`internal/security/content.go`(254 行)实现了完整的 -`ContentPolicy{Scan, BlockedBy}`,`Runtime.ScanContent` 也写好了, -但**全仓零生产调用方**(只剩 2 条测试在调)。 +> **本节已结案,保留是因为接通过程中的一次走错本身是教训。** -**影响**: +**原缺陷**:`content.go`(254 行)实现了完整的 `ContentPolicy{Scan, BlockedBy}`, +`Runtime.ScanContent` 也写好了,但**全仓零生产调用方**。配置与插件档位里 +声明的敏感词一条都不生效,注入迹象也不预警 —— 症状与"没配"完全一样。 -- 配置里写的敏感词一条都不生效 -- 模型被提示词注入时内核不预警、不阻断 -- 插件通过 `SecurityProfile.SensitiveWords` 声明的档位敏感词同样不生效 +**接线做了什么**: -**要做的**:在**入向边界**接线。合理位置是 `executeToolCallOutcome` 的 defer -(那里已经有 `security.Global().Replace(...)` 做凭据脱敏,同一个位置、 -同一条 defer 分支),以及插件注入的输入在进 `prepareInputTask` 之前。 +``` +Round.CheckContent(ins, text) ← security 对外的新入口 + → Runtime.ScanContentFor(ins, text, EffectiveProfile()) + → effectiveContentFor(profileName).Scan(...) +``` -**注意**:不要只接一处。入向有两条路——工具结果、插件输入事件。只接一条会 -留下「工具的返回被扫了、插件消息没扫」的缺口,而后者才是注入的主要入口。 +两处入向落点(本节原先就写明"不要只接一处",照做了): + +| 路径 | 位置 | 词表源 | +|---|---|---| +| 插件输入 | `task.go` → `ReviewInputContent(round, …)` | 档位(security 内部解析) | +| 工具结果 | `toolcall.go` 的 defer(与出向凭据脱敏同一位置) | 全局词表 | + +工具侧用全局词表是设计使然:工具执行链没有轮次句柄,硬塞"进程当前档" +才是收敛前的毛病(`ActivateProfile` 全局单例)。 + +**处置**:B 档 —— **标记 + 警示,不阻断**(用户裁定)。敏感词由插件按自己 +通道声明,词表难免偏宽,阻断会误杀正常消息。命中时保留原文、正文前追加 +警示语;警示写进正文而不是只记日志(模型看不到内核日志)。 + +**顺带修出一个真缺陷**:`effectiveContent()` 读的是**进程级 active** 档位, +而 2026-10-31 起档位已迁到 `AgentScope`。工具策略同步改了 +(`checkToolWithProfile` 走 `profilePolicyByName`),**内容审查没改** —— +于是 session 档声明的敏感词永远并不进词表。新增 `effectiveContentFor(profileName)`。 + +**☆ 走错的一次(与 §1.1 同族,值得记)** + +第一版我写的是: + +```go +// ✗ 让 agent 自己解析档位再传进来 +a.security.ScanContentFor(ins, text, a.effectiveSecurityProfile()) +``` + +这正是 §1.1 收敛掉的第 2 层毛病 —— 把「本轮该用哪个档位」这条策略语义 +交回调用方。判据红了两轮(档位在 `BeginRound` 之前是空值),我去读设计文档 +才发现方向错了,改走 `Round.CheckContent` 才对。 + +> 教训:**先读设计再动手**。这次盲试了两轮,而设计文档的接线状态表里 +> 🔴 那一行、以及"要做的"那一段,早就写清了落点和口径。 + +**☆ 判据补出来的第二课** + +最初的 6 条判据都直接调辅助函数 `ReviewInputContent`。做变异时发现: +**把 `task.go` 里的调用删掉,6 条全部仍然绿**。 + +那正是本模块的原始缺陷形态 ——「实现完整、判据绿、生产零调用」。 +所以补了 `TestInputContentReviewWiredIntoProcessing`:走真实入口 +`runInputTask`,断言 payload 被改写。变异后才真的变红。 + +> 教训:**判据必须至少有一条走生产调用点**。测辅助函数证明"函数能用", +> 不证明"生产路径上有人调它"。 ### 1.3 🔴 沙箱约束从未运行 diff --git a/docs/zh/kernel-secret-firewall-design.md b/docs/zh/kernel-secret-firewall-design.md index 157fdf14..f2a31c16 100644 --- a/docs/zh/kernel-secret-firewall-design.md +++ b/docs/zh/kernel-secret-firewall-design.md @@ -10,7 +10,8 @@ > 详见 `internal/security/agentscope.go` 与 `round.go` 的包注释。 > > **状态:部分实现。** 凭据防火墙、配置加密、变量库统一与 C1–C8 判据已落地并**在生产线生效**; -> 但**三条能力机制完整却零生产调用方**(敏感词/注入预警、路径沙箱、网络闸)。 +> 敏感词/注入预警 **2026-11-02 已接通**(B 档:标记+警示); +> 仍**零生产调用方**的是路径沙箱(`CheckPath`)与网络闸(`CheckNetwork`)。 > 本文保留原始设计与逐条审计记录;未实现项统一登记在 > [`future-plan.md`](./future-plan.md) §一。 > @@ -28,7 +29,7 @@ > | 按主体授权 `CheckToolFor` | 完整 | 同上(`checkToolForWithProfile` 同时叠主体策略) | ✅ **2026-10-30 接通** | > | 插件命名档位 `DeclareProfile` | 完整 | `sdk/security_impl.go`、`proc/corehandler_security.go` | ✅ 声明侧通 | > | 插件命名档位 `ActivateProfile` | 完整 | `security/agentscope.go` 的 `setSession` + `BeginRound` | ✅ **2026-10-31 接通**(每 agent 独立实例) | -> | 敏感词/注入 `ScanContent` | 完整(254 行) | **无** | 🔴 配置里的敏感词一条不生效,见 future-plan §1.2 | +> | 敏感词/注入 `Round.CheckContent` → `ScanContentFor` | 完整 | `task.go`(插件输入)、`toolcall.go` defer(工具结果) | ✅ **2026-11-02 接通**(B 档:标记+警示,不阻断) | > | 路径沙箱 `CheckPath` | 完整 | **无**(只被 Runtime 自己调 Policy) | 🔴 见 future-plan §1.3 | > | 网络闸 `CheckNetwork` | 完整 | **无**(同上) | 🔴 见 future-plan §1.3 | > | 事件总线授权 + 载荷过闸 | 完整 | `security/mod.go`(唯一装配点) | ✅ 生效 |