Skip to content

cdf-file 白名单按平台整体忽略大小写,可越权读取大小写敏感卷上的同名路径 #238

Description

@suntianc

来源

2026-07-28 对最近重构范围 b1630e5^...HEAD 的双轴 code review。关联既有安全修复:#204

问题

src/main/cdf-file-protocol.ts 当前用下面的常量推断文件系统语义:

const CASE_INSENSITIVE_FILESYSTEM = process.platform === 'darwin' || process.platform === 'win32';

随后 isPathWithinRoots() 将请求路径与白名单根整体 toLowerCase() 再做 path.relative()

操作系统不等于文件系统大小写语义:macOS 可以使用大小写敏感 APFS / 外置卷,Windows 目录也可以启用大小写敏感。若授权根是 /Volumes/Data/Project,同时存在 /Volumes/Data/project,后者会在比较阶段被误判为位于前者内,随后 stat/createReadStream 按原始请求路径读取未授权文件。

这破坏了 AGENTS.md 的 Electron 最小能力边界,也使 #204 的白名单保护在合法文件系统配置下可绕过。

目标行为

  • 不再根据 process.platform 猜测路径大小写语义。
  • 对已存在的请求目标与白名单根使用文件系统解析后的真实路径进行包含性判断。
  • 默认大小写不敏感的 macOS 上,Chromium 将 /Users host-fold 为 /users 时,历史图片/音频仍能正常返回 200。
  • 大小写敏感卷上,不同大小写的兄弟目录必须保持不同授权身份。
  • 白名单外路径、.. 逃逸以及根内 symlink 指向根外的目标必须拒绝。
  • 缺失文件继续返回 404;越权文件继续返回 403;Range/Content-Type 行为不变。

实现约束

  • 高权限判断留在 main;不得把真实路径或额外文件系统能力暴露给 renderer。
  • 不按字符串全量 lower-case 代替文件系统身份判断。
  • 保持现有 cdf-file URL、preload API 和调用方契约不变。
  • 错误响应不得泄漏白名单外真实路径。

测试

src/main/cdf-file-protocol.test.ts 增加或调整:

  1. 默认大小写不敏感文件系统上的 Chromium host-fold 历史资源回归。
  2. 可同时存在的 Allowed/allowed 兄弟目录:只允许真实授权目录。
  3. 根内 symlink 指向根外文件返回 403。
  4. ..、前缀碰撞(Library / LibraryEvil)继续拒绝。
  5. Range 请求和普通请求经过同一授权结果。

测试不要通过手工传入 caseInsensitive=true 来证明生产路径正确;应覆盖生产使用的真实路径解析 seam。

验收标准

  • 大小写敏感卷不存在白名单别名绕过。
  • 默认 macOS 上历史 cdf-file:///Users/... 资源可读取。
  • symlink 与路径逃逸不能越出允许根。
  • pnpm test src/main/cdf-file-protocol.test.ts 通过。
  • pnpm run typecheck 通过。
  • pnpm run build 通过。

非目标

  • 不扩大允许根集合。
  • 不修改 bypassCSP 等与本回归无关的协议注册策略。
  • 不引入 renderer 侧授权缓存。

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    P0最高优先级:安全边界 / 数据毒化bugSomething isn't workingready-for-agentFully specified, ready for an AFK agentsecurity安全问题

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions