Skip to content

认证与安全 ​

本文引用的源码文件

本文引用的文件

更新摘要 ​

变更内容

  • 修复了侧边栏图片API密钥处理的安全漏洞,确保加密凭证被正确解密为明文密钥
  • 在side_panel/index.js中添加了统一的decodeSecret()解密逻辑,用于处理incoming key changes
  • 完善了图片识别API密钥在整个应用生命周期中的数据完整性保护
  • 更新了相关流程图和故障排查指南以反映新的安全机制

目录 ​

  1. 引言
  2. 项目结构
  3. 核心组件
  4. 架构总览
  5. 详细组件分析
  6. 依赖关系分析
  7. 性能与可扩展性
  8. 故障排查指南
  9. 结论
  10. 附录:安全配置清单

引言 ​

本文件面向"认证与安全"子系统,覆盖以下目标:

  • Token 验证机制:配对码流程、临时会话建立、设备绑定与令牌校验。
  • 权限控制系统:路径沙箱、命令分级管控、黑名单/灰名单策略与强制模式。
  • 审计与统计:Token 使用记录、全局与会话级汇总、按模型与调用类型聚合。
  • 加密工具函数:密钥/Token 落盘混淆(Base64 + 前缀标记)、兼容旧明文。
  • 安全配置建议:TLS、CORS、速率限制与安全头(本节为通用实践建议,不直接分析具体源码)。

本项目采用双进程架构:Chrome 扩展端(Manifest V3)与独立本地代理端 Agent(Node.js)。两端通过 HTTP/WebSocket 通信;Agent 侧负责配对认证、路径与命令安全控制、以及持久化统计。

重要安全更新:最近修复了侧边栏图片API密钥处理的安全漏洞,确保所有模块在处理图片识别API密钥时都正确解密存储的加密密钥,防止将密文发送给视觉模型API导致鉴权失败。

项目结构 ​

与安全相关的关键代码分布如下:

  • 代理端认证模块:agent/src/auth.js
  • 代理端安全网关:agent/src/security.js
  • 代理端 HTTP 入口与路由集成:agent/src/server.js
  • 共享密钥混淆(扩展端):src/shared/secret.js
  • 代理端密钥混淆(Node 端):agent/src/crypto-lite.js
  • 扩展端 Token 统计存储:src/storage/token-store.js
  • 扩展端 Token 统计采集:src/background/token-recorder.js
  • 配置管理(含令牌解码):src/options/config-manager.js
  • 工具箱共享状态(含令牌解码):src/options/toolbox-shared.js
  • 工作区管理器(含令牌解码):src/side_panel/workspace-manager.js
  • 新增:侧边栏图片API密钥处理:src/side_panel/index.js, src/side_panel/chat-manager.js
  • 新增:背景脚本图片API密钥传递:src/background/index.js, src/background/react-loop.js
graph TB
subgraph "扩展端"
BR["background/token-recorder.js"]
TS["storage/token-store.js"]
SS["shared/secret.js"]
CM["options/config-manager.js"]
TB["options/toolbox-shared.js"]
WM["side_panel/workspace-manager.js"]
SP["side_panel/index.js"]
SCM["side_panel/chat-manager.js"]
BG["background/index.js"]
RL["background/react-loop.js"]
end
subgraph "代理端"
SRV["server.js"]
AUTH["auth.js"]
SEC["security.js"]
CL["crypto-lite.js"]
end
BR --> TS
SRV --> AUTH
SRV --> SEC
SRV --> CL
TS -.-> BR
CM --> SS
TB --> SS
WM --> SS
SP --> SS
SCM --> SP
BG --> RL

图示来源

章节来源

核心组件 ​

  • 配对认证模块(auth.js)
    • 生成并轮换配对码,支持一次性使用与失败锁定。
    • 维护最近一次成功认证时间,用于判断扩展是否在线。
    • 提供 verifyToken 基于持久化配对表进行令牌校验。
  • 安全网关(security.js)
    • 路径沙箱:白名单目录、工作目录放行、硬阻止敏感文件/目录。
    • 命令分级:黑名单绝对禁止、灰名单需确认、force 可跳过灰名单。
    • 链式命令拆分、解释器内联载荷解析、命令替换检测。
  • 密钥混淆(crypto-lite.js / secret.js)
    • Base64 + enc: 前缀标记,兼容旧明文,非密码学安全但防一眼可见。
  • Token 统计(token-store.js / token-recorder.js)
    • 记录每次 API 调用的 prompt/completion/total tokens 与上下文窗口占比。
    • 提供会话级、全局、按天、按模型、按调用类型的聚合查询。
  • 统一令牌解码机制(新增)
    • 在所有需要发送请求的模块中统一使用 decodeSecret 函数。
    • 确保存储的加密令牌在发送前转换为明文,避免鉴权失败。
  • 图片API密钥安全处理(新增)
    • 在侧边栏初始化时解密imageApiKey并存储在state中。
    • 监听storage变化时对新值进行解密处理。
    • 通过消息传递将明文密钥传递给background脚本进行处理。

