capacitor-ios-security-hardening
Skill75 starsChanged 34 days agoMITView on GitHub
Audits and progressively hardens Xcode security build settings for a Capacitor iOS app (ios/App/App.xcodeproj, scheme App) and native plugin code (Swift/ObjC/C, Package.swift, podspec). Covers `xcodebuild -showBuildSettings -json`, security compiler warnings, static analyzer checkers (`xcodebuild analyze`), Xcode Enhanced Security (ENABLE_ENHANCED_SECURITY, com.apple.security.hardened-process entitlements, pointer authentication / arm64e, memory tagging soft mode), what is safe for a WKWebView hybrid app vs what breaks CocoaPods, SPM binary xcframeworks or Cordova plugins, staged adoption, and a decision log. Use for "harden my iOS build", "enable Enhanced Security", security build settings audit, arm64e link errors after enabling pointer authentication, or Build and Analyze setup. Do not use for ATS/TLS, signing, secrets or WebView rules (capacitor-security), or App Store review (capacitor-apple-review-preflight).
In this repository56 other files it gives its agents.
- AGENTS.mdAGENTS.md
- CLAUDE.mdCLAUDE.md
- capacitor-accessibilitySkill
- capacitor-app-intentsSkill
- capacitor-apple-review-preflightSkill
- capacitor-app-storeSkill
- capacitor-app-upgradesSkill
- capacitor-app-upgrade-v4-to-v5Skill
- capacitor-app-upgrade-v5-to-v6Skill
- capacitor-app-upgrade-v6-to-v7Skill
- capacitor-app-upgrade-v7-to-v8Skill
- capacitor-app-upgrade-v8-to-v9Skill
- capacitor-best-practicesSkill
- capacitor-ci-cdSkill
- capacitor-deep-linkingSkill
- capacitor-ios-resizabilitySkill
- capacitor-keyboardSkill
- capacitor-mcpSkill
- capacitor-offline-firstSkill
- capacitor-performanceSkill
- capacitor-plugin-spm-supportSkill
- capacitor-pluginsSkill
- capacitor-plugin-upgradesSkill
- capacitor-plugin-upgrade-v4-to-v5Skill
- capacitor-plugin-upgrade-v5-to-v6Skill
- capacitor-plugin-upgrade-v6-to-v7Skill
- capacitor-plugin-upgrade-v7-to-v8Skill
- capacitor-plugin-upgrade-v8-to-v9Skill
- capacitor-push-notificationsSkill
- capacitor-securitySkill
- capacitor-splash-screenSkill
- capacitor-testingSkill
- capacitor-uiscene-migrationSkill
- capawesome-live-update-migrationSkill
- capgo-cli-usageSkill
- capgo-cloudSkill
- capgo-live-updatesSkill
- capgo-native-buildsSkill
- capgo-organization-managementSkill
- capgo-release-managementSkill
- capgo-release-workflowsSkill
- cocoapods-to-spmSkill
- cordova-to-capacitorSkill
- debugging-capacitorSkill
- framework-to-capacitorSkill
- ionic-appflow-migrationSkill
- ionic-designSkill
- ionic-enterprise-sdk-migrationSkill
- ios-android-logsSkill
- konsta-uiSkill
- safe-area-handlingSkill
- skill-creatorSkill
- sqlite-to-fast-sqlSkill
- subscription-app-revenueSkill
- tailwind-capacitorSkill
- webapp-to-capacitorSkill
The file
We split this skill into the rules it gives an agent
11 rules. About 0 are common, 5 are distinctive, and 6 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈5
Distinctive · estimate
This author's own choices. Worth a look.
6
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 20
After enabling Enhanced Security, the link step fails with errors that mention arm64e
- Distinctive: line 42
Only load a reference when its topic is in play.
- Very specific: line 63
Read the Capacitor version from package.json (@capacitor/ios).
- Very specific: line 66
Look for an existing decision document (ios/xcode-security-settings.md or similar) and read prior decisions.
- Distinctive: line 67
Read evaluated settings for Debug and Release (see references/reading-build-settings.md):
- Very specific: line 74
Read the entitlements file at the evaluated CODE_SIGN_ENTITLEMENTS path.
- Distinctive: line 78
Write the plan into the chat (or a file the user names).
- Distinctive: line 89
Ask the user to approve, edit or cancel.
- Very specific: line 98
Add Enhanced Security through Signing & Capabilities > + Capability > Enhanced Security on the App target.
- Distinctive: line 99
After each stage, build (step 5) before starting the next one.
- Very specific: line 120
Run the app on a real device.
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Capacitor iOS Security Hardening
Audit the security-relevant Xcode build settings of a Capacitor app and its native plugins, then enable them in stages the user approves. This skill changes build settings and entitlements only. It never touches web code, ATS, signing, or secrets.
When to Use
TRIGGER when:
- The user wants to audit or harden the iOS build configuration of a Capacitor app
- The user asks about Enhanced Security,
ENABLE_ENHANCED_SECURITY, hardened-process entitlements, pointer authentication, arm64e, or memory tagging - After enabling Enhanced Security, the link step fails with errors that mention
arm64e - A plugin author wants stricter warnings or static analysis for plugin Swift/ObjC/C code
- The user wants "Build and Analyze" /
xcodebuild analyzein CI
Do not use:
- ATS, TLS pinning, signing, secrets, WebView config, Capsec scans:
capacitor-security - App Store privacy manifest and review checklist:
capacitor-apple-review-preflight - The AppDelegate to SceneDelegate migration:
capacitor-uiscene-migration - Android R8, network security config:
capacitor-security
Facts that change the plan
- Build settings do not cross project boundaries. Settings on the App target do not apply to Pods (
ios/App/Pods/Pods.xcodeproj), to SPM packages (plugins,CapApp-SPM), or to the Cordova plugin package thatnpx cap syncgenerates. Hardening plugin code is done in the plugin repo (podspec / Package.swift), not in the app. - The App target of a stock Capacitor app is pure Swift (
AppDelegate.swift,SceneDelegate.swift). Clang warnings and analyzer checkers only matter if the app target has.m,.mm,.cor.cppfiles. Detect languages before proposing them. - The Capacitor 8 templates already set three Stage A warnings at project level (
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR,GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE,GCC_WARN_64_TO_32_BIT_CONVERSION = YES). Report them as already hardened. Do not re-add them. - WKWebView content is not affected. JavaScript and JIT run in WebKit's own processes. Enhanced Security entitlements apply to the app process and the native code linked into it (Capacitor runtime, plugins, SDKs).
- Pointer authentication adds an
arm64eslice to device builds. Every binary linked into the app must also havearm64e, or the link fails. This is the main breakage risk in Capacitor apps. See references/enhanced-security.md. - Do not edit generated files.
ios/App/Pods/**,Pods-App.*.xcconfig,ios/App/CapApp-SPM/Package.swift,ios/capacitor-cordova-ios-plugins/**andios/debug.xcconfig(SPM template, Debug only, CLI-managed) are rewritten by CocoaPods ornpx cap sync. Put settings in the App project (Xcode Build Settings, which writesproject.pbxproj) or in an xcconfig the team already owns. - The user owns the result. Enhanced Security turns latent memory bugs into crashes. Report findings and get approval before changing anything. Test on real hardware before shipping.
References
Only load a reference when its topic is in play.
| File | Load when |
| references/settings-catalog.md | Building the audit table: every tracked setting, its hardened value, language scope, risk |
| references/reading-build-settings.md | Running xcodebuild -showBuildSettings, using the audit script, telling "explicitly disabled" from "default off" |
| references/enhanced-security.md | Enabling the Enhanced Security capability, entitlements, pointer authentication with CocoaPods/SPM/binary SDKs, memory tagging |
| references/plugin-authors.md | Hardening plugin code: podspec pod_target_xcconfig, Package.swift warning settings, analyzing a plugin repo, shipping arm64e xcframeworks |
| references/decision-log.md | Creating or updating the team's decision document |
Script: scripts/audit-build-settings.mjs filters xcodebuild -showBuildSettings -json output to the tracked settings and marks each as hardened, default, or explicitly set (when given the pbxproj).
Workflow
1. Brief and check source control
Tell the user in two or three sentences: you will audit first, write a plan, and change nothing until they approve. If the project has no git, recommend committing first. Stop if they decline.
2. Discover (read-only)
- Confirm the iOS project:
ios/App/App.xcodeprojexists. Note SPM (ios/App/CapApp-SPM/) vs CocoaPods (ios/App/Podfile,App.xcworkspace). - Read the Capacitor version from
package.json(@capacitor/ios). Capacitor 8 deploys to iOS 15, Capacitor 9 to iOS 16 and needs Xcode 27. - Detect languages in the App target folder:
find ios/App/App -name '*.m' -o -name '*.mm' -o -name '*.c' -o -name '*.cpp'. Also rungrep -E 'sourcecode\.cpp\.' ios/App/App.xcodeproj/project.pbxprojto catch files whose type was overridden to C++/ObjC++. - List native dependencies that ship binaries: xcframeworks in
node_modules/**/ios/**,binaryTargetin pluginPackage.swiftfiles,vendored_frameworksin podspecs. - Look for an existing decision document (
ios/xcode-security-settings.mdor similar) and read prior decisions. - Read evaluated settings for Debug and Release (see references/reading-build-settings.md):
xcodebuild -showBuildSettings -json -project ios/App/App.xcodeproj -target App -configuration Release > /tmp/app-release.json
node <skill>/scripts/audit-build-settings.mjs /tmp/app-release.json --pbxproj ios/App/App.xcodeproj/project.pbxproj- Read the entitlements file at the evaluated
CODE_SIGN_ENTITLEMENTSpath. The stock template has none; that is normal.
3. Build the plan and ask
Write the plan into the chat (or a file the user names). Group it by stage. Show only items that apply:
| Stage | Items | Default |
| A. Compiler warnings | The five security warnings, only if C/ObjC/C++ is present in the target | on |
| B. Static analyzer | The security checkers plus the clang-tidy check; analyzer runs only on Analyze, so no build risk | on |
| C. Enhanced Security | Capability at project level, entitlements on the App target, pointer authentication with the dependency plan | on, after the dependency check |
| D. Memory tagging | checked-allocations + soft-mode | off, offer |
| E. Extra diagnostics | The noisier warnings | off, offer |
| F. Disabled settings | Ask about each explicit = NO that has no documented reason | on |
Ask the user to approve, edit or cancel. Real judgement calls to put to the user:
- A binary SDK with no
arm64eslice: turn pointer authentication off on the App target (keeps the rest of Enhanced Security) or wait for the vendor. - CocoaPods: add a
post_installhook that enables pointer authentication on pod targets, or turn it off on the App target. - Memory tagging: only with a plan to test on capable hardware.
4. Apply, one stage at a time
- Apply settings at the project level of
App.xcodeprojso every target inherits them, unless the setting is per target (entitlements, pointer-authentication opt-out). - Best path: ask the user to set them in Xcode (project > Build Settings > All). Then verify with
greponproject.pbxproj. If you editproject.pbxprojyourself, edit only thebuildSettingsdictionaries of the project's own Debug and ReleaseXCBuildConfigurationentries (the ones listed by the PBXProjectbuildConfigurationList), keep theKEY = VALUE;syntax, and re-run-showBuildSettingsto confirm. - Add Enhanced Security through Signing & Capabilities > + Capability > Enhanced Security on the App target. This creates or updates
App.entitlementsand wiresCODE_SIGN_ENTITLEMENTS. Details: references/enhanced-security.md. - After each stage, build (step 5) before starting the next one. If a stage breaks the build, revert that stage, record why in the decision log, and continue.
5. Verify
# Sync, then build for a device (arm64e only exists for device SDKs)
npx cap sync ios
xcodebuild -project ios/App/App.xcodeproj -scheme App -configuration Release \
-destination 'generic/platform=iOS' CODE_SIGNING_ALLOWED=NO build
# CocoaPods projects: use -workspace ios/App/App.xcworkspace instead of -project
# Static analyzer
xcodebuild -project ios/App/App.xcodeproj -scheme App -configuration Debug \
-destination 'generic/platform=iOS Simulator' analyze
# Confirm the slices of the built app binary
lipo -archs ~/Library/Developer/Xcode/DerivedData/App-*/Build/Products/Release-iphoneos/App.app/App- Re-run the audit script. Every approved setting shows as hardened.
- Simulator builds keep working: simulator SDKs have no
arm64e, and the build system drops it. Do not add a simulator-only opt-out. - Run the app on a real device. Check launch, plugin calls, and the JS
pause/resumeevents. With memory tagging in soft mode, collect the simulated crash reports from Xcode Organizer or the device logs (ios-android-logs).
6. Report and record
Report: what was enabled, what was already hardened, what was skipped and why, which dependencies block arm64e, and the action item to test on hardware before release. Then update the decision document (references/decision-log.md).
Error Handling
| Symptom | Cause | Fix |
Link fails with messages that mention arm64e after enabling Enhanced Security | A pod, SPM package or xcframework was built without arm64e | Find it with lipo -archs. Source pods: post_install hook. SPM source packages: workspace setting iOSPackagesShouldBuildARM64e. Binary with no slice: ENABLE_POINTER_AUTHENTICATION = NO on the App target and ask the vendor. See references/enhanced-security.md |
Sandbox: rsync(...) deny(1) file-write-create in [CP] Embed Pods Frameworks | ENABLE_USER_SCRIPT_SANDBOXING = YES with CocoaPods script phases | Keep it NO on the App target while on CocoaPods, record the reason, revisit after the SPM migration (cocoapods-to-spm) |
| New warnings flood after Stage A | Warnings were off before | Fix real bugs first. If a warning is in generated or vendored code, keep it on and defer that code; never flip -Werror for the whole project |
Settings changed but -showBuildSettings shows the old value | Set on the wrong level, or a target-level value overrides the project | Check the target column in Xcode; remove the target override if it has no reason |
| App crashes at launch only on newer devices after memory tagging | Soft mode was turned off too early, or a native library has a memory bug | Re-enable soft mode, collect reports, fix or update the library (often bundled C code such as zip or SQLite) |
Edits vanished after npx cap sync or pod install | A generated file was edited | Move the setting to the App project or to the plugin's own podspec / Package.swift |
Related Skills
capacitor-security: ATS, signing, secrets, WebView and storage securitycocoapods-to-spm: SPM removes most pod-related hardening frictioncapacitor-plugin-spm-support: Package.swift layout for pluginsios-android-logs: capture crash and memory-tagging reports from devices
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

