mcpField
A
audit-xcode-security-settings

audit-xcode-security-settings

github.com/tartinerlabs安全8277 次安装5 天前更新
代码仓库

关于 audit-xcode-security-settings

用于审计 Xcode 项目的安全构建设置和权限,并规划逐步加固。面向维护 Xcode 项目的团队;它会先生成可审阅的计划,仅在获批后应用更改,并提供设置、功能和采用顺序方面的指导。

主要功能

  1. 01审计构建设置和权限
  2. 02规划渐进式安全加固
  3. 03检查特定目标的设置
  4. 04仅应用已批准的更改
  5. 05使用 Xcode 工具操作项目

适用场景

  1. 01评估 Xcode 项目的安全状况
  2. 02规划 Enhanced Security 的采用
  3. 03按目标检查权限变更
  4. 04应用已批准的加固设置

MCP 相关

该技能会在可用时要求使用 MCP 服务提供的 Xcode 工具,包括项目搜索、读取、更新和目标枚举。它本身未说明提供 MCP 服务接口。

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/tartinerlabs/skills --skill audit-xcode-security-settings

安装后在 Claude Code 中输入/audit-xcode-security-settings确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

references/
additional-settings.md
adoption-strategy.md
checked-pointer-arithmetic.md
cpp-hardening.md
decision-document.md
enhanced-security.md
hardware-memory-tagging.md
pointer-authentication.md
reading-build-settings.md
readonly-platform-memory.md
runtime-restrictions.md
security-compiler-warnings.md
security-settings-reference.md
stack-zero-init.md
typed-allocators.md
universal-binaries-for-libraries.md
scripts/
filter_build_settings.py

详细介绍

审计 Xcode 安全设置

评估 Xcode 项目的安全态势,并逐步启用安全构建设置和授权 — 从广泛适用的警告,到 Enhanced Security 加固。

工具偏好

当 XcodeGlob、XcodeGrep、XcodeRead、XcodeLS 和 XcodeUpdate 工具可用时,ALWAYS 使用它们。不要回退到 Bash 文件系统工具(ls、find、cat、grep)来了解项目。它们会触发额外的权限提示,并绕过项目作用域。

工具名称可能带有 MCP 服务前缀。 这些工具由某个 MCP 服务托管,其名称因环境而异(xcode-mcp、xcode-tools、xcode 等),因此它们的完全限定名类似于 mcp__<server>__XcodeGlob。某些执行环境会注册短别名(仅 XcodeGlob);其他环境只暴露带前缀的形式。不要硬编码特定的服务名称。首次调用时,使用可用工具注册表所公布的任一形式 — 查找一次前缀,然后在本次会话的其余部分复用。如果短名称调用因未知工具错误而失败,不要猜测前缀:在注册表中查找它,然后用完整名称重试。

  • XcodeGlob 用于文件发现 — 项目内文件禁止使用 find。
  • XcodeGrep 用于内容搜索 — 项目内文件禁止使用 grep/rg。
  • XcodeRead 用于读取文件内容 — 项目中已注册的文件禁止使用 cat/Read。
  • XcodeLS 用于列出目录 — 项目内任何路径禁止使用 ls。
  • XcodeUpdate 用于就地编辑项目已注册的文本文件(xcconfig 文件、源文件)— 与内置 Edit 工具具有相同的 filePath / oldString / newString(+ 可选 replaceAll)签名,但接受 Xcode 工作区相对路径。项目中已注册的文件禁止使用 Edit。不要使用 XcodeUpdate / Edit / plutil 添加或更新 .entitlements 键 — 请使用 AddEntitlement。
  • AddEntitlement 用于添加或更新目标的授权 — 传入 targetName、entitlementKey、entitlementValueType(bool / string / int / stringArray / dictionary)以及值。进行授权更改时始终优先使用它;它只能添加或更新,不能删除键。
  • XcodeListTargets 用于枚举目标 — 不要手动解析 project.pbxproj。直接返回每个目标的 PRODUCT_TYPE_IDENTIFIER 和角色标志(IS_AGGREGATE、IS_TEST_TARGET、IS_APP_EXTENSION、SUPPORTS_HOSTING_TESTS)。

项目根目录和名称已经在系统提示词上下文中。 开始前不要运行 ls 来"验证"项目布局。系统提示词已经告诉你工作目录和项目结构。

XcodeGlob 的空结果不是失败。 .xcodeproj 和 .xcworkspace 不会作为文件被索引到 Xcode 工作区中 — XcodeGlob "**/*.xcodeproj" 正确返回 0 个匹配。请改用系统提示词上下文中的项目名称。不要回退到文件系统 ls/find。

所有 Xcode* 工具都接受 Xcode 工作区相对路径。 XcodeGlob、XcodeGrep、XcodeRead、XcodeLS、XcodeUpdate、XcodeWrite 和 XcodeRM 将其路径参数 — 以及返回的路径 — 解释为相对于 Xcode 工作区根目录(即你在 Project Navigator 顶部看到的内容)。不是 git 仓库根目录;也不是 .xcodeproj 包。用户在 Xcode 中看到的任何内容(授权、xcconfig、计划和决策文档、源文件)都可以通过其工作区相对路径访问到;将该路径原样传给这些工具,不要为其构造绝对文件系统路径。