章节来源

架构总览 ​

扩展端通过 background 脚本在 API 调用完成后收集 usage 信息,写入 IndexedDB;代理端 server.js 在请求入口处加载 auth 与 security 能力,完成配对、鉴权与命令/路径安全检查。

重要更新:现在所有扩展端模块在发送请求前都会使用 decodeSecret 对存储的令牌进行解码,确保 Authorization 头部携带的是明文令牌而非加密字符串。同时,图片API密钥的处理也遵循相同的安全模式。

sequenceDiagram
participant Ext as "扩展端"
participant BG as "background/token-recorder.js"
participant DB as "storage/token-store.js"
participant Srv as "agent/server.js"
participant Auth as "agent/auth.js"
participant Sec as "agent/security.js"
participant Secret as "shared/secret.js"
Note over Ext,Secret : 令牌解码流程
Ext->>Secret : "decodeSecret(encrypted_token)"
Secret-->>Ext : "plain_token"
Ext->>Srv : "HTTP 请求携带 Authorization : Bearer <plain_token>"
Srv->>Auth : "verifyToken(token)"
Auth-->>Srv : "extId 或 null"
alt 未认证
Srv-->>Ext : "401 未认证"
else 已认证
Srv->>Sec : "checkPath()/checkCommand()"
Sec-->>Srv : "允许/拒绝/需确认"
Srv-->>Ext : "业务响应"
end
Ext->>BG : "API 调用完成"
BG->>DB : "recordTokenCall(...)"
DB-->>BG : "写入结果"
Note over Ext,Secret : 图片API密钥处理流程
Ext->>Secret : "decodeSecret(imageApiKey)"
Secret-->>Ext : "plaintext_api_key"
Ext->>BG : "传递明文API密钥"
BG->>Srv : "视觉模型API调用"

图示来源

详细组件分析 ​

配对码与令牌认证流程 ​

  • 配对码生成
    • 使用密码学安全的随机数生成 6 位字符(排除易混淆字符),初始启动即生成并在 TTL 周期内轮换。
    • 若检测到已有配对且最近有活跃认证(默认 5 分钟窗口),则停止轮换;否则持续轮换以允许新设备配对。
  • 配对请求处理
    • 连续失败达到阈值后进入短时锁定,并立即轮换配对码使已观测码失效。
    • 配对成功后立即轮换配对码,防止重复利用;同时保存扩展 ID 与随机生成的 token。
  • 令牌校验
    • verifyToken 遍历持久化配对表匹配 token,命中则更新 lastAuthTime 并返回 extId。
flowchart TD
Start(["开始"]) --> Gen["生成配对码<br/>startPairCodeRotation()"]
Gen --> Rotate{"是否活跃连接?"}
Rotate --> |是| StopRot["停止轮换"]
Rotate --> |否| NextRot["定时轮换配对码"]
NextRot --> PairReq["handlePairRequest(code, extensionId)"]
PairReq --> CheckLock{"是否在锁定窗口?"}
CheckLock --> |是| Deny["拒绝:过于频繁"]
CheckFail["配对码错误计数+1"] --> LockCheck{"达到失败阈值?"}
LockCheck --> |是| ForceRotate["立即轮换配对码并锁定"]
LockCheck --> |否| ReturnInvalid["返回无效配对码"]
ForceRotate --> ReturnInvalid
CheckLock --> |否| CheckCode{"配对码正确?"}
CheckCode --> |否| CheckFail
CheckCode --> |是| CheckPaired{"是否已配对?"}
CheckPaired --> |是| Rotated["轮换配对码并返回已有token"]
CheckPaired --> |否| SavePairing["保存扩展ID与token"]
SavePairing --> Rotated
Rotated --> End(["结束"])

图示来源

章节来源

令牌在服务端的集成与解码流程 ​

  • server.js 在请求入口处从 Authorization 头部提取 Bearer token,调用 verifyToken 获取 extId。
  • 对需要认证的接口,若 verifyToken 返回空则拒绝访问。
  • 配对接口 handlePairRequest 由 server.js 路由调用,并传入翻译函数 t。

重要更新:现在所有扩展端模块在发送请求前都会使用 decodeSecret 对存储的令牌进行解码:

sequenceDiagram
participant Client as "客户端"
participant ConfigMgr as "config-manager.js"
participant Toolbox as "toolbox-shared.js"
participant Workspace as "workspace-manager.js"
participant Secret as "shared/secret.js"
participant Server as "server.js"
participant Auth as "auth.js"
Note over Client,Secret : 统一的令牌解码流程
Client->>ConfigMgr : "getAgentConnection()"
ConfigMgr->>Secret : "decodeSecret(stored_token)"
Secret-->>ConfigMgr : "plain_token"
Client->>Toolbox : "agentApi(method, path, body)"
Toolbox->>Secret : "decodeSecret(stored_token)"
Secret-->>Toolbox : "plain_token"
Client->>Workspace : "getAgentConfig()"
Workspace->>Secret : "decodeSecret(stored_token)"
Secret-->>Workspace : "plain_token"
Client->>Server : "POST /pair (code, extensionId)"
Server->>Auth : "handlePairRequest(code, extensionId, t)"
Auth-->>Server : "{success, token?, message?}"
Server-->>Client : "配对结果"
Client->>Server : "GET /api/... (Authorization : Bearer <plain_token>)"
Server->>Auth : "verifyToken(token)"
Auth-->>Server : "extId 或 null"
Server-->>Client : "业务响应或401"

图示来源

章节来源

路径沙箱与命令分级管控 ​

  • 路径沙箱
    • 硬阻止:代理配置文件、配对记录、日志、回收站等核心敏感文件/目录不可访问。
    • 系统目录白名单:记忆存储目录可读写。
    • 工作目录永远放行,但 realpath 仍会检查硬阻止,防止符号链接绕过。
    • allowedPaths 白名单前缀匹配,并对 realPath 再次校验。
  • 命令分级
    • 黑名单:绝对禁止(如 rm -rf /、格式化磁盘、fork bomb、恶意管道执行等)。
    • 灰名单:需用户确认(sudo、pip install、chmod 777、网络外联、kill、systemctl 等)。
    • force 模式:跳过灰名单,但仍受黑名单约束。
    • 链式命令拆分、包装器剥壳(sudo/doas/env/nohup 等)、解释器内联载荷(-c/-e、cmd /c /k、PowerShell -Command/-EncodedCommand)、命令替换 $(...) 与反引号检测。
flowchart TD
A["输入命令"] --> B["collectCommandScopes()<br/>原始串 + 拆分段 + 内联载荷 + 替换子段"]
B --> C{"黑名单命中?"}
C --> |是| D["deny不可绕过"]
C --> |否| E{"force 模式?"}
E --> |是| F["allow跳过灰名单"]
E --> |否| G{"灰名单命中?"}
G --> |是| H["confirm需用户确认"]
G --> |否| I["allow"]

图示来源

章节来源

Token 使用统计与审计 ​

  • 采集层:background/token-recorder.js 在 API 调用完成后读取 usage,计算 contextWindow,调用 storage/token-store.js 写入记录。
  • 存储层:IndexedDB 中 tokenStats 表,包含 sessionId、model、promptTokens、completionTokens、totalTokens、contextWindow、contextUsageRate、callType、timestamp 等字段。
  • 查询层:提供会话级汇总、全局汇总、按天聚合、按模型/调用类型分布、最近 N 条记录等接口。
classDiagram
class TokenRecorder {
+recordTokenUsage(params)
}
class TokenStore {
+recordTokenCall(record)
+getSessionTokenSummary(sessionId)
+getOverallTokenSummary()
+getDailyTokenSummary(days)
+getTokenSummaryByModel()
+getTokenSummaryByCallType()
}
TokenRecorder --> TokenStore : "写入记录"

图示来源

章节来源

加密工具函数与密钥管理 ​

  • 扩展端 shared/secret.js
    • encodeSecret/decodeSecret:Base64 + enc: 前缀标记;无前缀视为旧明文原样返回,下次写入自动升级。
  • 代理端 agent/src/crypto-lite.js
    • 与扩展端约定一致,Node 环境使用 Buffer 进行 base64 编解码。
  • 统一令牌解码实现(新增)
    • config-manager.js:导入并使用 decodeSecret 处理存储的令牌。
    • toolbox-shared.js:在 getAgentConnection 中统一解码令牌。
    • workspace-manager.js:在 getAgentConfig 中统一解码令牌。
flowchart TD
In["明文密钥"] --> Enc["encodeSecret()"]
Enc --> Out["enc:base64(明文)"]
Out --> Storage["chrome.storage.local"]
Storage --> Dec["decodeSecret()"]
Dec --> Plain["明文密钥"]
Note["兼容规则:无前缀 → 原样返回"]
Note2["统一解码:所有模块使用相同逻辑"]

