原作者:Yukang(CatCoding)。原文:《macOS 奇怪的安全扫码机制》,研究页记录日期为 2026 年 2 月 12 日。本文经授权整理,保留原作者的观察、排查顺序和推测,并明确区分三者。作者没有列出确切 macOS 与 VS Code 版本,本次也没有复现这些耗时。
作者在运行 Rust 编译器测试时发现速度异常缓慢,CPU 资源没有充分使用。几年前他遇到过相近现象,并发表过相关排查文章;这次现象虽然相似,解决过程却不同。他不确定变化来自 macOS 更新还是 VS Code 更新,因此先把问题缩小为“新建可执行脚本的第一次运行”。

从新文件的首次、再次执行开始
原脚本循环十次,每次用 openssl rand -hex 10 生成随机文件名,在 /tmp/speed_test 下写入只打印 Hello 的 shell 脚本,赋予执行权限,然后分别测量同一文件的第一次与第二次直接执行。TIMEFORMAT="%R" 用于输出墙钟耗时,脚本输出重定向到 /dev/null,计时结果从标准错误捕获。
原文开头有递归删除固定目录的 rm -rf /tmp/speed_test,并使用未加引号的 $FILE。这里不提供一段可一键执行的破坏性原样副本。下面是编者安全改写:新建独立临时目录、不删除任何目录,只给当前用户执行权限,并对路径加引号。逻辑仍是十个新文件各运行两次,但它只经过静态审核,未运行。
#!/bin/bash
set -eu
test_dir=$(mktemp -d "${TMPDIR:-/tmp}/wwj-speed-test.XXXXXX")
printf '测试目录:%s\n' "$test_dir"
for i in {1..10}; do
filename=$(openssl rand -hex 10)
file="$test_dir/$filename.sh"
printf '#!/bin/sh\necho Hello\n' > "$file"
chmod u+x "$file"
first=$(TIMEFORMAT="%R"; (time "$file" > /dev/null) 2>&1)
second=$(TIMEFORMAT="%R"; (time "$file" > /dev/null) 2>&1)
printf '第一次: %s 第二次: %s\n' "$first" "$second"
done
# 不自动删除:仅在确认路径属于本次隔离目录后自行清理。
它仍会创建文件并运行新生成的脚本,只适合使用者自己批准的隔离开发环境。随机命名减少的是重用同一路径的干扰,不能保证系统的所有安全缓存、父进程状态或内容缓存都被重置。
原作者在 VS Code 集成终端中记录到以下输出:
第一次: 0.525 第二次: 0.007
第一次: 0.290 第二次: 0.009
第一次: 0.280 第二次: 0.007
第一次: 0.272 第二次: 0.008
第一次: 0.307 第二次: 0.008
作者概括为相差约 30–50 倍;这是原文描述,各行实际比值并不相同。换到 Warp 终端运行同类脚本时,两次都在 0.006 秒左右。该对照提示终端或其所处安全上下文可能有关,但没有证明“所有 VS Code 都慢”或“换终端普遍提升 30–50 倍”。
用日志缩小到 syspolicyd
作者确认已把 VS Code 加入“系统设置 → 隐私与安全性 → 开发者工具”,认为这不像上次的 SIP 问题。他也认为 0.2–0.5 秒的延迟不像普通磁盘缓存差异,于是查看最近两分钟的安全策略日志:
log show --predicate 'subsystem == "com.apple.syspolicy.exec"' \
--last 2m --style compact
原日志包含 GK performScan、NSOSStatusErrorDomain Code=-67062 和 GK evaluateScanResult,且作者观察到每次执行新文件都会出现扫描记录:
GK performScan: PST: (path: 8d0e4c2de41c3e77), (team: (null)), (id: (null)), (bundle_id: (null))
Error Domain=NSOSStatusErrorDomain Code=-67062
GK evaluateScanResult: 2, PST: (path: 8d0e4c2de41c3e77), ... (bundle_id: NOT_A_BUNDLE), 0, 0, 1, 0, 7, 7, 0
这些是原文摘录,不是本次读取的机器日志。日志中的字段或错误码不能脱离系统版本单独解释为一个确定故障。对实际机器排查时,应匹配执行时间、文件和进程;导出日志前注意其中可能包含路径、应用标识及其他个人信息。
直接执行和显式解释执行
作者进一步把计时命令改为显式调用解释器:
(time /bin/sh "$FILE" > /dev/null) 2>&1
这里的引号是编者补充,原文使用未引号化的变量。作者记录:直接 ./script.sh 约 0.248 秒,/bin/sh ./script.sh 约 0.006 秒。这两种方式的执行路径不同:前者让脚本路径进入直接执行流程,后者是已运行的 shell 读取脚本内容。
作者据此将延迟关联到 Gatekeeper,提出从 execve、AppleSystemPolicy.kext 的 MACF hook(mpo_proc_notify_exec_complete)到 syspolicyd 的解释。他原文也明确承认,具体内部流程来自实验推断和社区逆向,而不是 Apple 的公开设计说明。不能把“显式解释运行这次快”扩张成“解释器运行的任意代码都不接受安全检查”,更不能把这种差异当作运行未知脚本的方法。
Apple 的 Gatekeeper 与运行时保护文档说明了签名、公证、完整性及已知恶意内容检查等保护职责,但没有为本个案中 FDA、负责进程和所谓快速路径之间的每一步关系背书。
赋予 Full Disk Access 后发生了什么
接着,作者在“隐私与安全性 → 完全磁盘访问权限”中给 VS Code 开启 Full Disk Access(FDA),重启 VS Code,再运行脚本。记录变成:
第一次: 0.005 第二次: 0.005
第一次: 0.005 第二次: 0.005
第一次: 0.006 第二次: 0.006
作者称延迟消失,并且日志里不再出现此前的 performScan。他用 TCC 权限 kTCCServiceSystemPolicyAllFiles、responsible process(负责进程)以及高信任来源来解释现象,推测 VS Code 的子进程因此走了快速评估路径;他还把 Warp 的表现关联到开发工具信任列表。
这些内部解释需继续保留“作者推测”的限定。尤其是“FDA 是最高级别信任授权”“FDA 会跳过完整扫描”等表述,没有在本次官方资料中得到证实。FDA 的实际后果包括扩大应用对敏感文件的访问面;不能为了未经确认的性能收益,默认让所有编辑器或终端获取该权限。
撤销权限后仍然快:为什么这不是因果证明
原作者随后移除 VS Code 的 FDA 权限,重启应用,再跑脚本,仍然很快。他指出 /var/db/SystemPolicyConfiguration/ExecPolicy 这个 SQLite 数据库(其机器当时约 35 MB),并查询内核统计:
sysctl security.mac.asp.stats.cache_entry_count
# 原作者输出:security.mac.asp.stats.cache_entry_count: 4700
作者将其理解为信任结果被持久化,并称系统会记住过去的决定。但这个实验顺序没有把权限变化与缓存状态独立控制:第一次授权时已经改变了运行历史,撤销后也没有恢复同样的起点。因此“FDA 造成提速”与“缓存或其他状态造成提速”的贡献无法被严格分开;查询到缓存条目数量,也不能证明具体哪一条缓存导致结果。
原文猜测重启或更极端地清理 ExecPolicy 数据库可能帮助复现。本文保留这一猜测的来源,但不提供删除安全数据库的命令,也不建议据此清理它。那不是已验证的复现步骤,会改变系统安全状态。
把这个案例变成可复核的排查方法
原文最后建议先检查开发者工具列表,再尝试 FDA,并给出查看最近扫描记录的命令:
log show --predicate 'subsystem == "com.apple.syspolicy.exec"' \
--last 5m --style compact | grep performScan
作为编者补充,更稳妥的顺序是先记录 macOS、终端、VS Code 版本及现有权限;用无秘密、无网络操作的最小测试比较首次与再次执行,交叉安排终端和执行方式;再把计时与安全日志时间对应起来。若要评估权限影响,应设计能控制缓存、顺序及重新启动条件的试验,不把一次“变快”作为普遍结论。
本稿没有修改 FDA、Developer Tools、Gatekeeper、SIP 或任何安全数据库,没有读取用户机器日志,也没有执行生成脚本。对原文的修改包括移除递归删除步骤、使用独立临时目录、补路径引号,并把机制断言恢复为有边界的个案推断。没有发现其他脚本问题不等于无漏洞。
原文参考还包括 Scott Knight 的 syspolicyd 研究与 Howard Oakley 的 macOS 研究,它们是原作者理解内部机制的线索。保留 Yukang / CatCoding 的作者归属;配图为原创对照图,不是伪造的测试或系统截图。












暂无评论内容