要读取或编辑特定文件:

  • 优先使用带工作区相对路径的 XcodeRead / XcodeUpdate。XcodeRead 也能读取 .entitlements plist — 它们是项目已注册的文件,可以像任何源文件一样导航 — 因此请用这种方式读取它们。要添加或更新授权,请使用 AddEntitlement,而不是 XcodeUpdate。 对于 entitlements 文件,绝不手动推导路径。 每个 target 的权威 entitlements 路径是其 CODE_SIGN_ENTITLEMENTS 构建设置求值后的值 —— 通过 GetTargetBuildSettings 获取并原样使用。不要解析 project.pbxproj 来重建路径,也不要使用 **/*.entitlements 通配符匹配:磁盘上可能存在未被任何 target 引用的孤立 .entitlements 文件。一个 entitlements 文件可以被多个 target 引用。

仅在 Xcode 工具无法完成的操作(例如 git 操作)中才回退到使用 Bash。

内置参考文档

所有参考资料都位于与本文件同级的 references/ 目录下。

  • references/security-settings-reference.md —— 本技能跟踪的安全构建设置与 entitlements 的规范列表,包含加固值、CLI 标志和语言适用范围。
  • references/reading-build-settings.md —— GetTargetBuildSettings schema、过滤脚本用法、审计表构建,以及“已加固” / “有意禁用” 判定条件。
  • references/enhanced-security.md —— Enhanced Security 能力:构建设置、entitlements、支持的产品类型。
  • references/pointer-authentication.md —— arm64e 指针签名:支持的平台、使用方兼容性说明。
  • references/universal-binaries-for-libraries.md —— 面向库/框架 target 的通用二进制指南(指针认证会自动添加 arm64e 切片)、符合条件的产品类型、XCFramework 指南。
  • references/security-compiler-warnings.md —— Enhanced Security 启用的安全相关编译器警告和设置。
  • references/cpp-hardening.md —— C++ 标准库加固(CLANG_CXX_STANDARD_LIBRARY_HARDENING)与边界安全缓冲区(ENABLE_CPLUSPLUS_BOUNDS_SAFE_BUFFERS)。
  • references/typed-allocators.md —— 类型感知分配器支持与 hardened-heap 子选项。
  • references/stack-zero-init.md —— 运行时自动对栈变量进行零初始化。
  • references/readonly-platform-memory.md —— dyld 状态的只读保护。
  • references/runtime-restrictions.md —— dylib 与 Mach message 平台限制。
  • references/hardware-memory-tagging.md —— MTE entitlements 与支持的硬件。
  • references/checked-pointer-arithmetic.md —— 受检指针运算(CPA2)。
  • references/additional-settings.md —— 默认值之外的可选诊断设置(可能有更多误报)。
  • references/adoption-strategy.md —— 验证 Enhanced Security 功能的推荐顺序(从最低风险到最高投入)。
  • references/decision-document.md —— 如何维护持久化的 xcode-security-settings.md 决策文档。

本技能附带一个辅助脚本:

  • scripts/filter_build_settings.py —— 将 GetTargetBuildSettings JSON 过滤为 security-settings-reference.md 中跟踪的宏。用法参见 references/reading-build-settings.md。
常见失败模式
现象原因正确处理方式
对 XcodeGlob 等工具调用失败,报错 "unknown tool" / "tool not found"在此环境中,harness 仅以带 MCP 前缀的完整名称(mcp__<server>__XcodeGlob)注册这些工具在可用工具注册表中查找前缀,用完整名称重试一次,然后在整个会话中继续使用完整名称。
XcodeGlob "**/*.xcodeproj" 返回 0 个匹配项.xcodeproj 本身不是项目索引中的文件使用系统上下文中的项目名称;不要退回到 find 或 ls
对确实位于 .xcodeproj / .xcworkspace 包内的文件(例如 WorkspaceSettings.xcsettings)执行 XcodeRead <workspace-relative-path> 失败该文件不是项目导航器成员使用系统上下文中的项目根目录将其转换为文件系统绝对路径,然后使用 Read / Edit。(不适用于 .entitlements 文件——那些是可导航的。)
对手动推导出的 entitlements 路径执行 Read 返回 File does not exist该路径是根据 project.pbxproj 的 group 嵌套结构重建的,或通过 glob **/*.entitlements 猜测的。Xcode 对某个 target 的 entitlements 的权威路径是 CODE_SIGN_ENTITLEMENTS 的求值结果,而不是导航器显示的内容。通过 GetTargetBuildSettings 查找该 target 的 CODE_SIGN_ENTITLEMENTS(或从审计表中读取),并将其求值结果用作路径。

工作流

阶段 1:简报

在开始任何工作之前,用两三句话告诉用户——这个技能是什么、它会做什么,以及大致需要他们投入多少时间和注意力:

  • 它是什么。 对项目 Xcode 安全构建设置和 entitlements 进行审计(编译器警告、Enhanced Security entitlements、指针认证、受检指针运算、库的通用二进制文件等)。
  • 会发生什么。 该技能分为两部分,长度大致相当。首先是 规划:我分析项目并在项目根目录写下一个可编辑的计划文件供你审阅。然后是 执行:一旦你选择 Run,我只应用你已批准的更改。在你选择 Run 之前,不会修改任何内容。
  • 时间投入。 规划 需要我几分钟的分析(对于有许多 target 的项目会更久——我会同步说明进度),外加你审阅计划文件的时间,你可以快速浏览也可以仔细阅读——由你决定。执行 耗时大致相同:应用已批准的更改,其中有两处可能会暂停以等待你的输入——询问步骤(如果有故意禁用的设置且其理由没有文档记录),以及最后关于是否将计划文件保留在项目中作为记录的 yes/no 确认。 整个过程通常需要约 15-30 分钟,大致平均分配到两部分,具体取决于构建 target 的数量以及你审阅和批准计划所需的时间。

保持简洁——用户调用该技能时已经知道自己想要一次审计。 简报的存在是为了让他们有合理的预期。

然后检查源代码控制。 如果满足以下任一条件,则项目有 源代码控制:

  • Environment 块的 Is a git repository 字段为 true,或
  • 在项目根目录进行一次文件系统检查,发现以下任意一项:.git、.hg、.svn、.bzr、.fslckout、_FOSSIL_、CVS。

否则,项目 没有源代码控制。记录此状态——阶段 4 步骤 3 会用它来决定是否在计划文件中包含 ⚠️ 引用块。

在完成简报后,通过 AskUserQuestion 暂停。如果项目有源代码控制:

  • 开始审计 —— 进入阶段 2。
  • 取消 —— 以 "Cancelled — no changes applied." 退出。

如果项目 没有源代码控制,先告诉用户:"强烈建议在继续之前设置源代码控制。该技能会修改构建设置和 entitlements;如果没有类似 Git 的工具,回滚需要手动操作,而且你也没有一种干净的方式来审阅差异。Xcode 内置支持 Source control management" 然后询问:

  • 先设置源代码控制(推荐) —— 以 "Set up source control and re-run the skill." 退出。
  • 在没有源代码控制的情况下继续 —— 进入阶段 2;阶段 4 步骤 3 会在计划文件中再次提示无源代码控制的提醒。
  • 取消 —— 以 "Cancelled — no changes applied." 退出。

暂停的存在是为了让简报在屏幕上停留足够长的时间以便阅读;否则 Discovery 和 Analysis 的输出会把它滚走。在没有源代码控制时尽早失败,可以避免花几分钟进行 discovery 和 analysis,结果用户却在计划批准时退出。

阶段 2:Discovery

阅读系统提示中的 Environment 块。相关字段:

  • Primary working directory —— 项目根目录(项目名称即为其 basename)。
  • Is a git repository —— 项目是否被 git 跟踪(供阶段 1 的源代码控制检查使用)。

跟踪进度

每一项需要执行的按目标 / 按设置的操作都必须有独立的任务,以保证透明性。

  • 阶段 1(简报)是一个任务,当用户选择 Begin audit / Cancel 时完成。
  • 阶段 3 为每个目标创建一个任务(Audit <target>);一旦阶段 3 既生成了按目标的审计表行,又(对于受支持的产品类型)生成了该目标的 Enhanced-Security 类别,该任务即关闭。阶段 3 将所有按目标的状态存储在任务的 description 字段中(格式见阶段 3 步骤 4),以便后续阶段可以通过 TaskGet 读回。阶段 4–7 读取这些任务描述。
  • 阶段 4(计划与批准)是一个任务,当用户选择 Run/Cancel 时完成。
  • 在 Run 时,阶段 4 步骤 5 解析计划并创建细粒度任务。对于每个应用任务,它将该目标的增量(从对应的 Audit <target> 任务的 description 中提取)嵌入到应用任务自己的 description 中,这样阶段 5 就不必再次查找。
    • 对于每个被勾选的 Enhanced Security 子项:
      • Enable Enhanced Security:Enable Enhanced Security at project level(一个任务)。在仅含 pbxproj 的项目上,此任务封装了阶段 5 步骤 1a 中描述的引导并验证流程。
      • Update entitlements:每个需要更改的目标对应一个 Apply Enhanced Security entitlements to <target>。
      • Hardware memory tagging:Apply Hardware Memory Tagging(一个任务;在内部遍历受支持的目标)。
      • Checked pointer arithmetic:Apply Checked Pointer Arithmetic(一个任务;在内部遍历受支持的目标)。
    • 对于每个被勾选的 Warnings 子项:
      • 如果该子项被勾选,则 Apply Compiler Warnings。
      • 如果该子项被勾选,则 Apply Static Analyzer Warnings。
      • 如果该子项被勾选,则 Apply Clang-Tidy Warnings。
    • 如果被勾选,则 Apply Additional Diagnostic Settings。
    • 如果被勾选,则 Emit Bounds Safety Adoption guidance。
    • 每个阶段 6 候选项对应一个 Inquire about <MACRO> on <target>(仅当 "Inquire about disabled settings" 被勾选时)。
    • Report and update decision document。
    • Prompt to remove plan file —— 始终最后执行;在错误路径上也会触发。

进入每个阶段或子步骤时:

  • 用纯英文打印一行,指明阶段或子步骤的名称 —— 绝不打印阶段编号。使用阶段的名称(例如 "▶ Briefing"、"▶ Analyzing project"、"▶ Plan & Approve"、"▶ Applying settings");对于子步骤,指明正在进行的操作(例如 "▶ Detecting languages"、"▶ Building the audit table")。
  • 将任务更新为 in_progress。

完成每个阶段或子步骤时:

  • 打印一行:"✓ <相同标签>",如适用则附上简要结果(例如 "✓ Detecting languages: C and Swift found.")。
  • 将任务更新为 completed。

应用步骤可以在完成自己的任务之前,在其任务的 description 中记录所做的事情,每个目标一行。阶段 7 读取这些行,而不是重新推导状态或抓取先前的输出。

阶段 3:分析项目和设置

无用户交互。在后台收集事实。

步骤 1:定位现有的决策文档

XcodeGlob '**/xcode-security-settings.md'。如果找到,则 XcodeRead 它,并提取语言以及先前设置决策及其状态和理由。这为后续阶段提供依据。

