Philosophy: Non-opinionated, correctness-focused. This skill provides facts, verified patterns, and Apple-documented best practices — not architecture mandates. It covers iOS 13+ as a minimum deployment target, with modern recommendations targeting iOS 17+ and forward-looking guidance through iOS 26 (post-quantum). Every code pattern is grounded in Apple documentation, DTS engineer posts (Quinn "The Eskimo!"), WWDC sessions, and OWASP MASTG — never from memory alone.
Works with
AI-first code editor with Composer
Before installing skills in Cursor, ensure your development environment meets these requirements:
node --versionswift-security-expertExecute the skills CLI command in your project's root directory to begin installation:
Fetches swift-security-expert from ivan-magda/swift-security-skill and configures it for Cursor.
The CLI shows a list of agents. Use arrow keys and space to select Cursor:
Confirm successful installation by checking the skill directory location:
Restart Cursor to activate swift-security-expert. Access via /swift-security-expert in your agent's command palette.
We perform automated surface-level scans (Gen AI Scanner, Socket, Snyk) during installation. These checks detect common vulnerabilities but do not guarantee complete security. Always review skill source code and verify the publisher's reputation before production use.
Skills execute code in your environment. Always review source, verify the publisher, and test in isolation before production.
Submit your Claude Code skill and start earning
Create detailed user stories, acceptance criteria, and feature specs
Example
Generate user stories for 'password reset feature' with acceptance criteria, edge cases, and test scenarios
Reduce spec writing time by 50%, ensure comprehensive coverage
Research competitors, compare features, identify gaps
Example
Analyze 5 competitor products, create feature comparison matrix, suggest differentiation opportunities
Complete competitive research in 2 hours instead of 2 days
Evaluate features using frameworks (RICE, ICE, Kano) and create prioritized backlogs
Example
Score 20 feature ideas using RICE framework, generate prioritized roadmap with rationale
1
total installs
1
this week
6
GitHub stars
0
upvotes
Run in your terminal
1
installs
1
this week
6
stars
Philosophy: Non-opinionated, correctness-focused. This skill provides facts, verified patterns, and Apple-documented best practices — not architecture mandates. It covers iOS 13+ as a minimum deployment target, with modern recommendations targeting iOS 17+ and forward-looking guidance through iOS 26 (post-quantum). Every code pattern is grounded in Apple documentation, DTS engineer posts (Quinn "The Eskimo!"), WWDC sessions, and OWASP MASTG — never from memory alone.
What this skill is: A reference for reviewing, improving, and implementing keychain operations, biometric authentication, CryptoKit cryptography, credential lifecycle management, certificate trust, and compliance mapping on Apple platforms.
What this skill is not: A networking guide, a server-side security reference, or an App Transport Security manual. TLS configuration, server certificate management, and backend auth architecture are out of scope except where they directly touch client-side keychain or trust APIs.
Determine the user's intent, then follow the matching branch. If ambiguous, ask.
┌─────────────────────┐
│ What is the task? │
└─────────┬───────────┘
┌──────────────────┼──────────────────┐
▼ ▼ ▼
┌─────────┐ ┌───────────┐ ┌────────────┐
│ REVIEW │ │ IMPROVE │ │ IMPLEMENT │
│ │ │ │ │ │
│ Audit │ │ Migrate / │ │ Build from │
│ existing│ │ modernize │ │ scratch │
│ code │ │ existing │ │ │
└────┬────┘ └─────┬─────┘ └─────┬──────┘
│ │ │
▼ ▼ ▼
Run Top-Level Identify gap Identify which
Review Checklist (legacy store? domain(s) apply,
(§ below) against wrong API? load reference
the code. missing auth?) file(s), follow
Flag each item Load migration + ✅ patterns.
as ✅ / ❌ / domain-specific Implement with
⚠️ N/A. reference files. add-or-update,
For each ❌, Follow ✅ patterns, proper error
cite the verify with domain handling, and
reference file checklist. correct access
and specific control from
section. the start.
Goal: Systematically evaluate existing keychain/security code for correctness, security, and compliance.
Procedure:
common-anti-patterns.md. Pay special attention to: UserDefaults for secrets (#1), hardcoded keys (#2), LAContext.evaluatePolicy() as sole auth gate (#3), ignored OSStatus (#4).compliance-owasp-mapping.md categories M1, M3, M9, M10.Key reference files for review:
common-anti-patterns.md (backbone — covers 10 most dangerous patterns)compliance-owasp-mapping.md (if compliance is relevant)Goal: Upgrade existing code from insecure storage, deprecated APIs, or legacy patterns to current best practices.
Procedure:
Identify the migration type:
migration-legacy-stores.md + credential-storage-patterns.mdcryptokit-symmetric.md or cryptokit-public-key.md + migration-legacy-stores.mdcryptokit-public-key.md (RSA migration section)keychain-item-classes.md (migration section)biometric-authentication.mdkeychain-fundamentals.md (TN3137 section)keychain-sharing.mdcertificate-trust.mdFollow the migration pattern in the relevant reference file. Every migration section includes: pre-migration validation, atomic migration step, legacy data secure deletion, post-migration verification.
Run the domain-specific checklist from the reference file after migration completes.
Verify no regressions using guidance from testing-security-code.md.
Goal: Build new keychain/security functionality correctly from the start.
Procedure:
testing-security-code.md — protocol-based abstraction for unit tests, real keychain for integration tests on device.Domain Selection Guide:
| If the task involves… | Load these reference files |
|---|---|
| Storing/reading a password or token | keychain-fundamentals.md + credential-storage-patterns.md |
Choosing which kSecClass to use |
keychain-item-classes.md |
| Setting when items are accessible | keychain-access-control.md |
| Face ID / Touch ID gating | biometric-authentication.md + keychain-access-control.md |
| Hardware-backed keys | secure-enclave.md |
| Encrypting / hashing data | cryptokit-symmetric.md |
| Signing / key exchange / HPKE | cryptokit-public-key.md |
| OAuth tokens / API keys / logout | credential-storage-patterns.md |
| Sharing between app and extension | keychain-sharing.md |
| TLS pinning / client certificates | certificate-trust.md |
| Replacing UserDefaults / plist secrets | migration-legacy-stores.md |
| Writing tests for security code | testing-security-code.md |
| Enterprise audit / OWASP compliance | compliance-owasp-mapping.md |
These seven rules are non-negotiable. Every keychain/security implementation must satisfy all of them.
1. Never ignore OSStatus. Every SecItem* call returns an OSStatus. Use an exhaustive switch covering at minimum: errSecSuccess, errSecDuplicateItem (-25299), errSecItemNotFound (-25300), errSecInteractionNotAllowed (-25308). Silently discarding the return value is the root cause of most keychain bugs. → keychain-fundamentals.md
2. Never use LAContext.evaluatePolicy() as a standalone auth gate. This returns a Bool that is trivially patchable at runtime via Frida. Biometric authentication must be keychain-bound: store the secret behind SecAccessControl with .biometryCurrentSet, then let the keychain prompt for Face ID/Touch ID during SecItemCopyMatching. The keychain handles authentication in the Secure Enclave — there is no Bool to patch. → biometric-authentication.md
3. Never store secrets in UserDefaults, Info.plist, .xcconfig, or NSCoding archives. These produce plaintext artifacts readable from unencrypted backups. The Keychain is the only Apple-sanctioned store for credentials. → credential-storage-patterns.md, common-anti-patterns.md
4. Never call SecItem* on @MainActor. Every keychain call is an IPC round-trip to securityd that blocks the calling thread. Use a dedicated actor (iOS 17+) or serial DispatchQueue (iOS 13–16) for all keychain access. → keychain-fundamentals.md
5. Always set kSecAttrAccessible explicitly. The system default (kSecAttrAccessibleWhenUnlocked) breaks all background operations and may not match your threat model. Choose the most restrictive class that satisfies your access pattern. For background tasks: kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly. For highest sensitivity: kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly. → keychain-access-control.md
6. Always use the add-or-update pattern. SecItemAdd followed by SecItemUpdate on errSecDuplicateItem. Never delete-then-add (creates a race window and destroys persistent references). Never call SecItemAdd without handling the duplicate case. → keychain-fundamentals.md
7. Always target the data protection keychain on macOS. Set kSecUseDataProtectionKeychain: true for every SecItem* call on macOS targets. Without it, queries silently route to the legacy file-based keychain which has different behavior, ignores unsupported attributes, and cannot use biometric protection or Secure Enclave keys. Mac Catalyst and iOS-on-Mac do this automatically. → keychain-fundamentals.md
| Constant | When Decryptable | Survives Backup | Survives Device Migration | Background Safe | Use When |
|---|---|---|---|---|---|
WhenPasscodeSetThisDeviceOnly |
Unlocked + passcode set | ❌ | ❌ | ❌ | Highest-security secrets; removed if passcode removed |
WhenUnlockedThisDeviceOnly |
Unlocked | ❌ | ❌ | ❌ | Device-bound secrets not needed in background |
WhenUnlocked |
Unlocked | ✅ | ✅ | ❌ | Syncable secrets (system default — avoid implicit use) |
AfterFirstUnlockThisDeviceOnly |
After first unlock → restart | ❌ | ❌ | ✅ | Background tasks, push handlers, device-bound |
AfterFirstUnlock |
After first unlock → restart | ✅ | ✅ | ✅ | Background tasks that must survive restore |
Deprecated (never use): kSecAttrAccessibleAlways, kSecAttrAccessibleAlwaysThisDeviceOnly — deprecated iOS 12.
Rule of thumb: Need background access (push handlers, background refresh)? Start with AfterFirstUnlockThisDeviceOnly. Foreground-only? Start with WhenUnlockedThisDeviceOnly. Tighten to WhenPasscodeSetThisDeviceOnly for high-value secrets. Use non-ThisDeviceOnly variants only when iCloud sync or backup migration is required.
| Need | Algorithm | Min iOS | Notes |
|---|---|---|---|
| Hash data | SHA256 / SHA384 / SHA512 |
13 | SHA3_256/SHA3_512 available iOS 18+ |
| Authenticate data (MAC) | HMAC<SHA256> |
13 | Always verify with constant-time comparison (built-in) |
| Encrypt data (authenticated) | AES.GCM |
13 | 256-bit key, 96-bit nonce, 128-bit tag. Never reuse nonce with same key |
| Encrypt data (mobile-optimized) | ChaChaPoly |
13 | Better on devices without AES-NI (older Apple Watch) |
| Sign data | P256.Signing / Curve25519.Signing |
13 | Use P256 for interop, Curve25519 for performance |
| Key agreement | P256.KeyAgreement / Curve25519.KeyAgreement |
13 | Always derive symmetric key via HKDF — never use raw shared secret |
| Hybrid public-key encryption | HPKE |
17 | Replaces manual ECDH+HKDF+AES-GCM chains |
| Hardware-backed signing | SecureEnclave.P256.Signing |
13 | P256 only; key never leaves hardware |
| Post-quantum key exchange | MLKEM768 |
26 | Formal verification (ML-KEM FIPS 203) |
| Post-quantum signing | MLDSA65 |
26 | Formal verification (ML-DSA FIPS 204) |
| Password → key derivation | PBKDF2 (via CommonCrypto) |
13 | ≥600,000 iterations SHA-256 (OWASP 2024) |
| Key → key derivation | HKDF<SHA256> |
13 | Extract-then-expand; always use info parameter for domain separation |
When reviewing code, search for these patterns. Any match is a finding.
❌ = insecure pattern signature to detect in user code. ✅ = apply the corrective pattern in the referenced file.
| Search For | Anti-Pattern | Severity | Reference |
|---|---|---|---|
UserDefaults.standard.set + token/key/secret/password |
Plaintext credential storage | CRITICAL | common-anti-patterns.md #1 |
| Hardcoded base64/hex strings (≥16 chars) in source | Hardcoded cryptographic key | CRITICAL | common-anti-patterns.md #2 |
evaluatePolicy without SecItemCopyMatching nearby |
LAContext-only biometric gate | CRITICAL | common-anti-patterns.md #3 |
SecItemAdd without checking return / OSStatus |
Ignored error code | HIGH | common-anti-patterns.md #4 |
No kSecAttrAccessible in add dictionary |
Implicit accessibility class | HIGH | common-anti-patterns.md #5 |
AES.GCM.Nonce() inside a loop with same key |
Potential nonce reuse | CRITICAL | common-anti-patterns.md #6 |
sharedSecret.withUnsafeBytes without HKDF |
Raw shared secret as key | HIGH | common-anti-patterns.md #7 |
kSecAttrAccessibleAlways |
Deprecated accessibility | HIGH | keychain-access-control.md |
SecureEnclave.isAvailable without #if !targetEnvironment(simulator) |
Simulator false-negative trap | MEDIUM | secure-enclave.md |
kSecAttrSynchronizable: true + ThisDeviceOnly |
Contradictory constraints | MEDIUM | keychain-item-classes.md |
SecTrustEvaluate (sync, deprecated) |
Legacy trust evaluation | MEDIUM | certificate-trust.md |
kSecClassGenericPassword + kSecAttrServer |
Wrong class for web credentials | MEDIUM | keychain-item-classes.md |
Use this checklist for a rapid sweep across all 14 domains. Each item maps to one or more reference files for deep-dive investigation. For domain-specific deep checks, use the Summary Checklist at the bottom of each reference file.
1. Secrets are in Keychain, not UserDefaults/plist/source — No credentials, tokens, or cryptographic keys in UserDefaults, Info.plist, .xcconfig, hardcoded strings, or NSCoding archives. OWASP M9 (Insecure Data Storage) directly violated. → common-anti-patterns.md #1–2, credential-storage-patterns.md, migration-legacy-stores.md, compliance-owasp-mapping.md
2. Every OSStatus is checked — All SecItem* calls handle return codes with exhaustive switch or equivalent. No ignored returns. errSecInteractionNotAllowed is handled non-destructively (retry later, never delete). → keychain-fundamentals.md, common-anti-patterns.md #4
3. Biometric auth is keychain-bound — If biometrics are used, authentication is enforced via SecAccessControl + keychain access, not LAContext.evaluatePolicy() alone. → biometric-authentication.md, common-anti-patterns.md #3
4. Accessibility classes are explicit and correct — Every keychain item has an explicit kSecAttrAccessible value matching its access pattern (background vs foreground, device-bound vs syncable). No deprecated Always constants. → keychain-access-control.md
5. No SecItem* calls on @MainActor — All keychain operations run on a dedicated actor or background queue. No synchronous keychain access in UI code, viewDidLoad, or application(_:didFinishLaunchingWithOptions:). → keychain-fundamentals.md
6. Correct kSecClass for each item type — Web credentials use InternetPassword (not GenericPassword) for AutoFill. Cryptographic keys use kSecClassKey with proper kSecAttrKeyType. App secrets use GenericPassword with kSecAttrService + kSecAttrAccount. → keychain-item-classes.md
7. CryptoKit used correctly — Nonces never reused with the same key. ECDH shared secrets always derived through HKDF before use as symmetric keys. SymmetricKey material stored in Keychain, not in memory or files. Crypto operations covered by protocol-based unit tests. → cryptokit-symmetric.md, cryptokit-public-key.md, testing-security-code.md
8. Secure Enclave constraints respected — SE keys are P256 only (classical), never imported (always generated on-device), device-bound (no backup/sync). Availability checks guard against simulator and keychain-access-groups entitlement issues. → secure-enclave.md
9. Sharing and access groups configured correctly — kSecAttrAccessGroup uses full TEAMID.group.identifier format. Entitlements match between app and extensions. No accidental cross-app data exposure. → keychain-sharing.md
10. Certificate trust evaluation is current — Uses SecTrustEvaluateAsyncWithError (not deprecated synchronous SecTrustEvaluate). Pinning strategy uses SPKI hash or NSPinnedDomains (not leaf certificate pinning which breaks on annual rotation). → certificate-trust.md
11. macOS targets data protection keychain — All macOS SecItem* calls include kSecUseDataProtectionKeychain: true (except Mac Catalyst / iOS-on-Mac where it's automatic). → keychain-fundamentals.md
| # | File | One-Line Description | Risk |
|---|