
Ios Security
Implement and audit iOS app security—Keychain, CryptoKit, biometrics, ATS, and privacy manifests—before App Store submission.
Overview
ios-security is an agent skill most often used in Ship (also Build integrations) that guides Keychain, CryptoKit, biometrics, ATS, and privacy-manifest patterns for secure iOS apps.
Install
npx skills add https://github.com/dpearson2699/swift-ios-skills --skill ios-securityWhat is this skill?
- Keychain-only guidance for tokens and secrets—explicit ban on UserDefaults and Core Data for credentials
- CryptoKit, Secure Enclave, and LAContext patterns for Face ID and Touch ID
- App Transport Security, certificate pinning, and data protection class coverage
- Privacy manifest auditing and a dedicated review checklist plus common-mistakes section
- Dedicated review checklist section
- 11 major topic areas in contents (Keychain through References)
Adoption & trust: 1.1k installs on skills.sh; 713 GitHub stars; 3/3 security scanners passed (skills.sh audits).
What problem does it solve?
You are storing secrets in UserDefaults or skipping ATS and biometrics best practices and need a single Apple-native security playbook before release.
Who is it for?
Indie iOS developers adding login, payments, or health data who must pass App Review and resist common credential-storage mistakes.
Skip if: Server-side-only backends, Android-only projects, or teams that only need high-level threat modeling without Swift implementation detail.
When should I use this skill?
Implementing app security features, auditing privacy manifests, configuring App Transport Security, securing keychain access, adding biometric authentication, or encrypting sensitive data with CryptoKit.
What do I get? / Deliverables
You get implementable Swift patterns for Keychain, encryption, biometrics, and transport security plus a review checklist aligned with privacy manifests and secure coding.
- Secure Swift snippets for Keychain, CryptoKit, and LAContext
- ATS and pinning configuration guidance
- Security review checklist outcomes
Recommended Skills
Journey fit
Spans multiple journey phases - primary shelf plus alternate fits below.
Canonical shelf is Ship because the skill centers on hardening, transport security, and review checklists right before release, even though some APIs are written during Build. Security subphase matches ATS, certificate pinning, secure coding patterns, and privacy-manifest auditing rather than generic feature coding.
Where it fits
Wire biometric unlock and Keychain persistence when adding account login to a new SwiftUI app.
Run the review checklist and privacy-manifest notes before cutting a release candidate.
Confirm data-collection declarations match actual Keychain and networking behavior expected at App Review.
How it compares
Use as a focused iOS app-security skill package, not a generic OWASP web checklist or an MCP secrets broker.
Common Questions / FAQ
Who is ios-security for?
Solo and indie builders shipping SwiftUI or UIKit apps with Claude Code, Cursor, or similar agents who need Keychain, CryptoKit, and ATS guidance grounded in Apple APIs.
When should I use ios-security?
During Build when wiring auth and encrypted storage; during Ship when auditing privacy manifests, pinning certificates, and running the review checklist before TestFlight or App Store submit.
Is ios-security safe to install?
Review the Security Audits panel on this Prism page and inspect the skill source in your repo before granting filesystem or network access to your agent.
SKILL.md
READMESKILL.md - Ios Security
# iOS Security Guidance for handling sensitive data, authenticating users, encrypting correctly, and following Apple's security best practices on iOS. ## Contents - [Keychain Services](#keychain-services) - [Data Protection](#data-protection) - [CryptoKit](#cryptokit) - [Secure Enclave](#secure-enclave) - [Biometric Authentication](#biometric-authentication) - [App Transport Security (ATS)](#app-transport-security-ats) - [Certificate Pinning](#certificate-pinning) - [Secure Coding Patterns](#secure-coding-patterns) - [Privacy Manifests](#privacy-manifests) - [Common Mistakes](#common-mistakes) - [Review Checklist](#review-checklist) - [References](#references) ## Keychain Services The Keychain is the ONLY correct place to store sensitive data. Never store passwords, tokens, API keys, or secrets in UserDefaults, files, or Core Data. ### Storing Credentials ```swift func saveToKeychain(account: String, data: Data, service: String) throws { let query: [String: Any] = [ kSecClass as String: kSecClassGenericPassword, kSecAttrAccount as String: account, kSecAttrService as String: service, kSecValueData as String: data, kSecAttrAccessible as String: kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly ] let status = SecItemAdd(query as CFDictionary, nil) if status == errSecDuplicateItem { let updateQuery: [String: Any] = [ kSecClass as String: kSecClassGenericPassword, kSecAttrAccount as String: account, kSecAttrService as String: service ] let updates: [String: Any] = [kSecValueData as String: data] let updateStatus = SecItemUpdate(updateQuery as CFDictionary, updates as CFDictionary) guard updateStatus == errSecSuccess else { throw KeychainError.updateFailed(updateStatus) } } else if status != errSecSuccess { throw KeychainError.saveFailed(status) } } ``` ### Reading Credentials ```swift func readFromKeychain(account: String, service: String) throws -> Data { let query: [String: Any] = [ kSecClass as String: kSecClassGenericPassword, kSecAttrAccount as String: account, kSecAttrService as String: service, kSecReturnData as String: true, kSecMatchLimit as String: kSecMatchLimitOne ] var result: AnyObject? let status = SecItemCopyMatching(query as CFDictionary, &result) guard status == errSecSuccess, let data = result as? Data else { throw KeychainError.readFailed(status) } return data } ``` ### Deleting Credentials ```swift func deleteFromKeychain(account: String, service: String) throws { let query: [String: Any] = [ kSecClass as String: kSecClassGenericPassword, kSecAttrAccount as String: account, kSecAttrService as String: service ] let status = SecItemDelete(query as CFDictionary) guard status == errSecSuccess || status == errSecItemNotFound else { throw KeychainError.deleteFailed(status) } } ``` ### kSecAttrAccessible Values | Value | When Available | Device-Only | Use For | |---|---|---|---| | `kSecAttrAccessibleWhenUnlocked` | Device unlocked | No | General credentials | | `kSecAttrAccessibleWhenUnlockedThisDeviceOnly` | Device unlocked | Yes | Sensitive credentials | | `kSecAttrAccessibleAfterFirstUnlock` | After first unlock | No | Background-accessible tokens | | `kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly` | After f