图示来源

章节来源

统一令牌解码安全机制(新增) ​

安全漏洞修复:之前存在一个安全漏洞,某些模块直接将存储的加密令牌(enc:base64格式)发送给Agent服务器,导致鉴权失败(401错误)。现已在所有相关模块中实现了统一的令牌解码逻辑。

修复范围:

  • src/options/config-manager.js:导入 decodeSecret 函数
  • src/options/toolbox-shared.js:在 getAgentConnection 中解码令牌
  • src/side_panel/workspace-manager.js:在 getAgentConfig 中解码令牌

实现细节:

  • 所有模块统一使用 decodeSecret(active.token) 进行令牌解码
  • 解码后的明文令牌用于构建 Authorization 头部
  • 保持向后兼容,支持旧的明文令牌格式

安全措施:

  • 令牌在存储时始终加密(enc:前缀 + base64编码)
  • 仅在内存中使用明文令牌
  • 请求发送后立即释放明文令牌引用

章节来源

图片API密钥安全处理机制(新增) ​

安全漏洞修复:侧边栏图片API密钥处理存在安全漏洞,当用户修改图片识别API密钥时,存储的加密密钥没有被正确解密,导致视觉模型API调用时携带密文密钥而返回401错误。

修复范围:

  • src/side_panel/index.js:在初始化时解密imageApiKey并监听storage变化
  • src/side_panel/chat-manager.js:传递明文API密钥给background脚本
  • src/background/index.js:接收并传递明文API密钥
  • src/background/react-loop.js:使用明文API密钥进行视觉模型调用

实现细节:

  • 侧边栏初始化时使用 decodeSecret(result.imageApiKey) 解密存储的密钥
  • 监听 chrome.storage.onChanged 事件,对新值进行解密处理
  • 通过消息传递将明文密钥传递给background脚本的apiParams
  • background脚本将明文密钥传递给react-loop进行视觉模型调用

安全措施:

  • 图片API密钥在存储时始终加密(enc:前缀 + base64编码)
  • 仅在内存中使用明文密钥
  • 密钥传递过程中保持明文状态,避免二次加密
sequenceDiagram
participant SP as "Side Panel"
participant BG as "Background"
participant RL as "React Loop"
participant Secret as "Shared Secret"
Note over SP,Secret : 图片API密钥处理流程
SP->>Secret : "decodeSecret(stored_imageApiKey)"
Secret-->>SP : "plaintext_api_key"
SP->>BG : "sendMessage({ imageApiKey : plaintext })"
BG->>RL : "apiParams.imageApiKey = plaintext"
RL->>RL : "config.apiKey = apiParams.imageApiKey"
RL->>RL : "调用视觉模型API"

图示来源

章节来源

依赖关系分析 ​

  • server.js 作为 HTTP 入口,依赖 auth.js 与 security.js 提供认证与安全能力。
  • auth.js 依赖配置模块(loadConfig、loadPairings、savePairing)与 i18n。
  • security.js 依赖 path/os/fs/promises 与配置模块,结合 i18n 输出多语言原因。
  • token-recorder.js 依赖 token-store.js 与共享 logger。
  • token-store.js 依赖 IndexedDB 封装 withStore。
  • 新增依赖:所有涉及令牌处理的模块都依赖 shared/secret.js 中的 decodeSecret 函数。
  • 新增依赖:侧边栏图片API密钥处理依赖完整的消息传递链路。
graph LR
SRV["server.js"] --> AUTH["auth.js"]
SRV --> SEC["security.js"]
AUTH --> CFG["config.js"]
SEC --> CFG
REC["token-recorder.js"] --> TSTORE["token-store.js"]
CM["config-manager.js"] --> SECRET["shared/secret.js"]
TB["toolbox-shared.js"] --> SECRET
WM["workspace-manager.js"] --> SECRET
SP["side_panel/index.js"] --> SECRET
SCM["side_panel/chat-manager.js"] --> SP
BG["background/index.js"] --> RL["background/react-loop.js"]

图示来源

章节来源

性能与可扩展性 ​

  • 配对码轮换
    • 基于配置的 TTL 定时刷新;当检测到活跃连接时停止轮换,减少不必要的随机数生成与日志输出。
  • 路径检查
    • 先做前缀快速匹配,再 realpath 校验,避免昂贵的系统调用;对 ENOENT 场景采用父目录回溯策略。
  • 命令检查
    • collectCommandScopes 深度封顶(默认 3),避免无限递归;仅对替换特征单独送检以减少误报。
  • Token 统计
    • 使用 IndexedDB 索引(sessionId、timestamp)缩小扫描范围;按天聚合与范围查询避免全表扫描。
  • 令牌解码优化
    • decodeSecret 函数轻量高效,仅在需要发送请求时调用。
    • 解码结果缓存于内存变量中,避免重复解码。
  • 图片API密钥处理优化
    • 只在必要时解密图片API密钥,避免不必要的解密操作。
    • 通过消息传递机制避免跨上下文的数据复制开销。

[本节为通用性能讨论,不直接分析具体文件]

故障排查指南 ​

  • 配对码频繁变化
    • 检查是否有活跃连接(lastAuthTime 是否在 ACTIVE_WINDOW_MS 内);若无,则会自动轮换配对码。
    • 检查 pairCodeTTL 配置是否过短。
  • 配对失败锁定
    • 连续失败达到 PAIR_FAIL_LIMIT 次后会进入 PAIR_LOCK_DURATION_MS 锁定;等待解锁后重试。
  • 路径访问被拒
    • 确认路径是否在 allowedPaths 或 workdir 内;检查是否存在符号链接指向硬阻止目录。
    • 查看 reason 字段中的多语言提示,定位 isHardBlocked 或前缀匹配失败。
  • 命令被拦截
    • 黑名单命中将直接 deny;灰名单命中需用户确认或使用 force 模式(注意风险)。
    • 使用 collectCommandScopes 调试实际送检的子命令范围。
  • Token 统计缺失
    • 检查 recordTokenUsage 是否被调用;确认 usage 对象存在 prompt_tokens 或 total_tokens。
    • 查看 IndexedDB 中 tokenStats 表是否有记录;检查 timestamp 索引是否正常。
  • 令牌鉴权失败(新增)
    • 检查是否正确使用了 decodeSecret 函数对存储的令牌进行解码。
    • 确认 Authorization 头部携带的是明文令牌而非 enc: 格式的密文。
    • 查看浏览器开发者工具的 Network 面板,确认请求头中的 Authorization 字段。
  • 图片API密钥鉴权失败(新增)
    • 检查侧边栏是否正确解密了imageApiKey并存储在state中。
    • 确认storage变化监听器是否正确处理了新值的解密。
    • 检查background脚本是否正确接收并传递了明文API密钥。
    • 查看视觉模型API调用的请求参数,确认apiKey字段是否为明文。

章节来源

结论 ​

本项目的认证与安全体系围绕"配对码 + 令牌校验 + 路径/命令安全网关 + 统计审计"展开:

  • 配对码流程具备抗暴破与一次性使用特性,配合活跃连接检测实现动态轮换。
  • 安全网关通过黑名单/灰名单与链式命令解析,提供细粒度的命令分级管控。
  • Token 统计提供多维度的审计能力,便于成本与使用分析。
  • 密钥混淆方案简单有效,适合避免明文泄露的初级防护;生产环境应结合更严格的密钥管理策略。
  • 最新安全加固:通过统一的令牌解码机制和图片API密钥安全处理,确保了所有模块在发送请求前都正确处理加密凭据,消除了鉴权失败的安全隐患。

[本节为总结性内容,不直接分析具体文件]

附录:安全配置清单 ​

以下为通用安全配置建议,供部署与运维参考:

  • TLS 证书
    • 启用 HTTPS,使用受信任 CA 签发的证书;定期轮换证书与私钥。
    • 禁用弱加密套件与过时协议版本(如 TLS1.0/1.1)。
  • CORS 策略
    • 明确允许的 Origin、方法与 Header;避免使用通配符 *。
    • 对预检请求设置合理的缓存时长。
  • 速率限制
    • 针对配对接口与高频 API 设置 IP/用户维度的速率限制,防止暴力破解与资源耗尽。
  • 安全头
    • 设置 Strict-Transport-Security、X-Content-Type-Options、X-Frame-Options、Content-Security-Policy 等。
  • 日志与审计
    • 记录认证失败、路径/命令拒绝事件;对敏感操作进行脱敏与留存。
    • 实施日志轮转策略(按大小/时间切分),保留期限符合合规要求。
  • 令牌安全管理(新增)
    • 确保所有模块使用统一的 decodeSecret 函数处理令牌。
    • 定期检查 Authorization 头部是否正确携带明文令牌。
    • 监控鉴权失败的日志,及时发现令牌处理问题。
  • 图片API密钥安全管理(新增)
    • 确保侧边栏正确解密并传递图片API密钥。
    • 监控视觉模型API调用的鉴权状态。
    • 定期检查storage中的imageApiKey字段是否正确加密。

[本节为通用实践建议,不直接分析具体文件]