主题
认证与授权系统
本文引用的源码文件
本文引用的文件
目录
引言
本文件聚焦 Agent 端(Node.js,版本 2.3.1)的认证、授权、命令执行安全、会话管理与审计日志能力。Agent 通过本地 HTTP/WebSocket 暴露接口,由 Chrome 扩展端调用;所有敏感操作均受 Bearer Token 认证、路径沙箱、命令分级白名单/黑名单以及审计日志约束。文档同时给出认证流程图、权限检查时序图、令牌生命周期图,并说明多租户支持现状、访问控制策略和安全配置建议。
项目结构与安全边界总览
Agent 的安全边界由以下层次构成:
- 网络边界:仅响应来自
chrome-extension://来源的跨域请求;部分管理接口限制本机来源。 - 认证边界:除配对与健康检查等少数接口外,其余接口需携带
Authorization: Bearer <token>。 - 数据边界:配置文件、配对记录、日志、工作区、记忆目录均有独立路径与权限控制。
- 文件系统边界:基于规范化路径、真实路径解析与硬阻止列表的沙箱。
- 命令执行边界:命令分级(黑名单绝对禁止、灰名单需确认、白名单放行),子进程环境变量白名单与超时控制。
- 审计边界:JSON Lines 日志按日轮转,分类记录认证、文件、命令、安全与系统事件。
graph TB Extension["Chrome 扩展<br/>side_panel / background"] --> HTTP["Agent HTTP 服务器<br/>server.js"] Extension --> WS["Agent WebSocket<br/>server.js + executor.js"] HTTP --> Auth["认证模块<br/>auth.js"] HTTP --> Security["安全模块<br/>security.js"] HTTP --> Logger["审计日志<br/>logger.js"] HTTP --> Config["配置与配对<br/>config.js"] HTTP --> Executor["命令执行器<br/>executor.js"] Executor --> Shell["系统 Shell<br/>bash/zsh/cmd/powershell"] Security --> FS["文件系统<br/>workdir / allowedPaths"]
图表来源
- agent/src/server.js#L417-L548
- agent/src/auth.js#L117-L179
- agent/src/security.js#L109-L229
- agent/src/executor.js#L198-L386
- agent/src/logger.js#L132-L172
- agent/src/config.js#L107-L149
章节来源
核心组件
- 认证模块:负责配对码生成、轮换、一次性使用、失败锁定与 Token 验证。
- 安全模块:负责路径沙箱、硬阻止目录、白名单校验、命令分级检查。
- 命令执行器:负责选择 Shell、创建子进程、流式输出、超时与强制终止、进程缓存回放。
- 服务器路由:统一处理 HTTP 与 WebSocket,注入语言环境、CORS、认证、限流与审计。
- 审计日志:按类别写入 JSON Lines,支持查询与日期列表。
- 配置与配对:内存缓存、写锁保护、敏感字段落盘混淆、默认安全值。
章节来源
- agent/src/auth.js#L30-L179
- agent/src/security.js#L62-L229
- agent/src/security.js#L285-L760
- agent/src/executor.js#L32-L91
- agent/src/executor.js#L118-L156
- agent/src/executor.js#L177-L186
- agent/src/logger.js#L7-L12
- agent/src/config.js#L15-L39
架构总览
Agent 作为本地服务,对外暴露两类通道:
- HTTP:用于配对、状态、文件操作、命令执行、RAG、MCP、技能、日志查询等。
- WebSocket:用于命令执行的实时流式输出与状态回放。
所有需要认证的请求在路由层先校验 Authorization 头,再调用 verifyToken 获取扩展 ID;随后根据具体接口进行路径或命令安全检查,并记录审计日志。
sequenceDiagram
participant Ext as "扩展"
participant Srv as "HTTP 服务器"
participant Auth as "认证模块"
participant Sec as "安全模块"
participant Log as "审计日志"
participant Exec as "命令执行器"
Ext->>Srv : "POST /api/pair {code, extensionId}"
Srv->>Auth : "handlePairRequest(code, extensionId)"
Auth-->>Srv : "{success, token|error}"
Srv->>Log : "logAuth(pair_success|pair_failed)"
Srv-->>Ext : "配对结果"
Ext->>Srv : "GET /api/status/detail (Bearer token)"
Srv->>Auth : "verifyToken(token)"
Auth-->>Srv : "extensionId or null"
Srv-->>Ext : "平台与工作目录信息"
Ext->>Srv : "POST /api/exec (command, cwd)"
Srv->>Sec : "checkCommand(command, force)"
Sec-->>Srv : "{safe, level}"
alt "deny"
Srv->>Log : "logSecurity(exec_denied)"
Srv-->>Ext : "拒绝"
else "confirm"
Srv-->>Ext : "需要用户确认"
else "allow"
Srv->>Exec : "executeCommand(command, cwd)"
Exec-->>Ext : "execId + 流式 stdout/stderr"
end
图表来源
- agent/src/server.js#L474-L548
- agent/src/auth.js#L138-L179
- agent/src/security.js#L691-L758
- agent/src/executor.js#L198-L386
- agent/src/logger.js#L167-L172
详细组件分析
认证与配对机制
认证流程围绕“配对码 + 扩展 ID → Bearer Token”展开:
- 配对码生成:使用密码学安全的随机字节,从排除易混淆字符的字符表中选取 6 位编码,抗暴力猜测。
- 配对码轮换:启动时立即生成初始配对码;定时任务根据是否有配对记录与最近活跃认证决定是否停止或继续轮换。
- 一次性使用:配对成功后立即轮换配对码,防止重复利用。
- 失败锁定:连续失败达到阈值后临时锁定一段时间,并在锁定时立即轮换配对码使已观测码失效。
- Token 验证:每次请求遍历配对记录比对 token,成功则更新最后活跃时间,返回扩展 ID。
flowchart TD
Start(["启动"]) --> Gen["生成初始配对码"]
Gen --> Timer["启动定时轮换任务"]
Timer --> Check{"有配对且最近活跃?"}
Check --> |是| StopRotate["停止轮换配对码"]
Check --> |否| Rotate["重新生成配对码"]
Rotate --> Timer
StopRotate --> Timer
PairReq["收到配对请求"] --> Validate["校验 code 与 extensionId"]
Validate --> Locked{"是否处于锁定窗口?"}
Locked --> |是| DenyLock["拒绝:过于频繁"]
Locked --> |否| Match{"code 匹配当前配对码?"}
Match --> |否| IncFail["失败计数+1"]
IncFail --> Threshold{"达到失败阈值?"}
Threshold --> |是| Lock["设置锁定时间并轮换配对码"]
Threshold --> |否| InvalidCode["返回无效配对码"]
Match --> |是| ResetFail["重置失败计数"]
ResetFail --> Exists{"是否已有配对?"}
Exists --> |是| Rotated["轮换配对码并返回已有 token"]
Exists --> |否| Save["生成新 token 并保存配对"]
Save --> Rotated
图表来源
章节来源
Token 验证与会话管理
- 会话语义:Agent 端不维护传统意义上的长会话对象,而是以“配对记录中的 token”作为凭据;每次请求校验 token 并刷新最后活跃时间。
- 活跃窗口:5 分钟内有过认证视为扩展在线,影响配对码是否继续轮换。
- 心跳接口:
/api/heartbeat仅需认证,用于维持扩展在线状态,不返回敏感信息。 - 令牌生命周期:配对成功即生成 32 字节随机十六进制 token,持久化到
pairings.json;配对码轮换不影响已配对 token,但会阻断新的配对尝试。
stateDiagram-v2 [*] --> 未配对 未配对 --> 配对中 : "提交配对码" 配对中 --> 已配对 : "配对成功" 配对中 --> 被锁定 : "连续失败过多" 已配对 --> 活跃 : "心跳或认证刷新 lastAuthTime" 活跃 --> 离线 : "超过活跃窗口" 离线 --> 可配对 : "配对码轮换完成" 被锁定 --> 可配对 : "锁定时间到期"
图表来源
章节来源
权限控制系统与命令白名单
命令安全采用分级策略:
- 黑名单:绝对禁止,不可绕过,包括磁盘破坏、系统目录递归删除、系统文件覆盖、恶意管道执行、fork bomb、shebang 直接执行等。
- 灰名单:需用户确认,包括提权命令、全局安装、危险权限变更、原始写入/销毁、网络外联、进程操作、系统服务、脚本解释器执行外部文件、Windows 高危命令等。
- 白名单:通过检查的命令视为允许。
命令解析不仅检查整串,还拆分链式命令、剥壳包装器(如 sudo、env、timeout)、归一化路径目标、提取解释器内联载荷与命令替换内容,逐段判定。
flowchart TD
Entry["接收命令"] --> Normalize["清理空白与换行"]
Normalize --> Scopes["收集子命令范围<br/>整串 + 拆分段 + 内联载荷 + 替换内容"]
Scopes --> Blacklist{"命中黑名单?"}
Blacklist --> |是| Deny["拒绝:绝对禁止"]
Blacklist --> |否| HardPath{"命令包含硬阻止路径?"}
HardPath --> |是| Deny
HardPath --> |否| Force{"force 模式?"}
Force --> |是| Allow["允许:跳过灰名单"]
Force --> |否| Graylist{"命中灰名单?"}
Graylist --> |是| Confirm["需要用户确认"]
Graylist --> |否| Allow
图表来源
章节来源
文件路径沙箱与输入验证
路径检查流程:
- 规范化路径格式,处理 Windows 盘符大小写、MSYS/Git Bash 风格路径、反斜杠统一。
- 展开
~为用户主目录。 - 优先硬阻止 Agent 核心敏感文件与目录。
- 放行记忆存储目录与工作目录。
- 对
allowedPaths做前缀匹配,再用realpath解析符号链接并再次校验。 - 返回允许结果与规范化后的路径,或拒绝原因。
flowchart TD
Start["输入路径"] --> Norm["规范化路径格式"]
Norm --> Tilde{"是否 ~ 或 ~/ ?"}
Tilde --> |是| Expand["展开为主目录"]
Tilde --> |否| Abs{"是否绝对路径?"}
Abs --> |是| ResolveAbs["resolve 绝对路径"]
Abs --> |否| ResolveWork["resolve 工作目录 + 相对路径"]
Expand --> ResolveWork
ResolveAbs --> NormalizePath["normalize 路径"]
ResolveWork --> NormalizePath
NormalizePath --> HardBlock{"是否硬阻止?"}
HardBlock --> |是| DenyHard["拒绝:核心敏感文件"]
HardBlock --> |否| MemoryCheck{"是否在记忆目录?"}
MemoryCheck --> |是| AllowMem["允许:记忆目录"]
MemoryCheck --> |否| WorkdirCheck{"是否在工作目录?"}
WorkdirCheck --> |是| RealpathWork["realpath 校验并再次硬阻止"]
RealpathWork --> AllowWork["允许:工作目录"]
WorkdirCheck --> |否| AllowedPrefix{"是否在 allowedPaths 前缀?"}
AllowedPrefix --> |否| DenyPrefix["拒绝:不在允许目录"]
AllowedPrefix --> |是| RealpathAllowed["realpath 校验并再次前缀匹配"]
RealpathAllowed --> AllowAllowed["允许:白名单路径"]
图表来源
章节来源
命令执行器与超时策略
命令执行器负责:
- 选择 Shell:根据平台与环境变量探测可用 shell,回退到已知路径或原生 cmd。
- 环境变量白名单:仅透传必要环境变量,强制关闭彩色输出与终端交互特性。
- 子进程管理:记录运行中进程、输出缓冲区上限、已完成进程缓存回放。
- 超时策略:支持受管模式(协商 timeoutMs)与旧模式;期内无输出视为挂起即杀,有输出则按预算封顶逐步延长。
- 跨平台终止:Unix 使用进程组信号,Windows 使用 taskkill 递归终止。
sequenceDiagram
participant Srv as "服务器"
participant Exec as "执行器"
participant Proc as "子进程"
participant WS as "WebSocket 客户端"
Srv->>Exec : "executeCommand(command, cwd, wsClient)"
Exec->>Exec : "pickShell() + buildSafeEnv()"
Exec->>Proc : "spawn(shell, args, command)"
Proc-->>Exec : "stdout/stderr 数据"
Exec->>WS : "广播 stdout/stderr"
Proc-->>Exec : "close/error"
Exec->>Exec : "armTimeout() 决策 extend/kill"
Exec-->>Srv : "onComplete({execId, exitCode, killed})"
图表来源
- agent/src/executor.js#L32-L91
- agent/src/executor.js#L118-L156
- agent/src/executor.js#L198-L386
- agent/src/executor.js#L495-L549
章节来源
- agent/src/executor.js#L32-L91
- agent/src/executor.js#L118-L156
- agent/src/executor.js#L177-L186
- agent/src/executor.js#L198-L386
- agent/src/executor.js#L495-L549
审计日志、安全事件监控与异常检测
审计日志模块提供:
- 分类日志:认证、文件、命令、安全、系统。
- JSON Lines 格式,按日轮转,自动清理旧日志与大文件。
- 控制台输出开关,便于前台调试。
- 查询接口:按日期、分类、分页查询日志条目。
安全事件监控体现在:
- 认证失败、路径越界、命令拒绝、重启/更新操作、npm 安装异常等均记录日志。
- 服务器级异常捕获返回通用错误,避免泄露内部细节。
flowchart TD
Event["安全/认证/文件/命令/系统事件"] --> Logger["logger.log(level, category, action, details)"]
Logger --> Console{"是否启用控制台输出?"}
Console --> |是| Stderr["stderr 输出可读日志"]
Console --> |否| SkipConsole["跳过控制台"]
Logger --> File["appendFileSync(agent-YYYY-MM-DD.log)"]
File --> Cleanup["定期清理旧日志与大文件"]
图表来源
章节来源
依赖关系分析
- server.js 依赖 auth.js、security.js、executor.js、logger.js、config.js 等模块,并在请求入口注入语言环境。
- auth.js 依赖 config.js 读取/保存配对记录,依赖 i18n 与系统语言检测。
- security.js 依赖 config.js 获取 workdir 与 allowedPaths,依赖 i18n 返回本地化拒绝原因。
- executor.js 依赖 config.js 获取默认超时与工作目录,依赖 i18n 返回本地化错误消息。
- logger.js 独立于业务逻辑,提供统一日志写入与查询能力。
graph LR Server["server.js"] --> Auth["auth.js"] Server --> Security["security.js"] Server --> Executor["executor.js"] Server --> Logger["logger.js"] Server --> Config["config.js"] Auth --> Config Security --> Config Executor --> Config
图表来源
- agent/src/server.js#L13-L23
- agent/src/auth.js#L3-L5
- agent/src/security.js#L5-L6
- agent/src/executor.js#L6-L7
章节来源
- agent/src/server.js#L13-L23
- agent/src/auth.js#L3-L5
- agent/src/security.js#L5-L6
- agent/src/executor.js#L6-L7
性能与资源控制
- 输出缓冲上限:命令 stdout/stderr 累计上限为 5MB,超限后标记截断并广播提示。
- 总超时预算:受管模式下最大延长次数与总预算封顶对齐扩展端 toolTimeout 上限,避免无限延长。
- 日志清理:每 60 秒检查一次,保留最多 30 个日志文件,单文件超过 10MB 自动删除。
- 配置缓存:配置与配对记录带 mtime 缓存,减少频繁 IO。
- 写锁保护:配置与配对写入加异步写锁,防止并发覆盖。
章节来源
- agent/src/executor.js#L96-L116
- agent/src/executor.js#L166-L186
- agent/src/logger.js#L8-L11
- agent/src/logger.js#L95-L123
- agent/src/config.js#L43-L51
- agent/src/config.js#L64-L73
故障排查指南
- 无法配对:
- 检查配对码是否过期或被轮换;查看 Agent 终端输出的配对码。
- 检查连续失败是否触发锁定;等待锁定时间后重试。
- 确认扩展 ID 是否正确传入。
- 认证失败:
- 确认请求头携带正确的
Authorization: Bearer <token>。 - 检查 token 是否仍存在于
pairings.json。 - 查看安全日志中的认证失败记录。
- 确认请求头携带正确的
- 命令被拒绝:
- 若为黑名单命令,无法绕过;需修改命令。
- 若为灰名单命令,需在扩展侧确认放行。
- 检查命令是否包含硬阻止路径。
- 命令执行卡住:
- 检查是否进入受管模式的延长策略;观察输出是否为空导致静默杀进程。
- 检查 WebSocket 连接是否断开;延迟连接的客户端可回放已完成进程输出。
- 日志缺失:
- 检查日志目录是否存在与权限;确认日志写入是否被其他进程占用。
- 使用日志查询接口按日期与分类过滤。
章节来源
- agent/src/auth.js#L138-L179
- agent/src/server.js#L537-L548
- agent/src/security.js#L691-L758
- agent/src/executor.js#L429-L453
- agent/src/logger.js#L183-L211
结论
Agent 的认证与授权体系以配对码与 Bearer Token 为核心,结合路径沙箱与命令分级策略,形成多层安全边界。认证流程具备一次性配对码、失败锁定与活跃窗口机制;命令执行具备黑名单绝对禁止、灰名单用户确认与白名单放行;审计日志提供可查询的分类事件记录。整体设计强调本地安全、最小权限与可观测性,适合在 Chrome 扩展与本地代理的双进程架构中使用。
附录:安全配置、最佳实践与审计清单
安全配置要点
- 监听地址:默认仅监听
127.0.0.1,如需远程连接需显式修改 host 参数。 - 工作目录与白名单:默认工作目录与 skills 目录自动加入允许列表;建议将 allowedPaths 限制在项目目录。
- 文件大小限制:读取默认 50MB,上传流式最大 200MB;可根据需求调整 fileMaxSize。
- 命令超时:默认 300 秒;可通过 execOpts.timeoutMs 协商受管模式。
- RAG 内网访问:默认拒绝内网,需同时开启 allowPrivateNetwork 且 allowedPrivateHosts 命中才放行。
- 记忆嵌入 API Key:内存明文、落盘混淆;任何对外响应脱敏。
章节来源
- agent/src/config.js#L15-L39
- agent/src/config.js#L138-L149
- agent/src/config.js#L160-L165
- agent/src/config.js#L249-L268
最佳实践
- 始终通过扩展端发起配对,不要手动编辑
pairings.json。 - 不要在仓库中硬编码真实 token;集成测试应从环境变量或本机配对记录取得 token。
- 对高危命令尽量在扩展侧引导用户确认,避免频繁 force 放行。
- 定期检查审计日志中的安全事件,关注认证失败、路径越界与命令拒绝。
- 保持 Agent 版本与扩展版本同步,修改 Agent 源码后必须重启进程。
章节来源
安全审计清单
- 认证:
- 配对码是否动态生成且一次性使用?
- 失败锁定是否生效?
- Token 是否仅在内存中比对,不落盘明文?
- 授权:
- 所有敏感接口是否要求 Bearer Token?
- 健康检查与配对接口是否限制来源?
- 路径:
- 是否启用 realpath 防符号链接绕过?
- 是否硬阻止 Agent 核心敏感文件?
- 是否限制 allowedPaths 与工作目录?
- 命令:
- 黑名单是否覆盖磁盘破坏、系统目录删除、系统文件覆盖、恶意管道执行?
- 灰名单是否覆盖提权、全局安装、危险权限变更、网络外联、进程操作?
- 是否支持链式命令、包装器剥壳、内联载荷与命令替换检查?
- 执行:
- 是否使用环境变量白名单?
- 是否限制输出缓冲区与总超时预算?
- 是否支持跨平台进程终止?
- 审计:
- 是否记录认证、文件、命令、安全、系统事件?
- 日志是否按日轮转并自动清理?
- 是否提供日志查询接口?
章节来源