Files
ReadViewSDK/Doc/CONCERNS.md
T
shenlei 3e60bf1869 修复阅读器资源、朗读与持久化稳定性
阅读器在多会话朗读、加密 EPUB 资源、并发打开同一本书和多 UserDefaults 容器等场景下,存在旧异步结果覆盖新状态、锁屏控制串会话、大型明文资源被误拒绝、解压半成品被复用及标注跨容器混用的风险;同时高亮、书签、搜索和设置面板的空状态与自动化可访问性入口不完整。\n\n本次为朗读会话引入代次和当前 utterance 校验,远程控制改为仅响应当前会话并按自身 token 清理;加密资源 provider 先判定是否实际返回解密数据,明文大资源继续流式读取;解压缓存串行化以避免并发复用未完成目录。书签与高亮迁移至受保护文件,按 UserDefaults 容器隔离命名空间,保留标准容器旧文件兼容并确保新副本成功落盘后才删除历史数据。\n\n同步调整缓存淘汰、FoundationModels 弱链接、搜索/标注/设置面板交互与 UI 测试,并更新 Pod 生成配置及 API、风险文档。已执行 git diff --check 和 ReadViewDemo Debug Simulator 构建,结果为 BUILD SUCCEEDED。
2026-07-30 20:52:21 +09:00

9.6 KiB
Raw Blame History

代码库风险与关注点

分析日期: 2026-05-21 状态复核: 2026-07-30(逐条对照源码,结论见下表;正文段落保留原始分析,勿当作现状)

# 项目 现状
1 User Script Sandboxing 被关 部分处理:已移除 Podfile 的全局强制覆盖;但显式打成 YES 会让 CocoaPods 的 [CP] Embed Pods Frameworks rsync 阶段被沙箱拒绝而构建失败(已实测)。要真正开启需先改掉 use_frameworks! 动态框架集成方式。
2 外链未做 allowlist 已修RDEPUBReaderController+ExternalLinks.swift 有 scheme allowlist + 二次确认弹窗 + delegate 否决。
3 Zip Slip 未加固 已修RDEPUBParser+Archive.swiftvalidatedExtractionDestination 做 standardized 前缀校验并拒绝 ../绝对路径。
4 高亮/选中文本明文写 UserDefaults 已修:新增 RDEPUBProtectedContentStore,高亮与书签改写 Application Support 下带 file protection 的文件、排除备份,首次读取自动迁移并删除明文;另加 clearReadingData(for:) / clearAllReadingContent()
5 Scheme handler 整文件读内存 原判断有误>512KB 早已走 respondWithStreaming 64KB 分块。本次补上 maximumInMemoryResourceBytes(默认 64MB)给走不了流式的加密 provider 分支兜底。
6 分页 WKWebView 可能加载外部资源 未复核。
7 解压缓存无限累积 已修pruneExtractionCache(keeping:) 先按 extractionCacheMaximumAge30 天)再按 extractionCacheMaximumTotalBytes(512MB)做 LRU 淘汰;复用时 touch mtime;另有 clearExtractionCache()
8+ 其余性能/可维护性项 未复核。

高风险:安全与隐私

1) CocoaPods 构建关闭了 User Script Sandboxing

  • 问题: post_install hook 将 Pods 以及 用户工程的 ENABLE_USER_SCRIPT_SANDBOXING 强制设置为 NO
  • 影响: 削弱对内嵌 Web 内容的纵深防御;增加 WKWebView 相关功能的风险面,并可能不符合组织/审核(含 App Store)安全基线。
  • 建议缓解:
    • 移除全局覆盖,保持系统默认的 sandboxing。
    • 如确有依赖需要 workaround,仅对具体 Pod target 做最小范围的设置,并记录原因。
    • 在 CI 中增加校验:出现 ENABLE_USER_SCRIPT_SANDBOXING=NO 时告警/失败。

