主题
安全架构设计
本文引用的源码文件
本文引用的文件
目录
- 引言
- 项目结构与安全边界总览
- 核心安全组件
- 系统架构与数据流
- 详细组件分析
- 依赖关系与耦合分析
- 性能与资源约束下的安全权衡
- 威胁模型与攻击面评估
- 认证授权、Token 管理与用户权限模型
- Prompt 注入防护、输入验证清洗与输出过滤
- 敏感信息保护、密钥管理与加密存储机制
- 安全审计、日志记录与合规性要求
- 安全更新机制、漏洞修复流程与应急响应预案
- 结论与建议
引言
本安全架构文档面向 AI Helper 的双进程体系:Chrome 扩展端(Manifest V3,版本 2.3.1)与独立本地 Agent 服务(Node.js,版本 2.3.1)。两端通过本地 HTTP/WebSocket 通信,扩展端负责浏览器上下文、页面交互与用户界面;Agent 端负责本地文件读写、命令执行、长期记忆、RAG 知识库、MCP 工具注册与技能系统。
从安全视角看,系统不是“一个程序”,而是由多个信任域组成的边界集合:
- 浏览器扩展 Service Worker 与 Side Panel 运行在扩展上下文中。
- 内容脚本运行在每个页面的隔离世界中。
- Agent 进程以本机 Node 进程身份访问文件系统与操作系统命令。
- 外部 LLM 提供商是受控但不可信的外部服务。
- 第三方 MCP Server 和 Skill 代码可能引入额外执行面。
因此,安全设计必须同时处理跨进程、跨上下文、跨平台路径语义、命令语法变体、提示注入、凭据泄露与可观测性五个维度。
章节来源
项目结构与安全边界总览
下图给出当前仓库中与安全性直接相关的主要模块及其职责划分。
graph TB subgraph "浏览器扩展端" SW["Service Worker<br/>background/index.js"] SP["Side Panel<br/>聊天与设置界面"] CS["Content Script<br/>页面隔离世界"] AC["Agent 客户端<br/>local-agent-client.js"] SEC_LIB["共享安全库<br/>secret.js / i18n / logger"] end subgraph "本地 Agent 进程" HTTP["HTTP + WebSocket 服务器<br/>server.js"] AUTH["配对与 Token 认证<br/>auth.js"] SEC["路径沙箱与命令分级<br/>security.js"] EXEC["命令执行器<br/>executor.js"] LOG["审计日志<br/>logger.js"] MEM["长期记忆与 RAG<br/>memory / rag"] MCP["MCP 工具注册<br/>mcp/registry.js"] SKILL["技能系统<br/>skill/*"] end subgraph "外部系统" MODEL["LLM 提供商 API"] OS["操作系统与 Shell"] FS["本地文件系统"] NET["网络与内网服务"] end CS --> SW SP --> SW SW --> AC AC --> HTTP HTTP --> AUTH HTTP --> SEC HTTP --> EXEC HTTP --> LOG HTTP --> MEM HTTP --> MCP HTTP --> SKILL EXEC --> OS SEC --> FS HTTP --> NET SW --> MODEL SP --> MODEL
图表来源
- src/background/local-agent-client.js#L40-L93
- agent/src/server.js#L1-L56
- agent/src/auth.js#L1-L48
- agent/src/security.js#L1-L10
- agent/src/executor.js#L1-L18
- agent/src/logger.js#L1-L10
章节来源
核心安全组件
本项目的安全能力集中在以下六个核心组件:
| 组件 | 主要职责 | 关键安全控制 |
|---|---|---|
| Agent HTTP 服务器 | 路由、CORS、请求解析、健康检查、重启/更新/关闭 | 仅允许 chrome-extension:// 来源跨域读取;对 /api/shutdown 做回环来源判断;限制请求体大小 |
| 认证模块 | 配对码生成、轮换、一次性使用、Token 校验 | 6 位密码学随机字符、失败锁定、活跃窗口、配对成功后立即轮换 |
| 安全管控模块 | 文件路径白名单、硬阻止目录、符号链接检测、命令黑白灰名单 | realpath 复检、工作目录放行、Agent 系统文件硬阻止、链式命令拆分与解释器载荷提取 |
| 命令执行器 | 子进程创建、流式输出、超时与终止、环境变量白名单 | 安全环境变量裁剪、输出缓冲上限、进程树递归终止、受管模式预算 |
| 审计日志模块 | JSON Lines 日志、按日归档、自动清理、查询接口 | 分类标签、单文件大小限制、保留数量限制、写入失败不阻塞主流程 |
| 不可信内容包装 | 工具结果包装、动态合约注入、注入短语拦截 | fail-closed 白名单、伪造标签剥离、记忆写入来源分级 |
章节来源
- agent/src/server.js#L235-L266
- agent/src/auth.js#L30-L48
- agent/src/security.js#L62-L229
- agent/src/executor.js#L118-L156
- agent/src/logger.js#L1-L10
- agent/src/memory/service.js#L71-L93
系统架构与数据流
下图展示一次典型“用户发起 → 扩展调度 → Agent 执行 → 结果返回”的安全数据流。
sequenceDiagram participant User as "用户" participant SP as "侧边栏" participant SW as "扩展后台" participant AC as "Agent 客户端" participant S as "Agent 服务器" participant A as "认证模块" participant SC as "安全管控" participant EX as "命令执行器" participant OS as "操作系统" User->>SP : 输入任务或选择工具 SP->>SW : 触发工具调用 SW->>AC : 构造带 Bearer Token 的请求 AC->>S : HTTP/WebSocket 请求 S->>A : 校验 Authorization A-->>S : 返回扩展 ID 或拒绝 S->>SC : 路径/命令安全检查 SC-->>S : allow / confirm / deny S->>EX : 执行命令或文件操作 EX->>OS : spawn shell / 文件系统 OS-->>EX : 输出/退出码 EX-->>S : 流式输出或最终结果 S-->>AC : 结构化响应 AC-->>SW : 附加 httpStatus 的结果 SW-->>SP : 渲染结果或确认弹窗
图表来源
- src/background/local-agent-client.js#L393-L443
- agent/src/server.js#L417-L548
- agent/src/security.js#L685-L758
- agent/src/executor.js#L198-L275
章节来源
详细组件分析
Agent HTTP 服务器安全入口
Agent 服务器是所有本地能力的统一入口。它承担以下安全职责:
- 只允许来自
chrome-extension://的来源跨域读取响应,防止恶意网页直接读取无认证接口。 - 对
/api/pair、/api/status等无需认证的接口进行最小化信息暴露。 - 对
/api/shutdown区分本机来源与远程来源:远程来源必须携带有效 Bearer Token。 - 对所有需认证接口统一校验
Authorization: Bearer <token>。 - 限制 JSON body 与 multipart 上传大小,避免内存耗尽。
- 将请求语言同步到各子模块,保证错误消息、安全提示、日志分类具备国际化一致性。
flowchart TD
Start(["收到 HTTP 请求"]) --> ParseURL["解析 URL 与路径"]
ParseURL --> CORS{"是否 OPTIONS 预检"}
CORS --> |是| AllowOrigin["仅反射 chrome-extension:// 来源"]
AllowOrigin --> End(["结束"])
CORS --> |否| PairCheck{"是否 /api/pair"}
PairCheck --> |是| PairFlow["处理配对请求并记录日志"]
PairFlow --> End
PairCheck --> |否| StatusCheck{"是否 /api/status"}
StatusCheck --> |是| StatusReturn["返回平台信息,不泄露主机名/Shell/家目录"]
StatusReturn --> End
StatusCheck --> |否| ShutdownCheck{"是否 /api/shutdown"}
ShutdownCheck --> |是| LocalCheck{"是否本机来源"}
LocalCheck --> |否| AuthRequired["需要 Bearer Token"]
LocalCheck --> |是| ShutdownProceed["进入冷却期与防重入检查"]
AuthRequired --> VerifyToken["verifyToken(token)"]
VerifyToken --> Valid{"是否有效"}
Valid --> |否| Deny["返回 401/403"]
Valid --> |是| ShutdownProceed
ShutdownProceed --> End
ShutdownCheck --> |否| AuthGate["通用认证门"]
AuthGate --> Heartbeat{"是否心跳"}
Heartbeat --> |是| HeartbeatReturn["刷新 lastAuthTime"]
Heartbeat --> |否| UpdateRestart{"是否更新/重启"}
UpdateRestart --> End
图表来源
章节来源
路径沙箱与命令分级
路径沙箱与命令分级是 Agent 端最重要的两道本地执行防线。
路径沙箱
路径检查遵循以下顺序:
- 空值或非字符串直接拒绝。
- 展开
~到用户主目录。 - 规范化路径格式,兼容 Windows 盘符、MSYS/Git Bash 风格路径。
- 绝对路径基于自身解析,相对路径基于 workdir 解析。
- 硬阻止检查:Agent 配置、配对记录、日志、回收站、内置技能状态等不可绕过。
- 记忆存储目录与工作目录特殊放行。
- 白名单前缀匹配。
realpath解析真实物理路径,再次检查硬阻止和白名单,防止符号链接绕过。
flowchart TD
Input["输入路径"] --> Normalize["规范化路径格式"]
Normalize --> Resolve["解析为绝对路径"]
Resolve --> HardBlock{"是否命中硬阻止目录"}
HardBlock --> |是| DenyPath["拒绝:禁止访问代理系统文件"]
HardBlock --> |否| MemoryWorkDir{"是否记忆目录或工作目录"}
MemoryWorkDir --> |是| RealpathCheck["realpath 复检"]
RealpathCheck --> AllowedPath["允许"]
MemoryWorkDir --> |否| WhitelistPrefix{"是否在 allowedPaths 前缀下"}
WhitelistPrefix --> |否| DenyOut["拒绝:路径不在允许目录"]
WhitelistPrefix --> |是| RealpathCheck
RealpathCheck --> FinalAllowed["允许"]
图表来源
命令分级
命令检查分为三类:
- 黑名单:绝对禁止,即使
force=true也不放行。包括破坏性删除、格式化磁盘、覆盖系统文件、Fork Bomb、管道执行 shell、修改根目录权限等。 - 灰名单:需要用户确认。包括
sudo、全局安装、递归删除、权限变更、网络外联、进程终止、系统服务、脚本执行等。 - 白名单:普通命令直接放行。
命令扫描不仅检查整串,还会:
- 拆分链式命令。
- 剥开
sudo/doas/nohup/env等包装器。 - 归一化
/./usr、//dev等路径变形。 - 提取
-c/-e、/c /k、-Command/-EncodedCommand等解释器内联载荷。 - 提取
$()与反引号中的子命令。 - 对命令替换场景做只读头命令豁免,避免误杀
echo $(date)。
flowchart TD
Cmd["原始命令"] --> Scopes["收集所有子命令范围"]
Scopes --> Blacklist{"是否命中黑名单"}
Blacklist --> |是| DenyCmd["deny:绝对禁止"]
Blacklist --> |否| ForceCheck{"是否 force 模式"}
ForceCheck --> |是| AllowCmd["allow:跳过灰名单"]
ForceCheck --> |否| Graylist{"是否命中灰名单"}
Graylist --> |是| ConfirmCmd["confirm:需要用户确认"]
Graylist --> |否| SafeCmd["allow:普通命令"]
图表来源
章节来源
命令执行器与进程生命周期
命令执行器负责把安全网关通过的命令交给操作系统执行,同时控制资源消耗与进程生命周期。
关键点:
- 根据平台与环境选择可用 shell,避免 Git Bash MSYS 路径在 Windows 上直接 spawn 失败。
- 环境变量采用白名单裁剪,避免泄露宿主敏感变量。
- stdout/stderr 有 5MB 缓冲上限,超限后截断并广播通知。
- 支持两种超时策略:旧模式到期即杀;受管模式根据是否有输出决定延长或终止。
- 支持流式 WebSocket 输出、延迟连接回放、断开后自由运行(显式 detach)。
- 跨平台终止进程树:Unix 用负 PID 杀进程组,Windows 用
taskkill /T /PID。
stateDiagram-v2 [*] --> 已创建 已创建 --> 运行中 : "spawn shell" 运行中 --> 有输出 : "stdout/stderr" 有输出 --> 运行中 : "继续执行" 运行中 --> 已终止 : "完成/错误" 运行中 --> 被杀死 : "超时/手动停止" 已终止 --> 已完成缓存 : "缓存输出" 被杀死 --> 已完成缓存 : "缓存输出" 已完成缓存 --> [*] : "TTL 清理"
图表来源
章节来源
- agent/src/executor.js#L32-L91
- agent/src/executor.js#L118-L156
- agent/src/executor.js#L198-L275
- agent/src/executor.js#L495-L549
扩展端 Agent 客户端
扩展端的 local-agent-client.js 封装了与 Agent 的所有 HTTP 与 WebSocket 通信,并负责:
- 多代理管理:保存多个 Agent 实例,切换活跃代理。
- Token 解密:从存储中读取时解密 token。
- 可达性缓存:避免频繁探测离线 Agent。
- 统一认证请求:所有需认证请求附带
Authorization: Bearer。 - 超时控制:AbortController 控制 fetch 与 WebSocket 空闲超时。
- 文件上传:multipart/form-data 与流式上传。
- 命令执行:异步启动、等待结果、停止、detach。
classDiagram
class AgentClient {
+getAgentConfig()
+pairWithAgent(agentUrl, pairCode)
+unpairAgent(agentId)
+agentRequest(path, body, method, timeoutMs)
+agentGet(path, timeoutMs)
+uploadFile(file)
+execCommand(command, cwd, force, timeoutMs)
+createExecWebSocket(wsUrl, onMessage, onClose, onError)
}
class Storage {
+pairedAgents
+activeAgentId
+decodeSecret(token)
}
class Logger {
+debug(message)
+warn(message)
+error(message)
}
AgentClient --> Storage : "读取/写入代理配置"
AgentClient --> Logger : "记录连接状态"
图表来源
- src/background/local-agent-client.js#L146-L232
- src/background/local-agent-client.js#L275-L330
- src/background/local-agent-client.js#L393-L443
- src/background/local-agent-client.js#L662-L728
章节来源
- src/background/local-agent-client.js#L146-L232
- src/background/local-agent-client.js#L275-L330
- src/background/local-agent-client.js#L393-L443
- src/background/local-agent-client.js#L662-L728
依赖关系与耦合分析
Agent 服务器的依赖关系体现了“入口集中、能力解耦”的设计:
graph LR Server["server.js"] --> Auth["auth.js"] Server --> Security["security.js"] Server --> Executor["executor.js"] Server --> Logger["logger.js"] Server --> Config["config.js"] Server --> Search["search.js"] Server --> RAGDetect["rag/detect.js"] Server --> MemoryRoutes["memory/routes.js"] Server --> MCPRegistry["mcp/registry.js"] Server --> SkillRegistry["skill/registry.js"] Server --> ProcessTree["process-tree.js"]
图表来源
耦合特点:
- server.js 是协调者,不直接实现业务逻辑,而是委托给 auth、security、executor、logger 等模块。
- security.js 与 executor.js 是强安全依赖:任何命令执行前都应经过 checkCommand。
- logger.js 是横切关注点,几乎所有安全事件都会写日志。
- memory、rag、mcp、skill 是可选能力,不影响基础文件与命令通道。
章节来源
性能与资源约束下的安全权衡
安全控制不能无限严格,否则会影响可用性。当前实现中存在若干明确权衡:
| 控制点 | 安全目标 | 性能/可用性代价 | 当前处理方式 |
|---|---|---|---|
| 命令黑名单 | 防止系统破坏 | 可能误伤复杂脚本 | 逐段扫描 + 包装器剥壳 + 解释器载荷提取 |
| 命令灰名单 | 用户确认高危操作 | 增加交互摩擦 | 提供“本次任务放行”降低频次 |
| 路径 realpath 复检 | 防止符号链接绕过 | 额外 I/O | 仅在必要时解析真实路径 |
| 输出缓冲上限 | 防止长命令撑爆内存 | 大输出被截断 | 广播 truncation 通知 |
| 超时策略 | 防止挂起命令常驻 | 长任务可能被杀 | 受管模式按输出延长,detach 豁免 |
| 日志清理 | 防止磁盘占满 | 历史日志丢失 | 最多 30 天,单文件超 10MB 清理 |
| 内容脚本注入瘦身 | 减少每页加载体积 | 功能按需加载更复杂 | 构建阶段以 manifest 声明为准 |
章节来源
- agent/src/security.js#L653-L758
- agent/src/executor.js#L96-L114
- agent/src/executor.js#L165-L186
- agent/src/logger.js#L8-L10
威胁模型与攻击面评估
安全边界图
graph TB Web["恶意网页"] --> Browser["浏览器"] Browser --> ContentScript["内容脚本"] Browser --> Extension["扩展上下文"] Extension --> Background["Service Worker"] Background --> AgentClient["Agent 客户端"] AgentClient --> AgentServer["Agent 服务器"] AgentServer --> FileSystem["本地文件系统"] AgentServer --> Shell["Shell 命令"] AgentServer --> Network["网络请求"] Background --> ModelAPI["LLM 提供商"] AgentServer --> MCP["第三方 MCP Server"]
主要攻击面
| 攻击面 | 威胁描述 | 现有防护 | 剩余风险 |
|---|---|---|---|
| 本地命令执行 | 模型通过 agent_exec 执行任意 shell 命令 | 黑名单/灰名单/用户确认/环境变量白名单 | 静态正则无法覆盖所有间接执行;审计日志曾指出确认链路存在历史缺口 |
| 路径穿越 | 通过 ..、符号链接、~、不同平台路径写法绕过白名单 | 规范化、workdir 优先、realpath 复检、硬阻止列表 | 若新增未走 checkPath 的文件接口,仍可能越界 |
| SSRF | 通过 fetch_url 访问内网、元数据服务、回环地址 | 扩展侧 network-scope 闸门、scheme 限制、内网白名单 | 历史审计指出 manage_tab open 曾存在残余可达面 |
| XSS | 内容脚本渲染宿主页面 DOM | 侧边栏使用 DOMPurify;SEC-10 CSS 注入做了简单白名单过滤 | 内容脚本 Markdown 渲染曾被审计标记为高风险 |
| 提示注入 | 外部数据伪装成系统指令 | 不可信内容包装、动态合约、记忆写入注入短语拦截 | 模型行为仍依赖 prompt 工程与系统提示质量 |
| 凭据泄露 | API Key、Token、Cookie、请求头落入模型上下文 | 配对码轮换、Token 混淆存储、部分日志脱敏 | 历史审计指出 debug_page 抓包有意暴露 header |
| 本地 DoS | 恶意网页关停 Agent | 回环来源判断、冷却期、防重入 | 审计指出 /api/shutdown 回环免认证模式需谨慎 |
章节来源
- docs/AUDIT_REPORT.md#L12-L37
- docs/AUDIT_REPORT.md#L174-L189
- docs/AUDIT_REPORT.md#L190-L220
- docs/AUDIT_REPORT.md#L279-L317
认证授权、Token 管理与用户权限模型
配对与认证流程
Agent 的认证不是传统用户名密码,而是“配对码 + Token”的两阶段机制:
sequenceDiagram
participant Ext as "扩展"
participant Agent as "Agent 服务器"
participant Auth as "认证模块"
participant Store as "配对记录存储"
Ext->>Agent : POST /api/pair {code, extensionId}
Agent->>Auth : handlePairRequest(code, extensionId)
Auth->>Auth : 检查失败锁定
Auth->>Auth : 比对 currentPairCode
Auth->>Store : 检查是否已配对
alt 已配对
Auth-->>Agent : 返回已有 token
else 首次配对
Auth->>Store : 保存 extensionId + randomBytes(32) token
Auth-->>Agent : 返回新 token
end
Agent-->>Ext : 返回 token
Ext->>Agent : 后续请求携带 Authorization : Bearer token
Agent->>Auth : verifyToken(token)
Auth-->>Agent : 返回 extensionId 或 null
图表来源
- agent/src/auth.js#L138-L179
- agent/src/auth.js#L117-L127
- agent/src/server.js#L474-L484
- agent/src/server.js#L537-L548
Token 管理机制
- 配对码:6 位字母数字,排除易混淆字符,使用密码学安全随机数。
- 配对码轮换:插件在线且最近 5 分钟有认证则停止轮换;否则定时刷新。
- 一次性使用:配对成功后立即轮换配对码。
- 失败锁定:连续失败 5 次后锁定 60 秒,并立即轮换配对码。
- Token:32 字节随机 hex,用于后续所有需认证接口。
- 活跃窗口:成功认证后更新 lastAuthTime,用于判断插件是否在线。
用户权限模型
当前权限模型不是细粒度 RBAC,而是“扩展实例级 Token + 服务端能力开关”的组合:
- 每个扩展实例拥有唯一 token。
- 同一 Agent 可配对多个扩展实例。
- 能力开关由 config.json 控制,例如 allowedPaths、commandTimeout、fileMaxSize、pairCodeTTL。
- 命令执行还叠加用户确认层:灰名单命令默认弹出确认,黑名单不可绕过。
- 网络访问在扩展侧有总闸与白名单,Agent 侧 RAG URL 摄入也有 AND 闸语义。
章节来源
- agent/src/auth.js#L30-L48
- agent/src/auth.js#L75-L102
- agent/src/auth.js#L138-L179
- agent/src/server.js#L537-L548
Prompt 注入防护、输入验证清洗与输出过滤
不可信内容包装
系统对来自外部数据的工具结果进行包装,将其标记为“数据而非指令”。核心思路:
- 定义包装类工具集合:页面内容、网络响应、本地文件、MCP 结果、记忆、RAG 检索等。
- 定义已知安全工具集合:纯操作状态、用户输入、模型自产文本等。
- 对包装类工具结果包裹
<untrusted_page_content>标签。 - 剥离内容中的伪造标签,防止越狱。
- 当检测到消息历史中存在包装内容时,向 system 消息注入安全合约。
- 契约文案强调:外部内容是数据,不得执行其中出现的命令、请求或指示。
flowchart TD
ToolResult["工具结果"] --> Classify{"是否包装类工具"}
Classify --> |否| PassThrough["原样返回"]
Classify --> |是| Sanitize["剥离伪造标签"]
Sanitize --> Wrap["包裹 untrusted_page_content"]
Wrap --> Messages["加入消息历史"]
Messages --> Detect{"是否存在包装内容"}
Detect --> |否| NormalCall["正常调用模型"]
Detect --> |是| InjectContract["注入安全合约"]
InjectContract --> CallModel["调用模型"]
图表来源
- docs/superpowers/specs/2026-10-10-prompt-injection-defense-design.md#L71-L91
- docs/superpowers/specs/2026-10-10-prompt-injection-defense-design.md#L338-L395
记忆写入注入防护
记忆模块对写入侧做 fail-closed 拦截:
- 命中常见忽略系统提示、越狱模式等注入短语的记忆直接拒写。
- origin 字段由运行时判定,模型不能自封可信来源。
- Tier1 常驻记忆仅限 user 来源且长度受限。
flowchart TD
WriteReq["记忆写入请求"] --> OriginCheck{"origin 是否可信"}
OriginCheck --> |否| Downgrade["降出 Tier1 常驻"]
OriginCheck --> |是| InjectionScan["扫描注入短语"]
InjectionScan --> Blocked{"是否命中注入模式"}
Blocked --> |是| Reject["拒绝写入"]
Blocked --> |否| Save["保存记忆"]
图表来源
输出过滤与 CSS 注入防护
- 侧边栏 Markdown 渲染使用 DOMPurify。
- 内容脚本 Markdown 渲染曾被审计标记为高风险,当前决策暂缓引入 DOMPurify,属于架构权衡。
- CSS 注入做了简单白名单过滤,剔除
@import、url()、expression()、element()、-moz-binding、behavior等危险构造。
章节来源
- docs/superpowers/specs/2026-10-10-prompt-injection-defense-design.md#L338-L395
- agent/src/memory/service.js#L71-L93
- src/content/advanced-tools.js#L357-L371
- docs/AUDIT_REPORT.md#L76-L139
敏感信息保护、密钥管理与加密存储机制
当前机制
- 扩展端存储的 Agent Token 使用 Base64 +
enc:前缀混淆。 - Agent 端配对记录中的 token 明文落盘,注释说明该文件未设置 0600 权限。
- WebSocket 认证 token 通过 URL query 传递,因为浏览器
new WebSocket()无法设置握手 header。 - 扩展端 API Key、视觉 API Key 存储在
chrome.storage.local,属于扩展模型固有约束。
flowchart TD Secret["敏感信息"] --> Encode["encodeSecret(enc: + base64)"] Encode --> Storage["chrome.storage.local"] Storage --> Decode["decodeSecret"] Decode --> Runtime["运行时使用明文"]
图表来源
风险评估
- Base64 混淆不是加密:能读取磁盘或 storage 的攻击者可轻易还原。
- WS token 在 URL 中可能进入代理日志、Referer、浏览器历史记录。
- 配对文件权限未设置为仅当前用户可读。
- 配置导出包含密钥字段,存在二次泄露风险。
建议
- 若威胁模型包含本地磁盘读取,应引入操作系统级密钥保护(如 macOS Keychain、Windows Credential Manager),但这会显著增加部署复杂度。
- WS 握手改用首帧鉴权可减少 URL 暴露面,但需要协议变更。
- 导出配置时对密钥做更强提示与二次确认。
章节来源
- src/shared/secret.js#L1-L31
- src/background/local-agent-client.js#L662-L693
- docs/AUDIT_REPORT.md#L304-L317
- docs/AUDIT_STATUS.md#L40-L41
安全审计、日志记录与合规性要求
审计日志结构
Agent 端日志采用 JSON Lines 格式,按日归档,分类包括:
- auth:认证相关
- fs:文件操作
- exec:命令执行
- security:安全拦截
- system:系统事件
每条日志包含时间戳、级别、分类、动作与详情。日志写入失败不会阻塞主流程。
flowchart TD
Event["安全事件"] --> Category{"分类"}
Category --> AuthLog["logAuth"]
Category --> FsLog["logFs"]
Category --> ExecLog["logExec"]
Category --> SecLog["logSecurity"]
Category --> SysLog["logSystem"]
AuthLog --> File["写入 agent-YYYY-MM-DD.log"]
FsLog --> File
ExecLog --> File
SecLog --> File
SysLog --> File
File --> Cleanup["定期清理旧日志"]
图表来源
合规性与可观测性
- 日志保留 30 天,单文件超过 10MB 自动清理。
- 可通过 API 查询日志,支持按日期、分类、偏移、限制分页。
- 前端可显示审计日志,但需注意 HTML 转义,历史审计已修复该问题。
- 扩展端活动统计与审计写操作已改为内存聚合 + 防抖落盘,避免并发写丢更新。
章节来源
- agent/src/logger.js#L1-L10
- agent/src/logger.js#L91-L123
- agent/src/logger.js#L174-L230
- docs/AUDIT_STATUS.md#L45
安全更新机制、漏洞修复流程与应急响应预案
安全更新机制
Agent 提供 /api/agent/update 接口,允许扩展端触发 npm 全局更新:
- 校验操作进行中与冷却期。
- 与 RAG 依赖安装互斥,避免 node_modules 互相破坏。
- 执行
npm install -g ai-helper-agent@latest,超时 90 秒。 - 更新失败不重启,保持老进程运行。
- 更新成功通过两阶段重启包装器拉起新版本。
flowchart TD
Start["收到更新请求"] --> Guard["防重入 + 冷却期 + RAG 安装互斥"]
Guard --> NPM["执行 npm install -g ai-helper-agent@latest"]
NPM --> Success{"是否成功"}
Success --> |否| Fail["返回失败,不重启"]
Success --> |是| SpawnHelper["spawn 两阶段重启包装器"]
SpawnHelper --> Shutdown["关闭当前进程"]
Shutdown --> NewProcess["新进程接管端口"]
图表来源
漏洞修复流程
根据审计报告与复核状态,本项目已形成较完整的修复闭环:
- 审计发现安全问题。
- 分类为严重/高/中/低。
- 区分“已修复”“成立值得排期”“等级下调”“产品策略决策”。
- 补充守卫测试与负向对照。
- 全量回归 + 构建验证。
- 真机冒烟或探针验证。
应急响应预案
针对高危场景,建议建立如下预案:
- 命令执行异常:立即停止运行进程,查看 exec 日志,检查黑名单是否遗漏。
- 路径越界:检查 workdir 与 allowedPaths,确认是否新增未走 checkPath 的接口。
- 提示注入:检查不可信内容包装是否生效,system 合约是否注入。
- 凭据泄露:轮换 API Key、Agent Token,检查日志是否打印敏感头。
- Agent 被关停:检查
/api/shutdown来源,评估是否需要收回回环免认证。
章节来源
结论与建议
AI Helper 的安全架构在双进程模型下实现了较为完整的多层防护:扩展端负责浏览器上下文与用户交互,Agent 端负责本地执行与数据能力,并通过认证、路径沙箱、命令分级、不可信内容包装、审计日志等手段形成纵深防御。
但仍存在若干需要持续关注的方向:
- 命令确认链路必须始终由用户交互驱动,不应接受模型传入的
force作为绕过依据。 - 内容脚本渲染与 XSS 防护仍需补齐,当前审计结论表明内容脚本 Markdown 渲染缺少消毒。
- SSRF 与内网访问应坚持 AND 闸语义,总闸关闭时即使白名单非空也应拒绝。
- 敏感信息存储应评估是否升级为操作系统级密钥保护,至少对配对文件设置严格权限。
- 调试能力与隐私保护需要明确产品边界,debug_page 抓包暴露 header 是有意取舍,但应提供显式开关。
- 安全更新与漏洞修复应配套自动化守卫测试,确保黑名单、路径沙箱、注入防护不因新增功能退化。
整体而言,该系统的安全基线优于许多同类项目,但“让 AI 操作本地文件和终端”的能力本身具有高风险。未来演进应以“最小权限、最大可见、强制确认、可审计”为核心原则,而不是单纯堆叠规则。