
Audit Xcode Security Settings
- 272 installs
- 263 repo stars
- Updated June 9, 2026
- superagents-lab/xcode27-skills
audit-xcode-security-settings is a Claude Code skill that audits an Xcode project and progressively enables security-oriented build settings, static analysis, and Enhanced Security hardening.
About
This skill audits an Xcode project's security posture and progressively enables security-oriented build settings and entitlements for C, C++, Objective-C, and Swift targets. It turns on compiler warnings, static analyzer checkers, and Enhanced Security hardening features, then validates the applied settings and records decisions in a decision document. A developer uses it to harden an Apple app's build configuration and catch more bugs at compile time. It explicitly skips network security, code signing, and privacy APIs.
- Audits Xcode build settings for security posture
- Enables Enhanced Security hardening and static analyzer checkers
- Covers C, C++, Objective-C and Swift targets
- Records decisions in an xcode-security-settings decision document
- Skips network/TLS, code signing, and privacy APIs
Audit Xcode Security Settings by the numbers
- 272 all-time installs (skills.sh)
- +24 installs in the week ending Jul 27, 2026 (Skillselion tracking)
- Ranked #651 of 2,203 Security skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
audit-xcode-security-settings capabilities & compatibility
Free skill; requires Xcode and an Apple-platform project.
- Capabilities
- xcode security audit · build settings hardening · static analysis setup · entitlements configuration
- Use cases
- security audit
- Platforms
- macOS
- IDEs
- visual studio
- Pricing
- Free
What audit-xcode-security-settings says it does
Audit and enable security-oriented Xcode build settings. Progressively enables compiler warnings, static analyzer checkers, and Enhanced Security features.
Assess an Xcode project's security posture and progressively enable security build settings and entitlements
SKIP: network security (TLS/ATS), code signing, privacy APIs.
npx skills add https://github.com/superagents-lab/xcode27-skills --skill audit-xcode-security-settingsAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 272 |
|---|---|
| repo stars | ★ 263 |
| Last updated | June 9, 2026 |
| Repository | superagents-lab/xcode27-skills ↗ |
Which Xcode compiler warnings, static analyzer checkers, and hardening entitlements should this project enable, and are they applied?
Auditing and enabling Xcode compiler warnings, static analysis, and Enhanced Security hardening for an Apple app.
Who is it for?
Apple-platform developers hardening an Xcode project's build configuration and static analysis coverage.
Skip if: Network/TLS/ATS work, code signing, or privacy API review, which the skill explicitly excludes.
When should I use this skill?
When a user wants to secure their Xcode project, audit security settings, enable hardening, or catch more bugs at compile time in C/C++/Objective-C/Swift.
What you get
Hardened build settings and entitlements applied per target, validated, and recorded in a decision document.
- Enabled security build settings and entitlements per target
- Validation of applied settings
- An xcode-security-settings decision document
By the numbers
- 6-phase workflow (Phase 0 Discovery through Phase 6 follow-ups)
- 14 reference documents bundled
Files
Audit Xcode Security Settings
Assess an Xcode project's security posture and progressively enable security build settings and entitlements — from broadly applicable warnings through Enhanced Security hardening.
Tool Preferences
When GetTargetBuildSettings writes its output to a saved file due to a token limit, see references/reading-build-settings.md for the schema and the filter script (scripts/filter_build_settings.py). Do not read the saved file linearly.
When XcodeGlob, XcodeGrep, XcodeRead, and XcodeLS tools are available, ALWAYS use them. Do not fall back to Bash filesystem tools (ls, find, cat, grep) to learn about the project. They trigger extra permission prompts and bypass project scoping.
- XcodeGlob for file discovery —
findis forbidden for files inside the project. - XcodeGrep for content search —
grep/rgis forbidden for files inside the project. - XcodeRead for file contents —
cat/Readis forbidden for files registered in the project. - XcodeLS for directory listing —
lsis forbidden for any path inside the project.
Project root and name are already in the system prompt context. Do NOT run ls to "verify" the project layout before starting. The system prompt already tells you the working directory and the project structure.
Empty XcodeGlob results are not a failure. The .xcodeproj and .xcworkspace are not indexed as files inside the Xcode project organization — XcodeGlob "**/*.xcodeproj" correctly returns 0 matches. Use the project name from system-prompt context instead. Do not fall back to filesystem ls/find.
Path translation between project-org and filesystem. XcodeGlob returns project-org-relative paths. To read or edit a file:
- Prefer
XcodeRead/XcodeUpdatewith the project-org path. - If that path is rejected (some on-disk files like
.entitlementsplists may not be navigable throughXcodeRead), translate to a filesystem absolute path by prepending the project root from system context. Do NOT usefindto discover the on-disk path.
Fall back to Bash only for operations the Xcode tools cannot do (e.g., plutil for plist editing, git operations).
Common Failure Modes
| Symptom | Cause | Correct Response |
|---|---|---|
XcodeGlob "**/*.xcodeproj" returns 0 matches | The .xcodeproj itself isn't a project-indexed file | Use the project name from system context; do not fall back to find or ls |
XcodeRead <project-org-path> fails for a config-type file (.entitlements, .xcsettings, .xcconfig) | Some on-disk artifacts aren't navigable via project paths | Translate to filesystem absolute path using the project root from system context, then use Read / Edit |
Workflow
Phase 0: Discovery
Read the system prompt context. It contains:
- The project root (working directory).
- The project name and structure (top-level files, packages).
- The active scheme.
Do not call ls, find, or any filesystem tool to re-discover this information.
Track Progress
Before starting Phase 1:
1. Print the workflow plan to the user as a visible bullet list (so non-verbose users can see what's coming):
Workflow:
- Phase 1: Analyze project and existing settings
- Phase 2: Apply settings
- Step 1: Enhanced Security
- Step 2: Basic Clang safety warnings
- Phase 3: Inquire about disabled settings
- Phase 4: Validate applied settings
- Phase 5: Report and update decision document
- Phase 6: Optional follow-ups
2. Call TaskCreate with the same items so verbose users get a tracker.
When entering each phase or sub-step:
- Print one line: "▶ Phase N: …" (or "▶ Phase 2 / Step 1: …" for sub-steps).
- Update the task to
in_progress.
When finishing each phase or sub-step:
- Print one line: "✓ Phase N: …" (with a brief outcome if applicable, e.g., "✓ Phase 3: No disabled settings found.").
- Update the task to
completed.
Phase 6 starts as a single task and a single line. When the user opts into a specific follow-up, print "▶ Phase 6 / <name>" at start and "✓ Phase 6 / <name>" at end, and create/update the corresponding sub-task.
Phase 1: Analyze Project and Settings
No user interaction. Gather facts silently. Prefer XcodeGlob, XcodeGrep, and XcodeRead over Bash equivalents when available (see Tool Preferences).
1. Find .xcodeproj or .xcworkspace via XcodeGlob (**/*.xcodeproj) or Glob. 2. Search for an existing decision document (**/xcode-security-settings.md) via XcodeGlob or Glob. If found, read it and extract: languages and all prior setting decisions with their statuses and rationale. This informs subsequent phases. 3. Detect languages present via XcodeGlob or Glob:
**/*.c→ C**/*.cpp,**/*.cxx,**/*.cc→ C++**/*.m→ Objective-C**/*.mm→ Objective-C++**/*.swift→ Swift
4. Enumerate targets and their entitlements files — for each target, record its product type, platform (via SDKROOT / SUPPORTED_PLATFORMS), and resolve CODE_SIGN_ENTITLEMENTS to the on-disk .entitlements path (per configuration if it varies). Phase 2 Step 1 needs this map. When using GetTargetBuildSettings, see references/reading-build-settings.md for the output schema and the recipe for handling large results.
Phase 2: Apply Settings
Apply settings progressively, from most applicable to least.
Check existing security settings. Grep pbxproj and xcconfig files for settings from the catalog (see references/settings-and-entitlements-catalog.md). Only apply settings that aren't already set. If everything is already enabled, tell the user and stop.
How to apply build settings:
- Project uses `.xcconfig` files — edit the xcconfig directly. Supports both project-level and target-level settings.
- Project uses `.pbxproj` only — use
UpdateTargetBuildSettingfor target-level settings andUpdateProjectBuildSettingfor project-level settings. - Mixed — if a target has an
.xcconfigfile, edit the xcconfig. Otherwise, use the Xcode build setting tools. Never introduce a new configuration method.
Prefer project-level when possible (less duplication). Fall back to target-level via UpdateTargetBuildSetting when the project doesn't use xcconfig.
Exception — `ENABLE_ENHANCED_SECURITY`: Must be set at project level. If the project uses xcconfig, set it there. Otherwise, use UpdateProjectBuildSetting.
Step 1: Enhanced Security — Audit entitlements + build settings, then propose per-target diffs
Read references/enhanced-security.md for the full key list, defaults, deprecated keys, version migration, and the supported product-type list. For details on individual sub-options, see:
references/pointer-authentication.md— arm64e pointer signingreferences/typed-allocators.md— type-aware memory allocationreferences/stack-zero-init.md— automatic stack variable zeroingreferences/readonly-platform-memory.md— dyld state protectionreferences/runtime-restrictions.md— dylib and Mach message restrictionsreferences/security-compiler-warnings.md— security-focused compiler warningsreferences/cpp-hardening.md— C++ stdlib hardening and bounds checkingreferences/hardware-memory-tagging.md— ARM MTE
1. Identify suported targets. From the target map gathered in Phase 1 step 4, skip any target whose product type isn't in the "Supported Product Types" list in references/enhanced-security.md. Remaining targets are "supported targets." Note: DriverKit targets are supported for build settings only — skip entitlement changes for them.
2. Audit each supported target. Gather build-setting values of ENABLE_ENHANCED_SECURITY and ENABLE_POINTER_AUTHENTICATION (check target-level, then project-level inherited). For non-DriverKit targets, also read the entitlements file and collect every key under com.apple.security.hardened-process*, including the deprecated keys. Compare against the required + default-ON keys in references/enhanced-security.md Part B and bucket each target:
- Up-to-date — nothing to do.
- Partial —
ENABLE_ENHANCED_SECURITYis YES, but missing default-ON sub-options, or has deprecated keys, or version"1"/ deprecated version key present. - Off —
ENABLE_ENHANCED_SECURITYis absent. - No entitlements file — target is supported but has no
.entitlementsfile yet. If the user confirms applying, one will be created (see Step 5).
IMPORTANT Do not enable pointer authentication if the project has any binary dependencies (such as frameworks, xcframeworks, Swift Packages) that are not in this project from source. If the project does have such dependencies, list them and recommend that the user reach out to the vendor of the dependencies for a Universal binary that includes both arm64 and arm64e.
3. Build the change set. For each Partial or Off supported target, compose entitlement changes in this order (omit empty sections):
- Add entitlements: missing required keys (
com.apple.security.hardened-process,...enhanced-security-version-string = "2") and missing default-ON sub-options (hardened-heap,dyld-ro,platform-restrictions-string = "2"). - Remove entitlements: deprecated keys (
...platform-restrictions,...enhanced-security-version). - Update entitlements: version string
"1"→"2"if present.
If a supported target has no `.entitlements` file, include creating one and wiring CODE_SIGN_ENTITLEMENTS in the change set.
Build settings: Follow "How to apply build settings" above. If the project uses xcconfig, set ENABLE_ENHANCED_SECURITY = YES at project level there. Otherwise, use UpdateProjectBuildSetting.
Because a project-level ENABLE_ENHANCED_SECURITY = YES cascades ENABLE_POINTER_AUTHENTICATION = YES to every target, pre-write a target-level ENABLE_POINTER_AUTHENTICATION = NO override on each target whose platform doesn't support arm64e (detect via SDKROOT / SUPPORTED_PLATFORMS). Skip if the target already has an explicit target-level value.
Do not auto-enable default-OFF sub-options (MTE family); report state and offer enablement in step 6 below.
4. Present and confirm. If every supported target is up-to-date, report that fact in one line and proceed to Step 2 (Basic Clang Safety Warnings) — do not ask an apply-confirmation when there is nothing to apply. Otherwise print the proposed list of targets to enable Enhanced Security on.
Then print a short summary of the benefits of enabling Enhanced Security in terms of the security protections it provides and code changes it may require.
Then ask once via AskUserQuestion: "Apply the Enhanced Security changes above?" Offer "Apply all", "Apply to a subset (choose targets)", "Skip Enhanced Security".
5. Apply.
- Target-level
ENABLE_POINTER_AUTHENTICATION = NOoverrides on non-arm64e-platform targets viaUpdateTargetBuildSetting. Skip targets where the user already has an explicit target-level value. - Edit existing per-target
.entitlementsplists directly — add required + default-ON keys, remove deprecated keys, migrate version-string"1"→"2"atomically. - For targets with no
.entitlementsfile, create one and wireCODE_SIGN_ENTITLEMENTSto it.
Report: "Enabled Enhanced Security on N target(s). Removed M deprecated entitlement(s). Upgraded version string to 2 on K target(s). Added arm64e override on T non-arm64e-platform target(s)."
6. Hardware memory tagging. Supported only for targets whose SUPPORTED_PLATFORMS (or SDKROOT) is macosx, iphoneos / iphonesimulator, or xros / xrsimulator. (Hardware backing is M5-class Apple silicon and later; tvOS, watchOS, and DriverKit targets are not supported.) Skip this step if Enhanced Security was not applied or if no modified target matches one of those platforms. Otherwise ask via AskUserQuestion: "Hardware memory tagging is available via com.apple.security.hardened-process.checked-allocations. Do you want to enable it?" If yes → read references/hardware-memory-tagging.md and apply it.
Step 2: Basic Clang Safety Warnings
For codebases with C, C++, Objective-C, and Objective-C++, apply without asking. For pure Swift codebases, skip this step. Skip settings already enabled. Unless annotated otherwise, all settings below apply to C/C++/ObjC/ObjC++.
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERRORGCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVECLANG_WARN_IMPLICIT_FALLTHROUGH = YESGCC_WARN_64_TO_32_BIT_CONVERSION = YESGCC_TREAT_IMPLICIT_FUNCTION_DECLARATIONS_AS_ERRORS = YES(C/ObjC/ObjC++ only)CLANG_ANALYZER_SECURITY_FLOATLOOPCOUNTER = YESCLANG_ANALYZER_SECURITY_INSECUREAPI_RAND = YESCLANG_ANALYZER_SECURITY_INSECUREAPI_STRCPY = YES
Report briefly: "Enabled additional compiler warnings."
Phase 3: Inquire about Disabled Settings
Grep pbxproj and xcconfig files for any build setting from references/settings-and-entitlements-catalog.md that is explicitly set to NO. Exclude ENABLE_POINTER_AUTHENTICATION = NO on targets whose platform doesn't support arm64e (the skill itself sets it there). Do flag ENABLE_POINTER_AUTHENTICATION = NO on arm64e-capable targets — that's a deliberate opt-out worth inquiring about. If no other disabled settings are found, skip this phase. Only consider settings relevant to the languages detected in Phase 1 — see the Scope column in the catalog.
For each disabled setting found, check whether it has an entry in the decision document with status Disabled and a rationale.
If there is a documented rationale in the decision document, note it in the report and move on. The rationale documents a prior decision that can be re-audited later.
If there is no entry in the decision document, ask the user:
"I found CLANG_ANALYZER_SECURITY_INSECUREAPI_RAND explicitly set to NO with no explanation. Is there a reason for this?"If the user provides a reason, accept it and record the rationale in the decision document so future audits can re-evaluate it. If no reason, recommend re-enabling.
This also applies to any setting the skill would normally enable, such as ENABLE_ENHANCED_SECURITY. If any is already explicitly set to NO, follow the same decision-document-check-then-inquire flow.
Phase 4: Validate Settings
For each target modified in Phase 2, use GetTargetBuildSettings to verify that every build setting applied appears with the expected value. If a setting is missing or has an unexpected value, flag it in the report as potentially unsupported by the current Xcode version. See references/reading-build-settings.md for the output schema and the recipe for handling large results.
Phase 5: Report and Decision Document
Produce a lean summary:
1. Enabled: List project-wide settings that were enabled. 2. Enhanced Security per target: For each supported target, one line: target name, final status (up-to-date / applied / skipped-by-user), and a terse delta (entitlements added, deprecated keys removed, version bumps, whether an entitlements file was created). Roll up targets skipped because the product type isn't supported into a single line rather than one per target. 3. Already active: List settings that were already configured correctly. 4. Inquired: Settings that were found disabled and the outcome of the inquiry.
Decision document. Read references/decision-document.md and follow it to create or update the decision document.
Phase 6: Optional Follow-up Steps
Offer these one at a time, in order. Each is a separate yes/no question — do not combine them into a single multi-choice prompt. For recommended adoption order and a decision matrix based on language mix, see references/adoption-strategy.md.
1. Additional settings. Ask via AskUserQuestion: "There are additional diagnostic settings that could find more issues but may also produce false positives. Want to enable them?" If yes → read references/additional-settings.md and follow it.
2. Bounds safety programming models (only if C or C++ code present). For C projects, ask: "Want to look into adopting ENABLE_C_BOUNDS_SAFETY? It's an annotation-based programming model for C bounds safety — invoke Xcode's bounds-safety skill to get started." For C++ projects, ask: "Want to look into adopting ENABLE_CPLUSPLUS_BOUNDS_SAFE_BUFFERS? It enables C++ bounds-safe buffer patterns — invoke Xcode's bounds-safety skill to get started."
User-Facing Interaction Guidelines
- Keep replies lean. Short sentences.
- Keep user questions minimal. Two scheduled questions: the Enhanced Security apply-confirmation and the hardware memory tagging offer. Other questions are situational: inquiries about deliberately-disabled settings (only when an explicit
= NOlacks a documented rationale) and the decision document location (first creation only). - Report progress so the user can track: "Enabling...", "Evaluating...", "Keeping/Reverting..."
- Use `AskUserQuestion` for inquiring about disabled settings, for the Enhanced Security apply-confirmation (including offering "apply to a subset"), and for the decision document location (first creation only).
- When asking a question provide context the user needs to answer the question. For example, describe the benefit of the security protection before asking whether to enable it. Describe it in terms of the protection it provides, not how it is enabled.
- When emitting lists of Xcode build settings, use bullet lists Don't use comma-separated lists.
Additional Settings
Additional diagnostic settings that can find more issues but may also produce false positives. These are applied only when the user opts in after the main audit.
Settings
CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = YESCLANG_ANALYZER_SECURITY_BUFFER_OVERFLOW_EXPERIMENTAL = YESCLANG_TIDY_BUGPRONE_REDUNDANT_BRANCH_CONDITION = YESCLANG_WARN_ASSIGN_ENUM = YESGCC_WARN_SIGN_COMPARE = YES
C++ / DriverKit / IOKit (only if C++ present):
CLANG_ANALYZER_OSOBJECT_C_STYLE_CAST = YES
Blocks (only if ObjC, ObjC++, or C with -fblocks present):
CLANG_WARN_COMPLETION_HANDLER_MISUSE = YES
ObjC-specific (only if ObjC/ObjC++ present):
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YESCLANG_WARN_OBJC_REPEATED_USE_OF_WEAK = YES
Procedure
Enable relevant settings based on languages used in the project. Record decisions in the decision document.
Adoption Strategy
A recommended order for validating and addressing Xcode Enhanced Security features, from lowest risk and effort to highest.
Adding the Enhanced Security capability enables all cascaded settings at once. The phases below represent the order in which to validate and fix issues — not separate enablement steps. Phase 1 features are zero-cost (nothing to fix for well-behaved code), Phase 2 may need minor code changes, and Phase 3 requires active annotation or rewriting.
Phase 1: Zero-Cost, No Code Changes
Start here. These features have no runtime cost and require no source code changes for well-behaved code.
| Feature | Why first | Reference |
|---|---|---|
| Security Compiler Warnings | Compile-time only. Zero runtime cost. Identifies real bugs. | security-compiler-warnings.md |
| Stack Zero Initialization | Transparent. Cannot cause crashes. Prevents info leaks. | stack-zero-init.md |
| Read-Only Platform Memory | No impact on well-behaved code. Blocks post-exploitation. | readonly-platform-memory.md |
Action: After enabling Enhanced Security, build and fix any new warnings. These features won't cause runtime issues.
Phase 2: Low-Effort Runtime Protections
Next, validate runtime protections that require minimal or no code changes for most apps.
| Feature | Effort | Reference |
|---|---|---|
| Runtime Restrictions | No changes if using XPC or no IPC. Review needed only for raw Mach IPC. | runtime-restrictions.md |
| Typed Allocators | No changes for standard malloc/free. Update custom allocator wrappers if present. | typed-allocators.md |
Action: Test thoroughly. If you use raw Mach IPC, read the Mach IPC conformance guide.
Phase 3: Annotation and Code Hardening
These features require active code changes — annotations, pointer type updates, or fixing unsafe patterns.
| Feature | Effort | Reference |
|---|---|---|
| Pointer Authentication | Add __ptrauth qualifiers to security-critical function/data pointers. Review pointer casts. | pointer-authentication.md |
| C++ Stdlib Hardening | Fix out-of-bounds container access and unsafe buffer operations. | cpp-hardening.md |
Action: Prioritize security-critical code paths first (parsers, network handlers, IPC).
Additionally, consider adopting C Bounds Safety (-fbounds-safety) as a complementary feature for C codebases — see Xcode's bounds-safety skill.
Phase 4: Hardware-Dependent Protections
These require specific hardware and OS versions.
| Feature | Requirement | Reference |
|---|---|---|
| Hardware Memory Tagging | iPhone 17 family, M5-based Macs/iPads/Vision Pro | hardware-memory-tagging.md |
Action: 1. Enable with soft mode first — this generates simulated crash reports without terminating the app 2. Deploy soft mode to internal testers 3. Review simulated crash reports and fix memory bugs 4. Disable soft mode for production enforcement
Decision Matrix
Use this to decide which features to prioritize based on your codebase:
| If your app... | Prioritize |
|---|---|
| Is pure Swift | Phase 1 + Runtime Restrictions + Read-Only Memory |
| Has C code | All of Phase 1-3, plus consider C Bounds Safety (separate skill) |
| Has C++ code | All of Phase 1-3, especially C++ Hardening |
| Processes untrusted input | All features, prioritize bounds checking and memory tagging |
| Uses Mach IPC | Review runtime restrictions carefully before enabling |
| Targets MTE-capable hardware (iPhone 17, M5 Macs/iPads/Vision Pro) | Consider hardware memory tagging (start with soft mode) |
| Is a DriverKit extension | All applicable features — elevated privilege means higher stakes |
General Principles
1. Enable Enhanced Security as a capability first — this turns on all cascaded features at once 2. Fix warnings before testing runtime protections — compiler warnings often reveal the same bugs that runtime protections would crash on 3. Test in soft mode before hard mode — applies to hardware memory tagging 4. Prioritize security-critical code — parsers, network handlers, IPC, auth logic 5. Don't skip testing — Enhanced Security features turn latent bugs into crashes, which is the point, but you want to find them before your users do
C++ Standard Library Hardening and Bounds Checking
Enables safety checks in the C++ standard library and compiler-enforced bounds checking for unsafe buffer operations.
What It Does
Two protections in one setting:
1. C++ Standard Library Hardening (Fast Mode)
Enables assertion checks in standard library container types:
- Valid element access — checks that elements exist before accessing them (applies to all containers including
std::functionandstd::optional) - Valid input range — checks that ranges passed to standard algorithms are valid (begin iterator can reach the sentinel)
These checks run in constant time. If an assertion fails, the system crashes the app.
2. Unsafe Buffer Usage Warnings (as Errors)
The compiler reports errors when it detects:
- Indexing an array, performing pointer arithmetic, or using unsafe C stdlib functions on raw pointers
- Calling
operator[]()on a smart pointer referring to a list of objects - Constructing
std::spanwith a two-argument (pointer + size) constructor
What Vulnerabilities It Mitigates
- Out-of-bounds container access — accessing elements beyond container size
- Iterator invalidation — using invalid or dangling iterators
- Unsafe buffer access — raw pointer arithmetic and indexing without bounds
- Span construction errors — creating spans with incorrect size parameters
How to Enable
Build setting: ENABLE_CPLUSPLUS_BOUNDS_SAFE_BUFFERS = Yes
This enables both protections described above (hardened libc++ and unsafe buffer usage warnings).
Relationship to Enhanced Security: ENABLE_ENHANCED_SECURITY = YES cascades the hardened libc++ portion only (via CLANG_CXX_STANDARD_LIBRARY_HARDENING). It does NOT enable unsafe buffer usage warnings. ENABLE_CPLUSPLUS_BOUNDS_SAFE_BUFFERS is the superset — it enables both the hardened libc++ and the compiler warnings — and must be enabled separately if you want both.
Hardening Modes
You can override the mode per-file by defining _LIBCPP_HARDENING_MODE before any standard library includes:
| Macro Value | Mode | Checks |
|---|---|---|
_LIBCPP_HARDENING_MODE_NONE | None | No checks |
_LIBCPP_HARDENING_MODE_FAST | Fast (default) | Constant-time checks only |
_LIBCPP_HARDENING_MODE_EXTENSIVE | Extensive | Additional non-constant-time checks |
_LIBCPP_HARDENING_MODE_DEBUG | Debug | All checks including debug-only assertions |
// At the very top of the file, before any includes
#define _LIBCPP_HARDENING_MODE _LIBCPP_HARDENING_MODE_EXTENSIVE
#include <vector>For more information, see Hardening Modes in the LLVM documentation.
Code Changes Required
- Fix hardening assertion failures (e.g., accessing
std::vectorout of bounds, using invalidated iterators) - Replace unsafe raw pointer operations with safe alternatives (e.g., use
std::spanwith range constructors,std::array, or iterator-based access) - Fix
std::spanconstruction to use safe constructors
How to Disable
Build setting: ENABLE_CPLUSPLUS_BOUNDS_SAFE_BUFFERS = No
Platform Availability
- iOS, iPadOS, macOS, visionOS
- Available on all supported hardware
Performance and Stability Impact
- Performance: Low. Fast mode checks are constant-time. The overhead is typically negligible for most applications.
- Stability: Code with latent out-of-bounds access bugs will crash. Test with the Debug hardening mode during development to catch issues early.
Decision Document
Maintain a persistent xcode-security-settings.md that records every setting considered, its status, and the rationale. This file is version-controlled and serves as the single source of truth for security build setting decisions.
Step 1: Locate or Create the File
The skill searches for an existing xcode-security-settings.md early in the workflow. If found, its path is known.
1. If the file was already found, use that path. Skip to Step 2. 2. If not found, explain the value of tracking these decisions: "I'd like to create a decision document that records which security settings were enabled, disabled, or deferred, and why. This helps future audits build on past decisions instead of re-evaluating from scratch." Then ask via AskUserQuestion: "Where should I place it?" Options: "Project root (next to .xcodeproj)", "docs/ subdirectory", or let the user type a custom path. 3. Create the file with the initial structure (see Document Structure below). 4. Add the file to the Xcode project
Step 2: Merge Decisions
If an existing document was found, its content is already known. Preserve all user-added content, custom notes, and section organization.
For each setting considered in this run:
- New entry (setting not in document) — add to the appropriate section.
- Status unchanged — leave the entry untouched.
- Status changed (e.g., moved from Deferred to Enabled) — move the entry to the correct section. Preserve the old rationale as context (e.g., "Previously deferred because too noisy. Now enabled after codebase cleanup.").
Never remove entries. The document is append/update only.
All settings must be recorded in this document — it is the single source of truth for security build setting decisions.
Sections:
- Enabled settings — settings that are active.
- Disabled settings — settings the team decided not to adopt. Always include rationale explaining why.
- Deferred — settings considered but not yet enabled. Always include rationale explaining what would need to change.
Step 3: Write the File
Write the merged document. Report the path: "Decision document updated at <path>."
Document Structure
Use this layout for new files. If the file already exists, follow its existing style.
# Xcode Security Settings
Security build settings decisions for [ProjectName].
## Enabled settings
- `GCC_WARN_ABOUT_RETURN_TYPE` to `YES_ERROR`
- `GCC_WARN_UNINITIALIZED_AUTOS` to `YES_AGGRESSIVE`
- `ENABLE_ENHANCED_SECURITY`
## Disabled settings
- `GCC_WARN_SIGN_COMPARE`: A lot of `for` loops trigger this.
The team decided to not adopt this warning because it would involve too many changes.
## Deferred
Settings considered but not yet enabled. Revisit them later.
- `CLANG_WARN_ASSIGN_ENUM`: The findings seem relevant.
- `CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION`:
Too noisy with current generated code.
Revisit after generated code is excluded from analysis.
- `ENABLE_C_BOUNDS_SAFETY`:
Requires annotation-based programming model.
It needs careful adoption planning.Entry format: "- SETTING_NAME [to VALUE]: Rationale"
Omit the to VALUE part for settings that are enabled, unless we have some relevant rationale to state. For example, if the setting was disabled in the past, we can mention that and why it was enabled now. Usually, disabled settings or deferred settings need explanation.
Enhanced Security
Enhanced Security is an Xcode capability, not just a build setting. Enabling it fully touches two places per target:
1. Build settings (in pbxproj or xcconfig) — ENABLE_ENHANCED_SECURITY + pointer authentication. 2. Entitlements (in the target's .entitlements file) — the runtime-protection keys.
ENABLE_ENHANCED_SECURITY = YES is the build setting that turns on the compiler-driven pieces. The com.apple.security.hardened-process entitlement family turns on the runtime-driven pieces and is what actually provisions the capability.
Supported Product Types
Enhanced Security only applies on iOS, macOS, visionOS, and DriverKit, to these product types. Skip any target whose product type isn't in this list (frameworks, test bundles, app extensions other than those below, etc.) or whose platform isn't one of those four.
com.apple.product-type.applicationcom.apple.product-type.application.on-demand-install-capablecom.apple.product-type.xpc-servicecom.apple.product-type.driver-extension(build settings only — entitlements do not apply to DriverKit)com.apple.product-type.system-extensioncom.apple.product-type.tool
Part A — Build Settings
Two settings the audit needs to resolve to YES on every supported target:
ENABLE_ENHANCED_SECURITY = YES— listed in the capability'srequiredValues. Cascades automatically to pointer authentication, stack zero init, security compiler warnings, typed allocators, and C++ stdlib hardening (the audit does not manipulate these cascaded settings directly).ENABLE_POINTER_AUTHENTICATION = YES— builds for arm64e. Listed in the capability'sbuildSettingKeysRequiredForAllTargets.
Both should be set at project level. The apply path:
1. Set ENABLE_ENHANCED_SECURITY = YES at project level. If the project uses xcconfig, set it there. Otherwise, use UpdateProjectBuildSetting. 2. For each target whose platform doesn't support arm64e, pre-write a target-level ENABLE_POINTER_AUTHENTICATION = NO override via UpdateTargetBuildSetting so the project-level cascade doesn't break those builds. See pointer-authentication.md for the full list of supported and unsupported platforms. Skip if the target already has an explicit target-level value — respect existing user intent.
Part B — Entitlements
All keys live in the target's .entitlements file. Each supported target has its own; the audit walks every one.
Required when the capability is enabled:
com.apple.security.hardened-process = <true/>— the main toggle. Without this, the runtime protections below are inert.com.apple.security.hardened-process.enhanced-security-version-string = "2"— selects v2 protections.
Default-ON sub-options (the audit adds these when missing):
com.apple.security.hardened-process.hardened-heap— Memory Safety category. Adds extra type-isolation buckets to the allocator at runtime, regardless of compiler settings. Most effective in combination with the cascadedCLANG_ENABLE_C_TYPED_ALLOCATOR_SUPPORT/CLANG_ENABLE_CPLUSPLUS_TYPED_ALLOCATOR_SUPPORTbuild settings, which communicate type information from the compiler to the allocator.com.apple.security.hardened-process.dyld-ro— Runtime Protections. Marks dyld state read-only.com.apple.security.hardened-process.platform-restrictions-string = "2"— Runtime Protections. Dyld + Mach messaging restrictions.
Default-OFF sub-options (audit reports state, does not auto-enable):
com.apple.security.hardened-process.checked-allocationsand its related keys — Hardware Memory Tagging (MTE). Seehardware-memory-tagging.mdfor supported hardware. Recommend soft-mode rollout when reporting state.
Deprecated — the audit removes these if present alongside hardened-process = true:
com.apple.security.hardened-process.platform-restrictions— superseded by the-stringvariant.com.apple.security.hardened-process.enhanced-security-version— superseded by the-version-stringvariant.
Version migration: when hardened-process = true AND either ...version-string = "1" OR the deprecated ...enhanced-security-version key is present, set ...version-string = "2" and delete the deprecated key. If ...version-string is simply absent (no deprecated key either), it's just a missing required entitlement — add "2" via the normal add-entitlements step, not via this migration path.
Settings implied by Enhanced Security
These are automatically configured when ENABLE_ENHANCED_SECURITY = YES and do not need to be set explicitly:
GCC_WARN_SHADOW—-Wshadow, detects variable declarations that shadow other variables.CLANG_WARN_EMPTY_BODY—-Wempty-body, detects empty bodies in control flow statements.ENABLE_SECURITY_COMPILER_WARNINGS— enables additional security-focused warnings (-Wbuiltin-memcpy-chk-size,-Wformat-nonliteral,-Warray-bounds, etc.). Seesecurity-compiler-warnings.md.CLANG_CXX_STANDARD_LIBRARY_HARDENING— set tofastin Release builds anddebugin Debug builds (the cascade handles per-configuration differentiation automatically). This enables the hardened libc++ runtime checks only. It does NOT enable unsafe buffer usage warnings — that requiresENABLE_CPLUSPLUS_BOUNDS_SAFE_BUFFERSseparately (seecpp-hardening.md).CLANG_ENABLE_C_TYPED_ALLOCATOR_SUPPORT— communicates type information from the compiler to the allocator for C code. Works in combination with thehardened-heapentitlement (see below).CLANG_ENABLE_CPLUSPLUS_TYPED_ALLOCATOR_SUPPORT— same, for C++ code.
Settings NOT covered by Enhanced Security
These must be set independently and are out of scope for this reference:
- All
CLANG_ANALYZER_SECURITY_*checkers - Additional
CLANG_WARN_*/GCC_WARN_*diagnostics not flipped by Enhanced Security (e.g.CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION,GCC_WARN_ABOUT_RETURN_TYPE) GCC_TREAT_IMPLICIT_FUNCTION_DECLARATIONS_AS_ERRORS,CLANG_TIDY_*ENABLE_C_BOUNDS_SAFETY/ENABLE_CPLUSPLUS_BOUNDS_SAFE_BUFFERS(defensive programming models, separate adoption)
Hardware Memory Tagging
Hardware memory tagging (Memory Integrity Enforcement) uses ARM Memory Tagging Extension (MTE) to detect use-after-free and out-of-bounds memory access at runtime.
What It Does
Each memory allocation and pointer receives an embedded tag value. When your app accesses memory through a pointer, the hardware checks that the pointer's tag matches the allocation's tag. If the tags don't match — because of a use-after-free, buffer overflow, or other memory corruption — the app crashes instead of performing the unsafe access.
What Vulnerabilities It Mitigates
- Use-after-free — accessing memory after it has been freed (the freed memory gets a new tag)
- Heap buffer overflow — accessing memory beyond the allocated region (adjacent allocations have different tags)
- Out-of-bounds access — reading or writing past array boundaries
- Double-free — freeing memory that has already been freed
How to Enable
Xcode UI: Signing & Capabilities > Enhanced Security > Memory Safety > click "Enable Hardware Memory Tagging"
Entitlement: com.apple.security.hardened-process.checked-allocations
Soft Mode.
Soft mode produces simulated crashes (crash reports) instead of actually terminating the app. Use this to find memory bugs without impacting users.
Entitlement: com.apple.security.hardened-process.checked-allocations.soft-mode
Soft mode is enabled by default when you first enable hardware memory tagging. After reviewing crash reports and fixing issues, disable soft mode for enforcement.
Xcode UI: Under Memory Safety, deselect "Enable Soft Mode for Memory Tagging"
Debugging Diagnostics
For detailed diagnostics during development, navigate to Scheme Editor > Run > Diagnostics > enable "Hardware Memory Tagging".
Additional Entitlements
com.apple.security.hardened-process.checked-allocations.enable-pure-data— extends tagging to pure data allocationscom.apple.security.hardened-process.checked-allocations.no-tagged-receive— prevents receiving tagged pointers from other processes
Code Changes Required
None for basic adoption. Hardware memory tagging is a runtime enforcement mechanism — no source code annotations are needed. However, code with latent memory bugs will safely abort (or produce simulated crash reports in soft mode).
How to Disable
Xcode UI: Under Memory Safety, deselect "Enable Hardware Memory Tagging"
Remove the com.apple.security.hardened-process.checked-allocations entitlement.
Platform Availability
- Hardware: Available on iPhone 17, iPhone 17 Pro, iPhone 17 Pro Max, iPhone 17 Air, M5-based Macs, iPads, and Vision Pro — and subsequent releases.
Performance and Stability Impact
- Performance: Moderate overhead due to hardware tag checking on every memory access. Profile your app.
- Stability: Code with latent memory bugs will crash. Use soft mode first to identify and fix issues before enforcing.
- Adoption path: Enable soft mode > review simulated crash reports > fix memory bugs > disable soft mode for production.
Pointer Authentication
Pointer authentication protects against control-flow hijacking attacks by signing pointers with cryptographic metadata and verifying the signatures before use.
What It Does
When enabled, Xcode builds your app for the arm64e architecture and enables pointer authentication. The system:
1. Generates signature metadata for pointers your app creates (memory allocation, C++ object construction) 2. Validates that signatures are unchanged when your app accesses memory through those pointers 3. Crashes your app if a pointer's signature is invalid
This prevents an attacker from overwriting function pointers or return addresses to redirect your app's control flow.
What Vulnerabilities It Mitigates
- Control-flow hijacking — overwriting function pointers, vtable pointers, or return addresses
- ROP/JOP attacks — chaining existing code gadgets by corrupting pointer values
- Code injection via pointer corruption — modifying data pointers to point to attacker-controlled memory
How to Enable
Xcode UI: Signing & Capabilities > Enhanced Security > check "Authenticate Pointers"
Build setting: ENABLE_POINTER_AUTHENTICATION = Yes
This is enabled by default when you add the Enhanced Security capability.
For detailed usage, see Improving control flow integrity with pointer authentication.
How to Disable
Xcode UI: Uncheck "Authenticate Pointers" in the Enhanced Security capability
Build setting: ENABLE_POINTER_AUTHENTICATION = No
Swift Package Manager Support
Swift Package dependencies are not automatically built for arm64e when the main project enables pointer authentication. To build SPM packages with arm64e, set workspace-level flags in the project's embedded workspace settings.
For a .xcodeproj (which contains an implicit workspace at MyProject.xcodeproj/project.xcworkspace/):
plutil -create xml1 MyProject.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings
plutil -insert iOSPackagesShouldBuildARM64e -bool YES MyProject.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings
plutil -insert macOSPackagesShouldBuildARM64e -bool YES MyProject.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings
plutil -insert visionOSPackagesShouldBuildARM64e -bool YES MyProject.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettingsFor a standalone .xcworkspace:
plutil -create xml1 MyWorkspace.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings
plutil -insert iOSPackagesShouldBuildARM64e -bool YES MyWorkspace.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings
plutil -insert macOSPackagesShouldBuildARM64e -bool YES MyWorkspace.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings
plutil -insert visionOSPackagesShouldBuildARM64e -bool YES MyWorkspace.xcworkspace/xcshareddata/WorkspaceSettings.xcsettingsSet the flags for each platform your project targets.
For binary SPM dependencies (XCFrameworks), the XCFramework must include an arm64e slice. If it only contains arm64, linking will fail. Contact the dependency vendor for a universal (arm64 + arm64e) build.
Platform Availability
Platforms that support arm64e:
- iOS / iPadOS (SDKROOT:
iphoneos) - macOS (SDKROOT:
macosx) - visionOS (SDKROOT:
xros) - DriverKit (SDKROOT:
driverkit)
Platforms that do NOT support arm64e:
- watchOS (SDKROOT:
watchos) - tvOS (SDKROOT:
appletvos) - Simulator (any
*simulatorSDKROOT)
Requires arm64e-capable hardware (A12 chip or later, M1 or later).
When ENABLE_ENHANCED_SECURITY = YES cascades ENABLE_POINTER_AUTHENTICATION = YES project-wide, targets on non-arm64e platforms need an explicit target-level ENABLE_POINTER_AUTHENTICATION = NO override to prevent build failures. Detect via SDKROOT or SUPPORTED_PLATFORMS.
Performance and Stability Impact
- Performance: Low overhead. Pointer signing/verification is done in hardware.
- Stability: Code that manipulates raw pointers, casts between function pointer types, or uses inline assembly with pointers may crash. Test thoroughly.
- Compatibility: arm64e binaries are separate from arm64. Need to rebuild dependencies as arm64e. **If there are binary dependencies that you don't have the source code for, you will need to reach out to your dependency vendor to get a universal (arm64 and arm64e) version of the dependency.
Reading Build Settings
How to consume GetTargetBuildSettings output during a security audit.
Schema
GetTargetBuildSettings returns:
{ "buildSettings": [ { "macroName": "...", "evaluatedValue": "...", "value": "...", "targetValue": "..." }, ... ] }Field reference:
- `macroName` — setting name (always present).
- `evaluatedValue` — fully resolved value after
$(...)macro expansion. This is what the build actually sees. Use this for audit decisions. May be omitted when the resolved value is empty — treat its absence as an empty string. - `value` — raw, unexpanded value as written in the source (often missing).
- `targetValue` — present only when the setting is explicitly set at the target level (vs. inherited from project level). Use this to detect per-target overrides.
Handling large results
If GetTargetBuildSettings writes its output to a saved file due to a token limit, run scripts/filter_build_settings.py against that file to extract only catalog-relevant settings. Do not read the saved file linearly.
Filter recipes
The script lives at scripts/filter_build_settings.py (relative to the skill root). It derives its filter regex from references/settings-and-entitlements-catalog.md at runtime, so adding settings to the catalog automatically extends the filter. Override with --regex if you need a narrower filter.
Compact name=value view
python3 scripts/filter_build_settings.py <saved-file>With explicit target-override flag
python3 scripts/filter_build_settings.py <saved-file> --show-overridesOnly catalog settings NOT at a hardened value (the "what's left to do" view)
python3 scripts/filter_build_settings.py <saved-file> --unhardened-onlyThe --show-overrides and --unhardened-only flags can be combined.
Read-Only Platform Memory
Marks regions of memory used by the platform for internal state (such as the dynamic loader) as read-only, preventing tampering.
What It Does
Informs the system to mark memory regions in your process that the platform uses for its internal state as read-only. This primarily protects the dynamic loader (dyld) internal data structures from being modified by an attacker who has achieved code execution in your process.
What Vulnerabilities It Mitigates
- Dyld state tampering — an attacker modifying the dynamic loader's internal data to redirect library loading
- Runtime metadata corruption — overwriting platform-internal data structures to alter program behavior
- Post-exploitation persistence — modifying loader state to maintain control after initial exploitation
How to Enable
Xcode UI: Signing & Capabilities > Enhanced Security > check "Enable Read-Only Platform Memory"
Entitlement: com.apple.security.hardened-process.dyld-ro
Enabled by default when you add the Enhanced Security capability.
Code Changes Required
Usually none. In most applications, this entitlement requires no code changes.
The only exception: if your app modifies data in protected memory regions (for example, modifying the value of const data sections), the system will crash your app. Fix: remove the code that writes to read-only memory.
How to Disable
Xcode UI: Uncheck "Enable Read-Only Platform Memory" in the Enhanced Security capability
Platform Availability
- iOS, iPadOS, macOS, visionOS
- Available on all supported hardware
Performance and Stability Impact
- Performance: None. Memory is marked read-only at load time; no ongoing runtime checks.
- Stability: Unless your code writes to
constdata sections or platform-internal memory (which is already a bug), this has zero impact.
Why This Feature Is Low-Risk
Read-only platform memory is one of the safest Enhanced Security features:
- No runtime cost
- No code changes for well-behaved code
- Only crashes code that was already doing something wrong (writing to
constmemory) - Provides meaningful protection against post-exploitation techniques
Enable this early alongside compiler warnings and stack zero init.
Additional Run-time Restrictions
Adds runtime checks on dynamic libraries your app loads and Mach messages your app receives, preventing common code injection and privilege escalation attacks.
What It Does
Informs the system to perform additional checks on:
1. Dynamic libraries — validates libraries your app or extension loads at runtime 2. Mach messages — validates Mach messages your app or extension receives from other processes
Potentially insecure situations are turned into crashes rather than allowing an attacker to gain privileged access through Mach ports.
What Vulnerabilities It Mitigates
- Dylib injection — an attacker loading malicious dynamic libraries into your process
- Mach port attacks — exploiting Mach IPC to send crafted messages to your process
- Privilege escalation via IPC — using Mach messages to gain access to your app's privileges or data
How to Enable
Xcode UI: Signing & Capabilities > Enhanced Security > check "Enable Additional Runtime Platform Restrictions"
Entitlement: com.apple.security.hardened-process.platform-restrictions-string
Enabled by default when you add the Enhanced Security capability.
Code Changes Required
If your app uses XPC for IPC (and doesn't use raw Mach IPC traps): likely no code changes needed.
If your app uses raw Mach IPC traps: you may need to update your code. The runtime restrictions turn potentially insecure Mach messaging patterns into crashes. For details on what patterns to fix, see Conforming to Mach IPC security restrictions.
If your app has no explicit IPC mechanism: no code changes needed.
How to Disable
Xcode UI: Uncheck "Enable Additional Runtime Platform Restrictions" in the Enhanced Security capability
Platform Availability
- iOS, iPadOS, macOS, visionOS
- Available on all supported hardware
Performance and Stability Impact
- Performance: Negligible. The checks run at library load time and message receive time, not on every operation.
- Stability: Apps using XPC or no IPC are unaffected. Apps using raw Mach IPC may crash if they use insecure messaging patterns — review and fix these before enabling.
Decision Guide
| Your IPC approach | Impact | Action needed |
|---|---|---|
| No IPC | None | Safe to enable |
| XPC only | None | Safe to enable |
| Mach IPC via higher-level APIs | Low | Test, review for issues |
| Raw Mach IPC traps | Moderate | Read Mach IPC conformance guide, fix insecure patterns |
Security Compiler Warnings
Enhanced Security enables a set of compiler warnings that help identify potentially insecure C and C++ code patterns at build time.
What It Does
Enables two categories of compiler warnings:
Standard Warnings (always-on with Enhanced Security)
| Warning Flag | What It Detects |
|---|---|
-Wshadow | Variable declarations that shadow other variables or type aliases |
-Wempty-body | Empty bodies in control flow statements (if, for, while) |
Additional Security Warnings
Enabled via the ENABLE_SECURITY_COMPILER_WARNINGS build setting:
| Warning Flag | What It Detects |
|---|---|
-Wbuiltin-memcpy-chk-size | memcpy destination buffer smaller than copy size |
-Wformat-nonliteral | printf-style format string that isn't a string literal |
-Warray-bounds | Array index before beginning or past end of array; array argument smaller than function expects |
-Warray-bounds-pointer-arithmetic | Pointer arithmetic resulting in out-of-bounds pointer |
-Wsuspicious-memaccess | Suspicious memory operations: acting on vtable pointers, transposed memset args, non-trivially-copyable objects, zero-size operations |
-Wsizeof-array-div | Incorrect sizeof calculation for array element count due to wrong types |
-Wsizeof-pointer-div | sizeof returning pointer size instead of array size |
-Wreturn-stack-address | Returning address of a local (stack) variable to the caller |
What Vulnerabilities It Mitigates
- Buffer overflows —
memcpysize mismatches, array bounds violations - Format string attacks — non-literal format strings that an attacker could control
- Use-after-return — returning pointers to stack-allocated data
- Logic bugs — variable shadowing, empty control flow bodies, transposed arguments
How to Enable
Build settings:
-Wshadow:GCC_WARN_SHADOW = Yes-Wempty-body:CLANG_WARN_EMPTY_BODY = Yes- Additional security warnings:
ENABLE_SECURITY_COMPILER_WARNINGS = Yes
All are cascaded automatically when ENABLE_ENHANCED_SECURITY = YES — no manual setup needed if Enhanced Security is enabled.
Code Changes Required
Fix the warnings. Common fixes include:
- Rename shadowed variables
- Add bounds checks before array access
- Use string literals for format strings, or mark intentional non-literal formats with appropriate attributes
- Fix
sizeofcalculations to use the correct types - Remove or populate empty control flow bodies
How to Disable
-Wshadow:GCC_WARN_SHADOW = No-Wempty-body:CLANG_WARN_EMPTY_BODY = No- Additional security warnings:
ENABLE_SECURITY_COMPILER_WARNINGS = No
Platform Availability
- All platforms — these are compile-time checks with no runtime component
Performance and Stability Impact
- Performance: Zero runtime cost. These are compile-time warnings only.
- Stability: No runtime behavior change. Fixing the warnings improves code correctness.
Why This Feature Is Low-Risk
Security compiler warnings are the safest Enhanced Security feature:
- Zero runtime cost
- No behavior changes — only build-time diagnostics
- Warnings identify real bugs that should be fixed regardless of security posture
Enable this first, before any other Enhanced Security feature.
Settings and Entitlements Catalog
Complete catalog of security build settings and entitlements managed by this skill, organized by application order.
Language relevance: Only enable or inquire about a setting if the codebase contains code in a language the setting applies to. The Scope column indicates which languages each setting is relevant to. Do not enable clang-only settings for pure Swift codebases.
Filtering recipe. scripts/filter_build_settings.py filters GetTargetBuildSettings output to catalog entries; it derives its filter regex from this file at runtime by extracting backtick-quoted macro names. Adding a new setting to this catalog automatically extends the filter. See references/reading-build-settings.md for usage.
Basic Clang Safety Warnings — Always Enable
| Build Setting | Value | CLI Flag | Scope | Why Safe |
|---|---|---|---|---|
GCC_WARN_ABOUT_RETURN_TYPE | YES_ERROR | -Werror=return-type | C/C++/ObjC/ObjC++ | Missing returns are always bugs |
GCC_WARN_UNINITIALIZED_AUTOS | YES_AGGRESSIVE | -Wuninitialized -Wconditional-uninitialized | C/C++/ObjC/ObjC++ | Real bugs, rarely false |
CLANG_WARN_IMPLICIT_FALLTHROUGH | YES | -Wimplicit-fallthrough | C/C++/ObjC/ObjC++ | Catches logic bugs in switch |
GCC_WARN_64_TO_32_BIT_CONVERSION | YES | -Wshorten-64-to-32 | C/C++/ObjC/ObjC++ | Truncation is a real issue |
GCC_TREAT_IMPLICIT_FUNCTION_DECLARATIONS_AS_ERRORS | YES | -Werror=implicit-function-declaration | C/ObjC/ObjC++ | Implicit decls cause wrong return types |
CLANG_ANALYZER_SECURITY_FLOATLOOPCOUNTER | YES | checker: security.FloatLoopCounter | C/C++/ObjC/ObjC++ | Low false-positive rate |
CLANG_ANALYZER_SECURITY_INSECUREAPI_RAND | YES | checker: security.insecureAPI.rand | C/C++/ObjC/ObjC++ | Flags insecure random |
CLANG_ANALYZER_SECURITY_INSECUREAPI_STRCPY | YES | checker: security.insecureAPI.strcpy | C/C++/ObjC/ObjC++ | Flags unsafe string ops |
Enhanced Security — Capability
Build Settings
| Build Setting | Value | CLI Flag / Effect | Note |
|---|---|---|---|
ENABLE_ENHANCED_SECURITY | YES | Enables the Enhanced Security capability (build-setting + entitlements) | See enhanced-security.md |
ENABLE_POINTER_AUTHENTICATION | YES | Builds for arm64e pointer signing | Set at project level; override to NO on non-arm64e targets. NO is expected on unsupported platforms. |
Cascaded by `ENABLE_ENHANCED_SECURITY` (do not set manually):
| Build Setting | Value | Effect | Note |
|---|---|---|---|
GCC_WARN_SHADOW | YES | -Wshadow — variable declarations that shadow other variables | See security-compiler-warnings.md |
CLANG_WARN_EMPTY_BODY | YES | -Wempty-body — empty bodies in control flow statements | See security-compiler-warnings.md |
ENABLE_SECURITY_COMPILER_WARNINGS | YES | Enables additional security warnings (-Wformat-nonliteral, -Warray-bounds, etc.) | See security-compiler-warnings.md |
CLANG_CXX_STANDARD_LIBRARY_HARDENING | fast / debug | Hardened libc++ runtime checks (fast in Release, debug in Debug — cascade handles per-configuration automatically) | Does not include unsafe buffer warnings — see cpp-hardening.md |
CLANG_ENABLE_C_TYPED_ALLOCATOR_SUPPORT | YES | Communicates type information to the allocator for C code | Most effective with hardened-heap entitlement |
CLANG_ENABLE_CPLUSPLUS_TYPED_ALLOCATOR_SUPPORT | YES | Communicates type information to the allocator for C++ code | Most effective with hardened-heap entitlement |
Entitlements
These are managed per-target in each target's .entitlements file. See enhanced-security.md Part B for full details.
Required (always add when enabling Enhanced Security):
com.apple.security.hardened-process=<true/>— main toggle for runtime protectionscom.apple.security.hardened-process.enhanced-security-version-string="2"— selects v2 protections
Default-ON (add when missing):
com.apple.security.hardened-process.hardened-heap— adds type-isolation buckets to the allocator at runtime; most effective with the cascadedCLANG_ENABLE_C_TYPED_ALLOCATOR_SUPPORT/CLANG_ENABLE_CPLUSPLUS_TYPED_ALLOCATOR_SUPPORTbuild settings (Memory Safety)com.apple.security.hardened-process.dyld-ro— marks dyld state read-only (Runtime Protections)com.apple.security.hardened-process.platform-restrictions-string="2"— dyld + Mach messaging restrictions (Runtime Protections)
Default-OFF (report state, do not auto-enable):
com.apple.security.hardened-process.checked-allocations— hardware memory tagging (MTE)com.apple.security.hardened-process.checked-allocations.soft-mode— simulated crash reports without terminationcom.apple.security.hardened-process.checked-allocations.enable-pure-data— tag non-pointer heap allocationscom.apple.security.hardened-process.checked-allocations.no-tagged-receive— opt out of receiving tagged pointers via Mach IPC
Deprecated (remove if present):
com.apple.security.hardened-process.platform-restrictions— superseded by-stringvariantcom.apple.security.hardened-process.enhanced-security-version— superseded by-version-stringvariant
Additional Settings — Potentially More False Positives
| Build Setting | Value | CLI Flag | Scope | Note |
|---|---|---|---|---|
CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION | YES | -Wsuspicious-implicit-conversion | C/C++/ObjC/ObjC++ | May be noisy in some codebases |
CLANG_ANALYZER_SECURITY_BUFFER_OVERFLOW_EXPERIMENTAL | YES | checker: security.ArrayBound | C/C++/ObjC/ObjC++ | Higher false-positive rate |
CLANG_TIDY_BUGPRONE_REDUNDANT_BRANCH_CONDITION | YES | clang-tidy: bugprone-redundant-branch-condition | C/C++/ObjC/ObjC++ | Code quality |
CLANG_WARN_ASSIGN_ENUM | YES | -Wassign-enum | C/C++/ObjC/ObjC++ | Code quality |
GCC_WARN_SIGN_COMPARE | YES | -Wsign-compare | C/C++/ObjC/ObjC++ | Code quality |
C++ / DriverKit / IOKit (only if C++ present)
| Build Setting | Value | CLI Flag |
|---|---|---|
CLANG_ANALYZER_OSOBJECT_C_STYLE_CAST | YES | checker: optin.osx.OSObjectCStyleCast |
Blocks (only if ObjC, ObjC++, or C with -fblocks present)
| Build Setting | Value | CLI Flag |
|---|---|---|
CLANG_WARN_COMPLETION_HANDLER_MISUSE | YES | -Wcompletion-handler |
ObjC-Specific (only if ObjC/ObjC++ present)
| Build Setting | Value | CLI Flag |
|---|---|---|
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF | YES | -Wimplicit-retain-self |
CLANG_WARN_OBJC_REPEATED_USE_OF_WEAK | YES | -Warc-repeated-use-of-weak |
Not Auto-Enabled (Mentioned in Report)
| Setting | User-Facing Build Setting | Why Not Auto-Enabled |
|---|---|---|
| C bounds safety | ENABLE_C_BOUNDS_SAFETY | Requires annotations, changes language semantics |
| C++ unsafe buffer usage | ENABLE_CPLUSPLUS_BOUNDS_SAFE_BUFFERS | Requires rewriting buffer patterns |
| Hardware memory tagging | com.apple.security.hardened-process.checked-allocations | See hardware-memory-tagging.md for supported hardware |
Default-ON Security Checkers — Audit Only
These default to YES in Xcode. The skill does not actively enable them, but Phase 3 will flag them if explicitly set to NO.
| Build Setting | Value | What It Checks | Scope |
|---|---|---|---|
CLANG_ANALYZER_SECURITY_KEYCHAIN_API | YES | Improper Keychain API usage | C/C++/ObjC/ObjC++ |
CLANG_ANALYZER_SECURITY_INSECUREAPI_UNCHECKEDRETURN | YES | Unchecked return values from security APIs | C/C++/ObjC/ObjC++ |
CLANG_ANALYZER_SECURITY_INSECUREAPI_GETPW_GETS | YES | Use of insecure getpw() and gets() | C/C++/ObjC/ObjC++ |
CLANG_ANALYZER_SECURITY_INSECUREAPI_MKSTEMP | YES | Insecure use of mkstemp() / mktemp() | C/C++/ObjC/ObjC++ |
CLANG_ANALYZER_SECURITY_INSECUREAPI_VFORK | YES | Use of vfork() | C/C++/ObjC/ObjC++ |
GCC_WARN_TYPECHECK_CALLS_TO_PRINTF | YES | Format string type checking (-Wformat) | C/C++/ObjC/ObjC++ |
Stack Zero Initialization
Stack zero initialization automatically zeroes out stack variables when they are created, preventing information leaks from uninitialized memory.
What It Does
The compiler initializes all automatic (stack) variables in your code with zeroes. Without this, stack memory retains whatever values were left by previous function calls, which can leak sensitive data if a variable is used before explicit initialization.
What Vulnerabilities It Mitigates
- Information disclosure via uninitialized stack variables — reading sensitive data left on the stack from a previous function call
- Use-of-uninitialized-value bugs — using a variable before assigning it a value, leading to undefined behavior
- Stack-based exploitation — leveraging predictable uninitialized values to influence control flow
How to Enable
Build setting: CLANG_ENABLE_STACK_ZERO_INIT = Yes
This is enabled by default when you add the Enhanced Security capability.
Code Changes Required
None. This is a transparent compiler behavior change.
How to Disable
Build setting: CLANG_ENABLE_STACK_ZERO_INIT = No
Platform Availability
- iOS, iPadOS, macOS, visionOS
- Available on all supported hardware
Performance and Stability Impact
- Performance: Minimal. The compiler inserts zero-initialization instructions for stack variables. In most code paths this is negligible.
- Stability: This change can only improve stability. If your code relied on reading uninitialized stack values (a bug), the behavior changes — variables will now consistently be zero instead of containing garbage.
Why This Feature Is Low-Risk
Stack zero initialization is one of the safest Enhanced Security features to adopt:
- No source code changes required
- No new crash scenarios (zeroing memory cannot cause crashes)
- Minimal performance impact
- Catches a real class of security bugs
This should be one of the first features you enable.
Typed Allocators
Typed allocator support has two complementary pieces that can be enabled separately but are most effective in combination:
1. Entitlement (`com.apple.security.hardened-process.hardened-heap`) — adds extra type-isolation buckets to the allocator at runtime, regardless of compiler settings. This provides baseline type isolation. 2. Build settings (`CLANG_ENABLE_C_TYPED_ALLOCATOR_SUPPORT`, `CLANG_ENABLE_CPLUSPLUS_TYPED_ALLOCATOR_SUPPORT`) — the compiler communicates type information to the allocator, allowing it to do a better job isolating different types and improving protection against use-after-free vulnerabilities.
Both are enabled by default when you add the Enhanced Security capability (the entitlement as a default-ON sub-option, the build settings as cascaded settings).
What It Does
When the build settings are enabled, the compiler tracks the intended type of memory allocations. This means that malloc, calloc, and similar allocator functions produce pointers that carry type information. Combined with the hardened-heap entitlement's runtime type-isolation buckets, this makes it harder for an attacker to exploit type confusion vulnerabilities where memory allocated for one type is used as another.
What Vulnerabilities It Mitigates
- Type confusion — treating a pointer to type A as a pointer to type B after allocation
- Allocator-based exploitation — abusing custom allocator wrappers to bypass type safety
How to Enable
Xcode UI: Signing & Capabilities > Enhanced Security > check "Enable Typed Allocators"
Build settings:
- C code:
CLANG_ENABLE_C_TYPED_ALLOCATOR_SUPPORT = Yes - C++ code:
CLANG_ENABLE_CPLUSPLUS_TYPED_ALLOCATOR_SUPPORT = Yes
Entitlement: com.apple.security.hardened-process.hardened-heap
All are enabled by default when you add the Enhanced Security capability (build settings are cascaded by ENABLE_ENHANCED_SECURITY; entitlement is a default-ON sub-option).
Code Changes Required
If your code uses custom memory-allocator wrapper functions, you may need to update them to propagate type information. Standard malloc/free usage typically requires no changes.
For details on updating custom allocators, see Adopting type-aware memory allocation.
How to Disable
Build settings:
- C:
CLANG_ENABLE_C_TYPED_ALLOCATOR_SUPPORT = No - C++:
CLANG_ENABLE_CPLUSPLUS_TYPED_ALLOCATOR_SUPPORT = No
Xcode UI: Uncheck "Enable Typed Allocators" in the Enhanced Security capability.
Platform Availability
- iOS, iPadOS, macOS, visionOS
- Available on all supported hardware
Performance and Stability Impact
- Performance: Minimal overhead — type tracking is primarily a compile-time mechanism.
- Stability: Custom allocator wrappers may need updates. Standard allocator usage is unaffected.
#!/usr/bin/env python3
"""Filter GetTargetBuildSettings JSON to security-relevant entries.
Usage:
filter_build_settings.py <saved-file> [--show-overrides] [--unhardened-only] [--regex REGEX]
"""
import argparse
import json
import re
from pathlib import Path
CATALOG_PATH = (
Path(__file__).resolve().parent.parent
/ "references"
/ "settings-and-entitlements-catalog.md"
)
# Settings the script needs that aren't documented in the catalog as security
# settings but are required to interpret results (target type, SDK, etc.).
EXTRA_NAMES = ("CODE_SIGN_ENTITLEMENTS", "PRODUCT_TYPE", "SDKROOT", "SUPPORTED_PLATFORMS")
# Tokens inside backticks that look like build-setting macro names.
_NAME_RX = re.compile(r"`([A-Z][A-Z0-9_]{2,})`")
HARDENED_VALUES = {"YES", "YES_AGGRESSIVE", "YES_ERROR"}
def _load_catalog_names(path: Path) -> list[str]:
text = path.read_text()
names = set(_NAME_RX.findall(text))
names.update(EXTRA_NAMES)
# Longest-first so prefix-like names don't get shadowed in alternation.
return sorted(names, key=lambda n: (-len(n), n))
def _default_regex() -> str:
return "|".join(re.escape(n) for n in _load_catalog_names(CATALOG_PATH))
def main():
parser = argparse.ArgumentParser(description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter)
parser.add_argument("saved_file", help="Path to the saved GetTargetBuildSettings JSON")
parser.add_argument("--regex", default=None,
help="Override the catalog-derived default regex")
parser.add_argument("--show-overrides", action="store_true",
help="Annotate target-level overrides with [target-override]")
parser.add_argument("--unhardened-only", action="store_true",
help="Only show settings whose evaluatedValue is not YES/YES_AGGRESSIVE/YES_ERROR")
args = parser.parse_args()
rx = re.compile(args.regex if args.regex else _default_regex())
with open(args.saved_file) as f:
data = json.load(f)
for s in data["buildSettings"]:
name = s["macroName"]
val = s.get("evaluatedValue", "")
if not rx.search(name):
continue
if args.unhardened_only and val in HARDENED_VALUES:
continue
flag = " [target-override]" if args.show_overrides and "targetValue" in s else ""
print(f"{name}={val}{flag}")
if __name__ == "__main__":
main()
Related skills
FAQ
What does this skill actually change?
It progressively enables compiler warnings, static analyzer checkers, and Enhanced Security features and entitlements, then validates the applied settings and records decisions.
Which languages does it support?
It detects and applies settings for C, C++, Objective-C, Objective-C++, and Swift targets.
What does it not cover?
It explicitly skips network security (TLS/ATS), code signing, and privacy APIs.