2) 外链打开未做 allowlistscheme/host

  • 问题: EPUB 内容中的外部 URL 通过 UIApplication.shared.open(...) 打开时,未对 scheme/host 做校验,也未强制用户二次确认。
  • 影响: 恶意 EPUB 可能触发钓鱼、隐私泄露,或打开意外的 URL scheme(包含跳转到其他 App 的 deep link)。
  • 建议缓解:
    • 强制 allowlist(默认仅允许 https;如需 mailto/tel 等应在明确 UI 提示后允许)。
    • 弹出确认对话框,展示目标 host。
    • 对 bridge 消息与导航行为中的非 HTTP(S) scheme 做拒绝/过滤。

3) EPUB 解压未显式做 Zip Slip(路径穿越)加固

  • 问题: 解压逻辑构造 destinationURL = extractionURL.appendingPathComponent(entry.path) 并解压 entry,但未显式验证标准化后的目标路径是否仍在 extractionURL 之内。
  • 影响: 构造的 EPUB 可能尝试通过 ../... 路径穿越覆盖目标目录外的文件(实际危害与 ZIPFoundation 行为及权限有关,但建议显式防护)。
  • 建议缓解:
    • 解压前计算 standardizedDestination = destinationURL.standardizedFileURL,并确保其前缀位于 extractionURL.standardizedFileURL.path + "/" 之下。
    • 拒绝包含 ..、绝对路径、或异常路径分隔符形式的 entry。
    • 考虑先解压到新的随机 UUID 目录,仅将校验通过的内容移动到最终目录。

4) 选中文本/高亮内容明文写入 UserDefaults

  • 问题: 选中文本与高亮 payload 以 JSON 编码写入 UserDefaults(包含“新”持久化与 legacy 路径)。
  • 影响: 可能将书籍敏感内容(高亮、选择文本)存入默认不加密的持久化位置,可能进入备份;同时数据量可能无限增长(性能与隐私风险)。
  • 建议缓解:
    • 仅持久化稳定标识/范围(例如 CFI / rangeInfo),运行时再派生文本。
    • 如必须持久化文本,存入加密存储(例如 Keychain 或使用 NSFileProtectionComplete 的加密文件)并设置大小上限。
    • 增加数据保留策略,并提供 “Clear reading data” API。

性能与稳定性风险

5) Scheme handler 将整文件一次性读入内存(无流式)

  • 问题: WKURLSchemeHandler 使用 Data(contentsOf:) 读取资源并一次性返回。
  • 影响: EPUB 内的大图/字体/媒体资源可能导致内存峰值、加载变慢,甚至在内存压力下被系统终止。
  • 建议缓解:
    • 尽可能改为基于 InputStream 的流式传输,并使用增量 didReceive(...)
    • 对单个资源增加大小上限,超过则优雅失败并提示。

6) 隐藏的分页 WKWebView 可能加载外部资源

  • 问题: RDEPUBPaginator 使用 loadFileURL(...allowingReadAccessTo:),但未看到对 navigationAction 的 allowlist(例如仅允许 file:// 或自定义 ss-reader://)。
  • 影响: 分页测量阶段可能产生意外网络请求,引发隐私泄露与不可控性能波动。
  • 建议缓解:
    • 在 paginator 场景加入导航策略:默认仅允许 file://(以及必要的自定义 scheme),对 http(s) 直接取消。
    • 视需求考虑内容拦截规则或禁用分页阶段的网络加载。

7) EPUB 解压缓存目录可能无限累积

  • 问题: 解压路径基于文件名/大小/mtime 的确定性签名;若目录已存在则直接复用,且无清理策略。
  • 影响: 书籍数量多或频繁更新时磁盘占用持续增长,造成存储压力与潜在卡顿。
  • 建议缓解:
    • ssreaderview-epub 缓存目录实现淘汰策略(LRU/按时间)。
    • 提供显式清理 API,并在低存储信号时触发清理。

可维护性与技术债