第 2 步:检测语言

每种语言执行一次 XcodeGlob。结果为空并不代表失败——将该语言记为不存在。

  • **/*.c → C
  • **/*.cpp、**/*.cxx、**/*.cc → C++
  • **/*.m → Objective-C
  • **/*.mm → Objective-C++
  • **/*.swift → Swift

Objective-C++ 意味着 C++ 也存在。 .mm 文件包含 C++ 源代码,因此当检测到 Objective-C++ 时,任何以“存在 C++”为条件的审计(C++ 标准库加固、bounds-safe-buffers 指引、CLANG_ANALYZER_OSOBJECT_C_STYLE_CAST 等)都必须触发,即使不存在任何 .cpp/.cxx/.cc 文件。

文件扩展名并非权威依据。 Xcode 项目可以通过 project.pbxproj 中的 explicitFileType / lastKnownFileType 覆盖文件的编译语言——最常见的是将 .m 文件标记为 sourcecode.cpp.objcpp(按 Objective-C++ 编译),或将 .h 标记为 sourcecode.c.h / sourcecode.cpp.h。为捕获这些覆盖,请通过 Bash 执行 grep -E 'sourcecode\.cpp\.[a-zA-Z0-9]+' <project-root>/<ProjectName>.xcodeproj/project.pbxproj。project.pbxproj 是 .xcodeproj bundle 内 Xcode 的项目描述文件;请直接读取它。将任何 sourcecode.cpp.objcpp 匹配同时视为 Objective-C++ 和 C++;将任何其他 sourcecode.cpp.* 匹配视为 C++。

第 3 步:构建审计表

列定义、构建方法以及规范判定条件(“已加固”“默认关闭”“被有意禁用”)见 references/reading-build-settings.md。概览如下:

  1. 调用 XcodeListTargets 枚举 target。跳过 IS_AGGREGATE = true 的条目(它们没有 product type)。为每个剩余的 target 记录 TARGET_NAME、CONTAINING_PROJECT 和 PRODUCT_TYPE_IDENTIFIER——第 4 步直接按 PRODUCT_TYPE_IDENTIFIER 对 target 分类(不做推断)。
  2. 对每个 target:TaskCreate "Audit <target>",设为 in_progress。调用 GetTargetBuildSettings,对生成的 JSON 运行 scripts/filter_build_settings.py,并为每个被跟踪的宏记录 evaluatedValue 和 setAtTargetLevel(如果 JSON 中存在 targetValue 则为 yes)。将这些行保留好,准备在第 4 步写入任务的 description(连同分类一起)。让任务保持 in_progress——第 4 步会将其关闭。
  3. 使用过滤正则分两轮扫描显式设置:对 *.xcconfig 执行 XcodeGrep,并通过 Bash 执行 grep -nE '<filter regex>' <project-root>/<ProjectName>.xcodeproj/project.pbxproj。project.pbxproj 是 .xcodeproj bundle 内 Xcode 的项目描述文件;请直接读取它。为每个宏记录 numMatchesInXCConfigs、numMatchesInPbxproj 以及 file:line 引用。
  4. 审计表是连接后的视图:每个(target,被跟踪宏)对应一行。第 4、5、6 阶段都使用此表;不再重新获取其他内容。

此步骤的规模随 target 数量增长:每次 GetTargetBuildSettings 调用需要数秒,而每个 target 都要调用一次。在约有十个或更多 target 的项目上,这可能耗时几分钟。

第 4 步:各 target 的 Enhanced-Security 状态

根据第 3 步记录的 PRODUCT_TYPE_IDENTIFIER,将每个 target 归入以下三类之一:

  • 支持 Entitlements——product type 位于 references/enhanced-security.md 的 "Supported Product Types" 列表中(applications、XPC services、system extensions、driver extensions [仅构建设置]、tools)。读取该 target 的 CODE_SIGN_ENTITLEMENTS 构建设置中路径所指向的 entitlements plist,并将该 target 分类为 Up-to-date、Partial、Off 或 No-entitlements-file。多个 target 可以共享同一个 CODE_SIGN_ENTITLEMENTS 路径;请分别独立地对每个 target 分类。
  • Library/framework——product type 位于 references/universal-binaries-for-libraries.md 中列出的合格集合中(frameworks、static frameworks、static libraries、dynamic libraries)。不读取 entitlements。第 5 阶段将为这些检查 universal-binary 配置。
  • Skipped——其他任何类型(test bundles、app extensions 等)。 现在把 Phase 3 了解到的关于此目标的所有内容,通过 TaskUpdate 写入 Audit <target> 任务的 description,然后将其设为 completed。该 description 保存 Phase 4–6 稍后需要查阅的整个按目标状态。格式:
Category: <category> [/ <sub-state>]      # e.g. "Entitlements-supported / Partial", "Library/framework", "Skipped"
Entitlements path: <evaluated CODE_SIGN_ENTITLEMENTS>     # omit for Library/framework and Skipped
SDKROOT: <value>
SUPPORTED_PLATFORMS: <value>
Missing entitlements: <comma-separated short names>      # Entitlements-supported only; required and default-ON keys the target lacks; omit if empty
Checked pointer arithmetic: <eligible-entitlement | eligible-slice-only | enabled | not-eligible: <reason>>   # Entitlements-supported and Library/framework targets
Deliberately-disabled: <MACRO>=<value> (<source>[+<source>...]), ...   # one per disabled row; sources ⊆ {target-level, xcconfig, pbxproj} joined with '+' when more than one applies; omit the line entirely if none

Audit table:
  <MACRO>=<value> setAtTargetLevel=<yes|no> numMatchesInXCConfigs=<n> numMatchesInPbxproj=<n> matchLocations=<citations>
  ...

Category 行放在最前面,这样任何展示片段摘要的客户端都能显示有意义的内容。Audit-table 块是 Step 3 中的按 (target, tracked macro) 行,以 key=value 形式呈现——每个被跟踪的宏一行,使用 references/reading-build-settings.md 中定义的规范列名。matchLocations 以贯穿全文使用的相同 <source>:<file>:<line>[,<line>...] 格式携带 file:line 引用。Skipped 目标获得此 Category 行、平台字段以及 Audit-table 块。Library/framework 目标获得这三项,外加 Checked pointer arithmetic: 行。两者都立即完成(不读取 entitlements)。

Checked pointer arithmetic 是此功能的唯一事实来源。 在此处计算一次,并记录四个值之一。之后每个阶段都读取此行,不再自行做任何判断。

  • enabled —— 对此目标无需任何操作。对于 Entitlements-supported 目标:entitlements 文件带有 com.apple.security.hardened-process.checked-allocations.enforce-checked-pointer-arithmetic-overflow,且求值后的 ENABLE_HARDWARE_CHECKED_POINTER_ARITHMETIC_SLICE 为 YES。对于 Library/framework 目标:求值后的 ENABLE_HARDWARE_CHECKED_POINTER_ARITHMETIC_SLICE 为 YES —— 无需检查 entitlement。
  • not-eligible: <reason> —— 取以下之一:platform,当 SUPPORTED_PLATFORMS / SDKROOT 既不匹配 iphoneos 也不匹配 watchos 时;opted out,当 ENABLE_HARDWARE_CHECKED_POINTER_ARITHMETIC_SLICE 对该目标为 deliberately disabled 时;no arm64e,当 ENABLE_POINTER_AUTHENTICATION 为 deliberately disabled 时;或 outside the capability,当 ENABLE_ENHANCED_SECURITY 为 deliberately disabled 时。仅仅 at default OFF 的宏不构成理由 —— 启用 Enhanced Security 会解除它。outside the capability 仅适用于 Entitlements-supported 目标:该 capability 提供 entitlement,而 library 不获取任何 entitlement。
  • eligible-entitlement —— 一个 Entitlements-supported 目标,可以接受 checked pointer arithmetic 但尚未为其完全配置:它缺少 arm64e.x1 slice、checked-pointer-arithmetic entitlement,或两者皆缺。Step 4 应用缺失的那一项。
  • eligible-slice-only —— 一个 Library/framework 目标,可以接受 checked pointer arithmetic 但没有该 build setting。这些目标没有 entitlement 那一半:entitlements 是按进程从主可执行文件授予的,因此 library 构建 slice,而消费方 app 的 entitlement 才是执行检查的依据。Step 4 仅应用 build setting。

该 key 永远不会列在 Missing entitlements 下,后者只保留必需的且默认开启的 key,因此它无法使目标变为 Partial,也无法到达 Step 1b。

在大型项目中,这会遍历许多 .entitlements plist —— 如果 Step 3 耗时明显,这一步也会如此。

Phase 4:规划与批准

此阶段生成一份量身定制、可编辑的计划文件,用户在任何更改发生之前审阅它。一旦批准,Phase 5–7 将端到端运行,不再有进一步提示。

Step 1:源代码控制状态

源代码控制已在 Phase 1 中检查,且用户当时已接受了任何无源代码控制的状态。Phase 4 Step 3 使用记录的状态来决定是否在计划文件中包含 ⚠️ 块引用。

步骤 2:如果一切都已配置,则跳过

对 Audit <target> 任务执行 TaskList,并对每个任务执行 TaskGet。如果所有默认勾选的计划项都已处于其目标状态,则提前退出:

  • 每个 Enhanced-Security 类别(来自每个任务的 Category: 行)均为 Up-to-date 或 Skipped。
  • 没有任何任务的 Checked pointer arithmetic: 行显示为 eligible-entitlement 或 eligible-slice-only。
  • 每个相关的 Warnings 设置(编译器、静态分析器和 clang-tidy)在每个适用的目标上均为 already hardened(依据每个任务的 Audit 表格块)。
  • 没有任何任务的 Deliberately-disabled: 行会产生一行(在下方 Phase-6 排除项之后)。

可选的后续操作(Additional diagnostic settings、Bounds safety adoption)不会阻止提前退出。报告 "Everything in scope is already configured" 并退出;不要写入计划文件。

步骤 3:写入计划文件

通过 XcodeWrite 在 Xcode 工作区的根目录创建 xcode-security-audit-plan.md(路径:xcode-security-audit-plan.md,无父分组)。XcodeWrite 既会将文件写入磁盘上 <project-root>/ 之下,又会在项目中注册该文件,以便用户可以直接从 Xcode 的 Project Navigator 打开它。

仅包含适用于该项目的项(参见下方的省略规则)。使用此模板——替换 <…> 中的占位符:

# Xcode Security Audit — Plan
**Project:** <name> · <N> targets · languages: <list>
**Generated:** <YYYY-MM-DD>
> ⚠️ **No source control detected.** This skill modifies build settings and entitlements.
> Without source control (e.g., Git), rollback requires manual undo. Consider [setting up source control](doc://com.apple.documentation/documentation/xcode/configuring-your-xcode-project-to-use-source-control) before picking **Run**.
Edit the items below — set what steps to perform now, or leave them unchecked to defer them. Questions about any item, or want a more detailed plan? Just ask — I'll answer, and can expand this plan on the points you care about before you decide.
## Phases
- **Enhanced Security** — the project's runtime-protection bundle. Apply to: <target list>. (Group — check the sub-items below.)
  - [x] **[Enable Enhanced Security](doc://com.apple.documentation/documentation/Xcode/enabling-enhanced-security-for-your-app)** — sets `ENABLE_ENHANCED_SECURITY=YES` at the project level. (Your project doesn't use a project-level xcconfig — I'll walk you through enabling it in Xcode's Build Settings UI yourself, then verify by reading project file.)
  - [x] **[Update entitlements](doc://com.apple.documentation/documentation/BundleResources/Entitlements/com.apple.security.hardened-process)** — adds the hardened-process entitlement family per target (Memory Safety, Runtime Protections).
  - [x] **[Hardware memory tagging](doc://com.apple.documentation/documentation/BundleResources/Entitlements/com.apple.security.hardened-process.checked-allocations)** — adds the hardware memory tagging entitlement, in soft mode, on supported platforms (<target list filtered to MTE-supported platforms>).
  - [x] **[Checked pointer arithmetic](doc://com.apple.documentation/documentation/BundleResources/Entitlements/com.apple.security.hardened-process.checked-allocations.enforce-checked-pointer-arithmetic-overflow)** — adds the arm64e.x1 slice and the entitlement to enforce pointer-arithmetic overflow checking (<target list filtered to arm64e.x1-supported platforms>). Run time enforcement requires hardware memory tagging enabled. Latent pointer-arithmetic bugs will terminate the app on capable hardware.
- **[Warnings](doc://com.apple.documentation/documentation/Xcode/build-settings-reference)** — additional diagnostics on all C/C++/ObjC targets. (Group — check the sub-items below.)
  - [x] **Compiler warnings** — <N> settings promoting security-relevant compiler diagnostics (fire on every build).
  - [x] **Static analyzer warnings** — <N> security checkers (run during Build and analyze).
  - [x] **Clang-tidy warnings** — <N> clang-tidy-integrated checks (run during Build and analyze).
- [x] **Inquire about disabled settings** — <M> found (e.g., `<setting>=NO` on `<target>`). May trigger follow-up questions if no rationale is documented.
- [ ] **Additional diagnostic settings** — extra opt-in warnings/checkers beyond the defaults. Off by default: they surface more findings to review and can be noisier (more false positives).
- [ ] **[Bounds safety adoption](https://clang.llvm.org/docs/BoundsSafetyAdoptionGuide.html)** — pointer to a separate skill. No changes applied here.
## Decision document
The skill creates or updates `xcode-security-settings.md` to record every setting decision (kept, deferred, disabled, with rationale). Edit the path to relocate.
- Path: `xcode-security-settings.md`

仅当项目没有源代码控制时才包含 ⚠️ 引用块;否则省略。

仅当项目仅为 pbxproj(Phase 3 的项目级扫描未发现任何 *.xcconfig 文件)时,才在 Enable Enhanced Security 子项末尾包含括号内的说明;否则省略。

决策文档应与其余文档位于同一目录中,或位于项目层级。

项省略规则

当某一计划项不适用时,将其完全省略:

  • Enhanced Security —— 仅当 Phase 3 步骤 4 中每个受支持产品类型类别均为 Up-to-date 或 Skipped,且没有任何任务的 Checked pointer arithmetic: 行显示为 eligible-entitlement 或 eligible-slice-only 时才省略(连同所有子项)。否则必须启用 Enhanced Security。
  • Enable Enhanced Security(子项)—— 当显示 Enhanced Security 时永不省略;仅末尾的 pbxproj-only 括号说明是有条件部分。
  • Update entitlements(子项)—— 当显示 Enhanced Security 时永不省略。
  • Hardware memory tagging(子项)—— 如果没有任何目标的 SUPPORTED_PLATFORMS / SDKROOT 匹配 macosx、iphoneos、iphonesimulator、watchos、xros 或 xrsimulator,则省略。
  • Checked pointer arithmetic(子项)—— 如果没有任何任务的 Checked pointer arithmetic: 行显示为 eligible-entitlement 或 eligible-slice-only,则省略。
  • Warnings —— 如果是纯 Swift,或者三个组中的所有设置在每个适用目标上均为 already hardened,则省略父项(及所有三个子项)。否则,当某一组(Compiler warnings、Static analyzer warnings 或 Clang-tidy warnings)中的所有设置在每个适用目标上均为 already hardened,或者该组对检测到的语言没有适用设置时,省略该单个子项。
  • Inquire about disabled settings —— 如果 deliberately disabled 谓词不产生任何行,则省略。
  • Additional diagnostic settings —— 永不省略;始终提供。
  • Bounds safety adoption —— 如果 Phase 3 步骤 2 未检测到任何 C、C++ 或 Objective-C++(将 sourcecode.cpp.* 覆盖计为 C++),则省略。
默认勾选状态

分组标题不带复选框。 带有子项的父级行——Enhanced Security 和 Warnings——只是普通的加粗分组标签,不是可勾选项;复选框由子项携带。这样可以避免出现父项已勾选、但其所有子项都未勾选这种含糊情况。其余每一项(包括没有子项的叶子项,如 Inquire about disabled settings、Additional diagnostic settings、Bounds safety adoption)都可勾选。

用户可以在选择 Run 之前编辑计划文件,以此切换 Phases 下的各项和子项。

第 4 步:请求批准

告诉用户:

“计划已写入 xcode-security-audit-plan.md 并添加到 Xcode 项目——打开它进行查看。按需编辑——取消勾选或删除条目即可跳过它们;编辑决策文档路径即可将其迁移。准备好后,选择 Run。选择 Cancel 可在不做任何更改的情况下中止。在你选择 Run 之前,不会修改任何内容。”

然后通过 AskUserQuestion 以单选选项询问:

  • Run — 继续进入“第 5 阶段”
  • Cancel — 中止
步骤 5:处理响应

如果用户提出问题或要求更多细节,而不是选择 Run/Cancel:请回答该问题,查阅 Bundled Reference Documents 中的相关文档(例如,关于额外诊断设置可查阅 references/additional-settings.md)。如果他们希望将这些细节记录下来,请通过 XcodeUpdate 更新 xcode-security-audit-plan.md 以详细说明这些要点。然后重新显示步骤 4 的审批提示——在用户选择 Run 之前,不会应用任何内容。

如果选择 Cancel:运行最终的清理任务(Prompt to remove plan file,见下文“阶段 7:报告与决策文档”)。在 Cancel 时也会提供保留或移除的提示,因此用户放弃审计的选择不会与正常完成时悄然不同。报告“已取消——未应用任何更改”,并退出该 skill。

如果在重新读取时计划文件缺失(用户在响应之前已将其从磁盘删除),则将其视为 Cancel——并跳过 Prompt to remove plan file 任务(没有任何内容需要移除)。

如果选择 Run:执行 XcodeRead xcode-security-audit-plan.md。解析:

  • 每个 - [x] 或 - [X] 列表项都是已勾选条目;条目名称是加粗部分(位于 **…** 之间)。
  • 带加粗但没有复选框的列表项(例如 - **Enhanced Security** …、- **Warnings** …)是分组标题,不是可勾选条目。它本身不会创建任何任务——由其已勾选的子条目驱动工作。不要将其视为已勾选或未勾选。
  • 写为 - [ ] 的条目以及从文件中删除的条目会被跳过——两者产生相同的跳过行为。
  • 在“Decision document”标题下,Path: 后面的值是决策文档位置。

创建 Track Progress 中列出的细粒度任务:

  • 对于每个 Apply Enhanced Security entitlements to <target> 任务,将相应 Audit <target> 任务描述中的按目标差异(Category:、Entitlements path:、Missing entitlements:)复制到 apply 任务自己的描述中,以便阶段 5 从一个地方读取。
  • Warnings 父行是标题,不是任务——它本身不会产生任何任务。每个已勾选的 Warnings 子条目会创建其对应的 apply 任务:Compiler warnings → Apply Compiler Warnings,Static analyzer warnings → Apply Static Analyzer Warnings,Clang-tidy warnings → Apply Clang-Tidy Warnings。这与 Enhanced Security 父项映射到其子条目任务的方式一致。
  • 要创建 Inquire about <MACRO> on <target> 任务(仅当 Inquire about disabled settings 被勾选时),对 Audit <target> 任务执行 TaskList,并对每个任务执行 TaskGet;每个描述的 Deliberately-disabled: 行列出了该目标的候选行。过滤时应用下文记录的阶段 6 排除项。
  • 创建 Report and update decision document 任务时,将解析出的决策文档路径放入其描述中,以便阶段 7 从那里读取。

如果解析出的计划中没有任何已勾选条目,请立即运行最终的清理任务并报告“计划为空——无事可做。”

阶段 5:应用设置

在需要时,从每个 Audit <target> 任务的描述(Audit 表格块)中读取构建设置状态;每个目标的 apply 状态来自每个 apply 任务自己的描述。

如何应用构建设置:

  • 项目使用 .xcconfig 文件——直接编辑 xcconfig。同时支持项目级和目标级设置。
  • 项目仅使用 .pbxproj——对于目标级设置,使用 UpdateTargetBuildSetting。请用户启用项目级设置。一旦用户回复已设置,请使用 grep 对项目文件验证其设置是否正确。
  • 混合——如果某个目标有 .xcconfig 文件,则编辑该 xcconfig。否则,使用 Xcode 构建设置工具。绝不要引入新的配置方法。

ENABLE_ENHANCED_SECURITY 必须在项目级设置,以便任何现有和未来的构建目标都继承此设置。 只有在经过认真考虑并有充分理由后,才应禁用此设置。

步骤 1:增强安全性

1a. 在项目级别启用增强安全性。 执行 Enable Enhanced Security at project level 任务。其中包含两条路径:

  • 项目使用项目级 xcconfig — 通过 XcodeUpdate 将 ENABLE_ENHANCED_SECURITY = YES 写入 xcconfig。将该任务标记为已完成。
  • 项目仅有 pbxproj — 任何 MCP 工具都无法直接写入项目级 pbxproj 设置,因此用户必须在 Xcode 中设置。给出以下确切步骤(每次重新展示时都逐字重复):"在 Xcode 中打开项目。在 Project Navigator 中选择项目(最顶部的条目,而不是某个 target)。前往 Build Settings,将范围切换为 All / Combined,搜索 ENABLE_ENHANCED_SECURITY,将项目级列(target 列的左侧)设置为 YES。保存。" 然后使用 AskUserQuestion 给出两个选项:我已启用 和 再次展示步骤。选择 我已启用 后,用 Bash 验证:grep -E 'ENABLE_ENHANCED_SECURITY *= *YES' <project-root>/<ProjectName>.xcodeproj/project.pbxproj。如果找到匹配项,将该任务标记为已完成。如果没有找到,不要继续:确认很可能是在实际未做更改的情况下被接受——误按了 Enter,或者忘记保存。明确说明这一点,逐字重新展示步骤,然后再次询问。循环执行——每次确认后重新运行 grep,只要仍未找到就重新展示步骤——直到 grep 找到 ENABLE_ENHANCED_SECURITY = YES。

1b. 更新增强安全性授权文件。 在阶段 4 步骤 5 中创建的细粒度 Apply Enhanced Security entitlements to <target> 任务已经列举了需要更改的 target(Partial、Off 和 No-entitlements-file 类别——Up-to-date 和 Skipped 被排除)。执行这些任务。

阅读 references/enhanced-security.md 了解完整的键列表、默认值和支持的产品类型列表。有关各个子选项的详细信息,请参阅:

  • references/pointer-authentication.md — arm64e 指针签名
  • references/typed-allocators.md — 类型感知内存分配
  • references/stack-zero-init.md — 自动栈变量清零
  • references/readonly-platform-memory.md — dyld 状态保护
  • references/runtime-restrictions.md — dylib 和 Mach 消息限制
  • references/security-compiler-warnings.md — 安全相关的编译器警告
  • references/cpp-hardening.md — C++ 标准库加固和边界检查
  • references/hardware-memory-tagging.md — ARM MTE
  • references/checked-pointer-arithmetic.md — 受检指针算术(CPA2)

指针认证与二进制依赖。 增强安全性是一组相互独立的保护措施;只有指针认证会级联到 arm64e。始终建议在项目级别设置 ENABLE_ENHANCED_SECURITY = YES。如果项目有一个二进制 Swift Package、xcframework 或预构建 framework 不提供 arm64e,正确的缓解措施是在所有链接该依赖项的 target 上以 target 级别覆盖 ENABLE_POINTER_AUTHENTICATION = NO——而不是跳过增强安全性。在报告中列出有问题的依赖项,以便用户可以向供应商要求 arm64e 支持,并在日后解除该覆盖。

arm64e.x1 是指针认证切片,因此在指针认证关闭的情况下不应构建它。不提供 arm64e 切片的二进制依赖项很可能也不提供 arm64e.x1。在每个获得 target 级别 ENABLE_POINTER_AUTHENTICATION = NO 的 target 上,还要设置 target 级别的 ENABLE_HARDWARE_CHECKED_POINTER_ARITHMETIC_SLICE = NO。步骤 4 会跳过这些 target,因此审计不会在那里添加受检指针算术授权。如果某个 target 已经在之前的配置中带有 com.apple.security.hardened-process.checked-allocations.enforce-checked-pointer-arithmetic-overflow,请报告它——构建时会警告:在没有 arm64e.x1 的情况下它不会生效。 生产方——以库/框架为目标的通用二进制文件。 强烈建议在库和框架目标上也启用指针认证——不要因为通用二进制文件在磁盘上体积更大就跳过它(RAM 占用和执行成本不变;dyld 只加载一个切片)。启用指针认证后已经会自动构建 arm64 和 arm64e 两个切片,因此无需显式设置 ARCHS。同样的理由也适用于受检指针算术,它需要追加 arm64e.x1 切片:只有当库提供该切片时,为 arm64e.x1 构建的使用方才能在库的代码上获得受检算术——使用方 App 还必须满足其他必要条件才能在运行时强制生效。第 4 步会将该构建设置应用到这些目标。参见 references/universal-binaries-for-libraries.md 和 references/checked-pointer-arithmetic.md。

对于每个任务:

  1. 根据此 apply 任务的描述(从审计任务复制过来的 Category: / Missing entitlements: 行)组合变更集。

    • 支持 Entitlements 的类别(Partial / Off / No-entitlements-file):通过 AddEntitlement 添加/更新 entitlements;如果缺少 .entitlements 则创建它,并配置 CODE_SIGN_ENTITLEMENTS。DriverKit 目标仅支持构建设置——对它们跳过 entitlement 更改。
    • 库/框架类别:不做 entitlement 工作,也不做构建设置更改——指针认证已经会自动生成两个切片。唯一要做的是下面第 2 项中的分发检查。
  2. 按目标设置构建设置。 ENABLE_ENHANCED_SECURITY = YES 已在项目级别设置(见上文第 1a 步),因此它会将 ENABLE_POINTER_AUTHENTICATION = YES 级联到每个目标。模拟器构建无需覆盖——构建系统会自动为模拟器 SDK 去掉 arm64e。唯一的按目标覆盖:对于每个链接了不提供 arm64e 的二进制依赖的目标,在目标级别无条件设置 ENABLE_POINTER_AUTHENTICATION = NO(该依赖在任何平台上都无法作为 arm64e 链接)。跳过已有显式目标级别值的目标(参见其 Audit <target> 任务中的审计表块)。

    对于每个指针认证最终会被启用的库/框架类别目标(该目标的平台支持 arm64e,且不存在已有的目标级别 ENABLE_POINTER_AUTHENTICATION = NO),无需更改构建设置——指针认证会自动追加 arm64e 切片。只需检查分发的构建是否同时生成 arm64 和 arm64e 切片:如果该目标在其 Release/分发配置中设置了 ONLY_ACTIVE_ARCH = YES,则在报告中警告使用方将获得单架构产物。

    不要自动启用默认关闭的子选项。硬件内存标记属于第 3 步,受检指针算术属于第 4 步。

  3. 按目标应用变更集:使用 AddEntitlement 添加或更新 entitlements(当目标没有 .entitlements 文件时创建它并配置 CODE_SIGN_ENTITLEMENTS);并应用构建设置更改。

处理完所有目标后,报告:"已在 N 个目标上启用 Enhanced Security。在 T 个链接了不含 arm64e 的二进制依赖的目标上添加了目标级别的 ENABLE_POINTER_AUTHENTICATION = NO。在 U 个库/框架目标上生成通用 arm64/arm64e 二进制文件。" 如果项目是仅含 pbxproj 且 Verify Enhanced Security at project level 成功,则追加:"Enhanced Security 已在项目级别启用(你在 Xcode 中设置的)。" 如果用户跳过了指南步骤,则追加:"本次运行未启用项目级别的 ENABLE_ENHANCED_SECURITY——在 Xcode 中启用后重新运行该技能。"

用户已在“Phase 4”中批准了此操作——无需进一步提示。

在多目标项目上,按目标的 Apply Enhanced Security entitlements 任务占据了 Phase-5 的大部分实际耗时。每个任务都会编辑该目标的 .entitlements plist。

第 2 步:警告

如果是纯 Swift,跳过整个步骤。本步骤涵盖三组,每组都以其各自的计划子项为前提 —— 编译器警告、静态分析器警告和 Clang-tidy 警告。跳过任何子项未勾选或已删除的组。对于每一项设置,查阅该 target 的 Audit <target> 任务描述(Audit 表块),并跳过其行标记为 already hardened 的个别设置。否则,应用 target 级别的设置(参见“如何应用构建设置”)。

编译器警告(每次构建都会触发):

  • GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR —— 非 void 函数在没有返回值的情况下返回属于未定义行为;调用方会读取返回寄存器中碰巧存在的任何内容。将其提升为错误可在编译时捕获此问题。YES_ERROR 是 Xcode 文档中记载的“将此特定警告视为错误”的值 —— 它不会把所有警告都变成错误。
  • GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE —— 读取未初始化的栈值会泄露先前栈帧的内容,并让攻击者利用残留数据控制执行流。激进模式会对更多情况发出警告(例如条件初始化路径)。
  • CLANG_WARN_IMPLICIT_FALLTHROUGH = YES —— 隐式 switch 贯穿是分支错误最常见的来源之一;该警告会在有意为之的情况下强制使用显式的 [[fallthrough]] / __attribute__((fallthrough))。
  • GCC_WARN_64_TO_32_BIT_CONVERSION = YES —— 将 size_t/指针静默窄化为 int 是整数截断漏洞的典型来源(长度检查在宽值上通过,随后在窄值上失败放行)。
  • GCC_TREAT_IMPLICIT_FUNCTION_DECLARATIONS_AS_ERRORS = YES(仅 C/ObjC)—— 隐式声明已在 C99 中移除,在现代 C 中会产生错误的调用约定和错误的返回类型假设。始终视为错误。

这两个 YES_ERROR / … ERRORS = YES 设置是有作用范围的:它们只将其自身特定的警告提升为错误,而非项目中的所有警告。

静态分析器警告(在 Build and analyze 期间运行,而非常规构建):

  • CLANG_ANALYZER_SECURITY_FLOATLOOPCOUNTER = YES —— 浮点循环计数器可能因舍入而停滞或超出预期;分析器会标记可能因此成为安全相关缺陷的循环。
  • CLANG_ANALYZER_SECURITY_INSECUREAPI_RAND = YES —— rand() / random() 是可预测的伪随机数生成器,不适合任何安全用途;分析器会标记其使用,以便调用方改用 arc4random_uniform 或 SecRandomCopyBytes。
  • CLANG_ANALYZER_SECURITY_INSECUREAPI_STRCPY = YES —— 标记 strcpy、strcat 及其同类函数,它们本质上不安全;调用方应改用有长度限制的变体(strlcpy、strlcat、snprintf)。

Clang-tidy 警告(clang-tidy 集成检查,属于 clang 静态分析器的一部分;它们仅在 Build and analyze / clang --analyze 期间触发,从不在常规构建中触发,因此没有破坏构建的风险,采用者也无需额外安装任何东西):

  • CLANG_TIDY_BUGPRONE_REDUNDANT_BRANCH_CONDITION = YES —— 标记与外围条件重复的分支条件,这通常是复制粘贴或逻辑错误的迹象。

按组简要报告,例如:“已启用编译器警告、静态分析器警告和 clang-tidy 警告。” —— 仅列出实际应用的组。

第 3 步:硬件内存标记

如果 硬件内存标记 子项(位于“增强安全性”下)未被勾选或已被删除,请跳过此步骤。

硬件内存标记仅支持 SUPPORTED_PLATFORMS(或 SDKROOT)为 macosx、iphoneos / iphonesimulator、watchos 或 xros / xrsimulator 的目标。 硬件支持需要搭载 A19 芯片或更新芯片的 iPhone 或 iPad、搭载 M5 芯片或更新芯片的 Mac 或 Apple Vision Pro,或搭载 S11 芯片或更新芯片的 Apple Watch。

阅读 references/hardware-memory-tagging.md,并对每个受支持的目标应用这两个键:com.apple.security.hardened-process.checked-allocations,以及其用于非致命发布的 soft-mode 子选项。仅软模式本身不起作用——它修改父键而非替换它。用户已在“第 4 阶段”中批准此项——无需进一步提示。

第 4 步:受检指针运算

在 Step 1 和 Step 3 中运行的步骤之后运行此步骤:它会读取 Step 1 可能更改的设置以及 Step 3 可能添加的授权。受检指针运算需要 arm64e.x1 切片,而此步骤仅在已构建带指针认证的 arm64e 切片的目标上启用该切片。运行时强制还要求同一目标上启用硬件内存标记。

如果 受检指针运算 子项未被勾选或已被删除,请跳过此步骤。

应用于每个 Checked pointer arithmetic: 行内容为 eligible-entitlement 或 eligible-slice-only 的目标;跳过其余目标。该行在第 3 阶段第 4 步中计算,是唯一的资格测试——不要在此处重新推导。

然后按目标检查以下条件,并重新读取每个值:Step 1 可能已更改构建设置,Step 3 可能已添加授权。当目标所受的任一条件不满足时,跳过该目标并报告。

  • ENABLE_ENHANCED_SECURITY 求值为 YES —— 仅限 eligible-entitlement 目标,因为该授权需要此能力。
  • ENABLE_POINTER_AUTHENTICATION 求值为 YES —— 两种目标均适用,因为 arm64e.x1 是指针认证切片。
  • 授权文件中存在 com.apple.security.hardened-process.checked-allocations —— 仅限 eligible-entitlement 目标,因为运行时强制依赖硬件内存标记。当 Step 3 未运行、跳过此目标,或 硬件内存标记 子项未被勾选时,该键不存在。

运行时强制需要运行 iOS 且搭载 A20 Pro 芯片或更新芯片的设备,或运行 watchOS 且搭载 S11 芯片或更新芯片的设备。

阅读 references/checked-pointer-arithmetic.md 并按目标应用。对于 eligible-entitlement 目标,应用两部分:在目标级别设置 ENABLE_HARDWARE_CHECKED_POINTER_ARITHMETIC_SLICE = YES(目标的 xcconfig,否则使用 UpdateTargetBuildSetting),并使用 AddEntitlement 添加 com.apple.security.hardened-process.checked-allocations.enforce-checked-pointer-arithmetic-overflow。两部分均为必需,因为仅切片不会强制受检指针运算,并且如果设置了授权而目标未构建 arm64e.x1,Xcode 会在构建时发出警告。对于 eligible-slice-only 目标,仅应用构建设置。

通过 TaskUpdate 在 Apply Checked Pointer Arithmetic 任务的 description 中记录每个目标的结果,每个目标一行,以便第 7 阶段(报告与决策文档)从一个位置读取:

<target>: applied | skipped: <reason>

对于从未符合资格的目标,使用 skipped: not eligible — <reason from the target's Checked pointer arithmetic: line>;对于符合资格但未通过上述重新读取的目标,使用 skipped: ENABLE_ENHANCED_SECURITY is <value>、skipped: ENABLE_POINTER_AUTHENTICATION is <value> 或 skipped: no hardware memory tagging entitlement。用户已在“第 4 阶段”中批准此项——无需进一步提示。

第 5 步:其他诊断设置

如果 Additional diagnostic settings 计划项未被勾选或已被删除,则跳过此步骤。

阅读 references/additional-settings.md 并按照其中的说明操作。用户已在“第 4 阶段”批准此项——无需再次询问。

第 6 步:边界安全采纳

如果 Bounds safety adoption 计划项未被勾选或已被删除,则跳过此步骤。

此步骤不会应用任何更改——它仅输出指引。

对于 C 项目(根据第 3 阶段第 2 步检测到存在 C),打印:

“要采纳 ENABLE_C_BOUNDS_SAFETY(基于注解的 C 边界安全),请调用 adopt-c-bounds-safety 技能。”

对于 C++ 项目(根据第 3 阶段第 2 步检测到存在 C++ 或 Objective-C++——包括对其他扩展名文件上的任何 sourcecode.cpp.* 覆盖),打印:

“要采纳 ENABLE_CPLUSPLUS_BOUNDS_SAFE_BUFFERS(C++ 边界安全缓冲区模式),请阅读 https://clang.llvm.org/docs/SafeBuffers.html 上的文档”

第 6 阶段:询问已禁用的设置

如果 Inquire about disabled settings 计划项未被勾选或已被删除,则跳过此阶段。

对于每个被刻意禁用但缺少书面理由的设置,此阶段会暂停并等待一次用户回复。如果候选列表很长,请提前告知数量,让用户心里有数(“我发现 7 个被刻意禁用的设置;让我逐一询问”)。

当 deliberately disabled 谓词(定义于 references/reading-build-settings.md)成立时,该行即为候选行。对 Audit <target> 任务执行 TaskList,并对每个任务执行 TaskGet;每个描述的 Deliberately-disabled: 行列出了该目标的候选行。标记无条件的 ENABLE_POINTER_AUTHENTICATION = NO,因为它会在设备构建中禁用指针认证。在 Checked pointer arithmetic: 行内容为 not-eligible: opted out 的目标上标记 ENABLE_HARDWARE_CHECKED_POINTER_ARITHMETIC_SLICE = NO——该原因意味着此选择退出是目标与 arm64e.x1 slice 之间的唯一障碍。对于其他 not-eligible 原因不要标记,因为在这些情况下该 slice 无论如何都无法构建。仅限于其 Scope(在 references/security-settings-reference.md 中)涵盖第 3 阶段第 2 步检测到的语言的设置;上述两个设置没有 Scope,因此无论语言如何都会标记。

对于每个候选设置,走查第 4 阶段第 5 步创建的对应 Inquire about <MACRO> on <target> 任务:

  • 如果决策文档中有一条状态为 Disabled 且带有理由的记录 → 在报告中注明并继续。
  • 否则 → AskUserQuestion:“我发现 <MACRO> 被显式设置为 NO 且没有解释。这有原因吗?”再次确认该宏是 deliberately disabled,而不仅仅是 Xcode 默认的 OFF——只应指出显式覆盖。记录理由(如果没有理由,则建议重新启用)。

同样的流程也适用于 ENABLE_ENHANCED_SECURITY = NO,如果它出现在任何任务的 Deliberately-disabled: 行中。

阶段 7:报告与决策文档

生成一份简洁的总结:

  1. 已启用 — 项目范围内已启用的设置。
  2. 各目标的安全增强 — 每个目标一行:名称、最终状态(已是最新 / 已应用 / 被用户跳过)、简短的变更(添加的 entitlements、是否创建了 entitlements 文件、该目标现在构建哪些架构切片、是否应用了受检指针算术)。将被跳过的目标汇总为一行。对于受检指针算术,TaskGet 获取 Apply Checked Pointer Arithmetic 任务,并使用其按目标的结​​果行,包括每次跳过的原因。
  3. 已处于活动状态 — 已正确配置的设置。
  4. 已询问 — 发现已禁用以及询问结果的设置。
  5. 测试你的应用 — 给用户的行动项:在支持所有已启用加固的真实硬件(而非模拟器)上进行测试,留意保护是否触发,并修复出现的崩溃和模拟崩溃报告。只有在对加固后的应用进行充分测试后,才能发布给客户——否则它可能在生产环境中崩溃或运行缓慢。特别是对于硬件内存标记,在禁用软模式以强制执行之前,先修复软模式产生的模拟崩溃报告。受检指针算术没有软模式,内存标记的软模式也不涵盖它,因此请在发布前在支持的硬件上进行测试:潜在的指针算术 bug 会终止应用。

决策文档。 TaskGet 获取 Report and update decision document 任务以读取决策文档路径。然后读取 references/decision-document.md 并遵照它在该路径创建或更新文档。

在阶段 7 之后——以及阶段 5–7 期间的任何错误路径上——将运行此最终任务:

  1. Prompt to remove plan file — 通过 AskUserQuestion 询问用户:“审计已完成。是否从你的项目中移除计划文件 xcode-security-audit-plan.md?”
    • 是,移除它(推荐) → XcodeRM xcode-security-audit-plan.md deleteFiles:true
    • 否,保留它 → 原地保留;它将留在 Project Navigator 中,作为已批准内容的记录。用户可以稍后从 Xcode 或 Finder 中删除它。

如果移除失败,警告用户,但不要阻止退出。

面向用户的交互准则

  • 保持回复简洁。 使用短句。
  • 使用完整句子表达。 不要使用短语片段。不要输出像“没有现成的决策文档。”这样的电报式名词短语——要写成完整的句子(“我没有找到现成的决策文档——我会在结尾创建一个。”)。
  • 阶段编号仅供内部使用。 绝不要在面向用户的叙述中提及阶段编号或步骤编号。直接描述结果:说“我不需要询问你关于已禁用设置的问题”,而不是“不会有第 6 阶段的询问问题”。这适用于叙述、状态行以及任何 AskUserQuestion 文本。
  • 不要使用技能内部术语。 不要在面向用户的叙述中使用“catalog”“audit table”之类的词——这些是技能内部的术语。用日常的 Xcode 术语描述正在发生的事情:“检查已知的安全构建设置”“目标列表”“我刚刚运行的分析”。
  • 将用户提问控制在最少。 三个计划内问题:“阶段 1”结尾的简报确认提示(开始审计 / 取消)、“阶段 4”结尾的计划批准提示(运行 / 取消),以及“阶段 7”结尾的保留或删除计划文件提示。其他问题视情况而定:在“阶段 6”中询问有意禁用的设置(仅当显式的 = NO 缺少文档化理由时),以及 Enable Enhanced Security at project level 确认提示(仅适用于仅含 pbxproj 的项目且勾选了该子项时)。
  • 报告进度,以便用户能够跟踪:“正在启用……”“正在评估……”“正在保留/还原……”
  • 使用 AskUserQuestion 进行简报确认(开始审计 / 取消)、计划批准(运行 / 取消)、在“阶段 6”中询问已禁用设置、阶段 5 步骤 1a 中的 Enable Enhanced Security at project level 确认(仅含 pbxproj),以及“阶段 7”结尾的保留或删除计划文件提示。
  • 提问时提供用户回答问题所需的背景信息。例如,在询问是否启用某项安全保护之前,先描述它的好处。要描述它提供的保护,而不是它如何被启用。
  • 在列出 Xcode 构建设置时,使用项目符号列表。不要使用逗号分隔的列表。

评论

支持 Markdown