跳转到内容

安全:Root-Based 路径验证与遥测设计

安全:Root-Based 路径验证与遥测设计

学习目标

本章分析 Chrome DevTools MCP 的安全机制和遥测系统。你将理解:

  • MCP roots/list 协议与 Workspace Roots 白名单机制
  • validatePath() 的 canonical path 解析与路径匹配
  • 临时文件 vs 工作目录文件的区别
  • ClearcutLogger 遥测系统的异步持久化
  • 隐私保护:敏感请求头脱敏与遥测开关

前置知识


项目实践

Workspace Roots 白名单机制

项目通过 MCP 的 roots/list 协议获取 Agent 的工作区目录:

server.oninitialized = () => {
if (server.getClientCapabilities()?.roots) {
void updateRoots(); // 请求 MCP Client 发送 roots
server.setNotificationHandler(
RootsListChangedNotificationSchema,
() => { void updateRoots(); } // 监听 roots 变化
);
}
};

自动追加临时目录

roots(): Root[] {
return [
...this.#roots,
{ uri: pathToFileURL(os.tmpdir()).href, name: 'temp' },
];
}

这允许工具将文件保存到系统临时目录(如截图、Trace),即使该目录不在 workspace roots 中。

validatePath() 路径校验

validatePath(filePath):
1. resolveCanonicalPath(filePath) → 获取真实路径(解析 symlinks)
2. 遍历每个 root:
a. fileURLToPath(root.uri) → URI 转本地路径
b. fsPromises.realpath(rootPath) → 获取真实根路径
c. 检查 canonicalPath === root 或 startsWith(root + path.sep)
3. 若不在任何 root 内 → 抛出 "Access denied"

安全考虑

  • 使用 realpath 而非 resolve:解析 symlinks,防止符号链接逃逸
  • startsWith(root + path.sep) 而非 startsWith(root):防止 /tmp 匹配到 /tmp-data
  • 静默跳过无法解析的 root(console.warn 而非抛出异常)

两种文件保存方式

方法用途路径校验目录结构
saveTemporaryFile截图、Trace 等临时文件必须在 roots 内使用 os.tmpdir() 或自定义临时目录
saveFile用户指定的保存路径必须在 roots 内按用户指定路径创建目录结构

网络请求头脱敏

--redactNetworkHeaders 标志启用时,敏感请求头(如 AuthorizationCookie)在返回给 Agent 前被脱敏:

setRedactNetworkHeaders(true):
→ 在 NetworkFormatter 中过滤敏感头
→ 返回 "Authorization: [REDACTED]"

默认关闭:因为调试场景通常需要查看完整请求头。

ClearcutLogger 遥测系统

ClearcutLogger.logToolInvocation({
toolName, params, schema, success, latencyMs
}):
持久化到本地文件(FilePersistence)
异步发送到 Google Clearcut 端点
延迟桶化(bucketizeLatency)而非发送精确毫秒

遥测开关

条件效果
--no-usage-statistics禁用
CI=true 环境变量禁用
CHROME_DEVTOOLS_MCP_NO_USAGE_STATISTICS禁用

延迟桶化:发送的是延迟区间(如 “100-500ms”)而非精确值,减少数据量。

设计取舍

取舍选择原因
realpath vs resolverealpath防止符号链接绕过白名单
白名单 vs 黑名单白名单默认拒绝,更安全
精确延迟 vs 桶化桶化保护隐私,减少数据量
遥测默认开启 vs 默认关闭默认开启提高数据覆盖率,但提供明确退出选项

陷阱与对策

陷阱后果对策
symlink 指向白名单外路径绕过使用 realpath 解析
root 路径包含空格或特殊字符startsWith 误判使用 path.sep 精确匹配
遥测文件过大磁盘占用FilePersistence 定期清理旧日志

参考来源