8) DEBUG 下日志与 Web Inspector 可能泄露内容

  • 问题: Debug 辅助会打印导航/消息体;selection payload 可能包含用户选中文本;且 DEBUG 下可能默认开启 inspectable。
  • 影响: 在 debug 构建(含内部测试/QA)中,日志可能包含敏感内容并被导出/分享。
  • 建议缓解:
    • 默认对消息体做脱敏(仅记录类型/大小),需要时再显式 opt-in 输出内容。
    • isInspectable 受控于 app 级 debug 开关,而不是在 DEBUG 下默认启用。

构建与依赖脆弱性

9) 仓库中包含 vendored 的 Pods/ 目录

  • 问题: 仓库根目录有 Pods/,示例工程内也有 ReadViewDemo/Pods/
  • 影响: diff 体积大、clone 慢、易产生 merge 冲突,也容易出现依赖陈旧导致的构建不一致。
  • 建议缓解:
    • 通常建议不要提交 Pods,仅提交 Podfile.lock,在 CI 中执行 pod install
    • 如确有 vendoring 政策,需文档化并提供同步/校验工具,避免漂移。

10) Podfile 与 podspec 的部署版本不一致

  • 问题: Podfile 设为 platform :ios, '15.6',而 podspec 声明 s.platform = :ios, "15.0"
  • 影响: 对外承诺与本地构建基线不一致,容易造成集成方预期偏差。
  • 建议缓解:
    • 对齐 Podfile*.podspec、Xcode project 的 deployment target。
    • 在 CI 中增加漂移检查,防止版本被无意改动。

11) podspec 将 Swift 版本钉死为 5.10

  • 问题: s.swift_versions = ["5.10"] 将 pod 与特定 Swift 版本强绑定。
  • 影响: 旧工具链的集成方无法使用;未来升级可能出现“突然不兼容”,尤其当依赖未同步时。
  • 建议缓解:
    • 如兼容性允许,可声明更多支持版本(或范围),并在 CI 中覆盖多个 Xcode/Swift 版本构建验证。
    • 在文档中明确最低支持的 Xcode/Swift 版本。

不清晰/容易踩坑的契约

12) 默认的持久化协议实现可能静默丢失数据

  • 问题: RDEPUBReaderPersistence 通过 protocol extension 提供了 bookmarks/settings 的默认 no-op 实现。
  • 影响: 集成方可能误以为这些能力默认会持久化,但实际数据会被静默丢弃,且不易排查。
  • 建议缓解:
    • 将关键方法改为必须实现(移除 no-op 默认实现);或在未实现且功能启用时输出日志/assert。
    • 提供并文档化 “最小持久化” 与 “完整持久化” 的参考实现。

Evidence(仓库路径)

  • Build flagsPodfile
  • Pod metadata/toolchainRDEpubReaderView.podspec
  • Archive extractionSources/RDEpubReaderView/EPUBCore/RDEPUBParser+Archive.swift
  • Resource path validationpost-extraction):Sources/RDEpubReaderView/EPUBCore/RDEPUBParser+Resources.swift
  • Scheme handler reads full file bytesSources/RDEpubReaderView/EPUBCore/RDEPUBResourceURLSchemeHandler.swift
  • WebView bridge + message handlingSources/RDEpubReaderView/EPUBCore/RDEPUBWebView+JavaScriptBridge.swift
  • External link openingSources/RDEpubReaderView/EPUBUI/RDEPUBReaderController.swift
  • UserDefaults persistence implementationSources/RDEpubReaderView/EPUBUI/RDEPUBReaderPersistence.swift
  • Hidden paginator web viewSources/RDEpubReaderView/EPUBCore/RDEPUBPaginator.swift
  • Debug loggingSources/RDEpubReaderView/EPUBCore/RDEPUBWebViewDebug.swift
  • Vendored dependenciesPods/ReadViewDemo/Pods/

风险与关注点审计:2026-05-21