Skip to content

05 · 应用保护与白名单

路径只描述“在哪里”,应用保护还要回答“它属于谁、承载什么数据、当前为什么不能动”。

规则数据与判断逻辑分离

app_protection_data.sh 保存系统关键 Bundle、可卸载 Apple 应用、官方卸载器规则、EDR 前缀和数据保护 Bundle;app_protection.sh 负责决策。

这种分离让审查者能分别检查“规则是否完整”和“规则如何组合”,也避免一长串模式匹配淹没控制流。

三种保护问题

判断关注点示例
should_protect_from_uninstall应用本体能否卸载系统关键应用、不可安全手工卸载的软件
should_protect_data用户数据能否删除Notes、Mail、Keychain、账户与许可数据
should_protect_path任意路径是否应跳过EDR、网络扩展、Codex 持久状态、系统配置

卸载模式会对“用户明确选择的应用”放宽部分数据保护,但不会放宽系统关键应用保护。这把用户授权限制在具体对象上,而不是把整个运行期切到不安全模式。

Bundle ID 是主要身份证据

卸载器优先从 Info.plist、Spotlight 与安装收据建立 Bundle 身份。匹配要求完整 reverse-DNS 标识,避免用短应用名做宽泛搜索。对 XPC、appex 和登录项等嵌套组件,解析数量有上限,并排除 Sparkle 等常见共享标识。

这解决了名字碰撞:GUI 应用 “Codex” 与 ~/.codex、GUI “Claude” 与 ~/.claude 不必然属于同一个产品。仅凭名称会让卸载器删除独立 CLI 的持久数据。

白名单保护双向关系

白名单支持精确路径和 glob,匹配时既保护目标本身与后代,也保护其祖先,避免删除父目录间接抹掉白名单项。路径会折叠重复 /,降低文本形式差异带来的绕过。

白名单不是“删除许可名单”,而是额外的拒绝层。它只能减少操作范围,不能覆盖系统保护。

容器和缓存的细粒度

一个容器根可能承载配置、数据库与令牌,必须保护;容器内部明确识别的缓存叶节点却可能安全清理。Mole 因此不把“容器路径”一概视为可删或不可删,而是区分根与缓存叶。

Bundle 解析的降级路线

解析器先使用有超时的 mdfind,失败后检查常见应用目录与 Info.plist,再补充 SMJobBless helpers 与已知映射。快速路径不可用不会导致安全规则失效,只会进入更慢、更保守的路径。

关键源码索引

下一章补齐容易被忽略的运行时地基:有界等待、sudo 会话、临时文件、终端 UI 与日志。

独立源码研究笔记 · 非 Mole 官方文档