7.9 KiB
7.9 KiB
代码库风险与关注点
分析日期: 2026-05-21
高风险:安全与隐私
1) CocoaPods 构建关闭了 User Script Sandboxing
- 问题:
post_installhook 将 Pods 以及 用户工程的ENABLE_USER_SCRIPT_SANDBOXING强制设置为NO。 - 影响: 削弱对内嵌 Web 内容的纵深防御;增加
WKWebView相关功能的风险面,并可能不符合组织/审核(含 App Store)安全基线。 - 建议缓解:
- 移除全局覆盖,保持系统默认的 sandboxing。
- 如确有依赖需要 workaround,仅对具体 Pod target 做最小范围的设置,并记录原因。
- 在 CI 中增加校验:出现
ENABLE_USER_SCRIPT_SANDBOXING=NO时告警/失败。
2) 外链打开未做 allowlist(scheme/host)
- 问题: EPUB 内容中的外部 URL 通过
UIApplication.shared.open(...)打开时,未对 scheme/host 做校验,也未强制用户二次确认。 - 影响: 恶意 EPUB 可能触发钓鱼、隐私泄露,或打开意外的 URL scheme(包含跳转到其他 App 的 deep link)。
- 建议缓解:
- 强制 allowlist(默认仅允许
https;如需mailto/tel等应在明确 UI 提示后允许)。 - 弹出确认对话框,展示目标 host。
- 对 bridge 消息与导航行为中的非 HTTP(S) scheme 做拒绝/过滤。
- 强制 allowlist(默认仅允许
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)直接取消。 - 视需求考虑内容拦截规则或禁用分页阶段的网络加载。
- 在 paginator 场景加入导航策略:默认仅允许
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 政策,需文档化并提供同步/校验工具,避免漂移。
- 通常建议不要提交 Pods,仅提交
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 flags:
Podfile - Pod metadata/toolchain:
RDReaderView.podspec - Archive extraction:
Sources/RDReaderView/EPUBCore/RDEPUBParser+Archive.swift - Resource path validation(post-extraction):
Sources/RDReaderView/EPUBCore/RDEPUBParser+Resources.swift - Scheme handler reads full file bytes:
Sources/RDReaderView/EPUBCore/RDEPUBResourceURLSchemeHandler.swift - WebView bridge + message handling:
Sources/RDReaderView/EPUBCore/RDEPUBWebView+JavaScriptBridge.swift - External link opening:
Sources/RDReaderView/EPUBUI/RDEPUBReaderController.swift - UserDefaults persistence implementation:
Sources/RDReaderView/EPUBUI/RDEPUBReaderPersistence.swift - Hidden paginator web view:
Sources/RDReaderView/EPUBCore/RDEPUBPaginator.swift - Debug logging:
Sources/RDReaderView/EPUBCore/RDEPUBWebViewDebug.swift - Vendored dependencies:
Pods/、ReadViewDemo/Pods/
风险与关注点审计:2026-05-21