ios-security-review

iOS security vulnerability detection and remediation guide. Covers OWASP Mobile Top 10, Keychain, ATS, App Store security compliance, and security review workflows.

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "ios-security-review" with this command: npx skills add sh-oh/ios-agent-skills/sh-oh-ios-agent-skills-ios-security-review

iOS Security Review

Expert iOS security skill focused on identifying and remediating vulnerabilities in iOS applications. Prevents security issues before they reach production and App Store review.


When to Apply

ALWAYS activate when:

  • Implementing authentication or authorization logic
  • Handling sensitive user data (PII, credentials, financial)
  • Working with Keychain, Data Protection, or Secure Enclave
  • Creating or modifying network requests
  • Implementing biometric authentication
  • Integrating third-party SDKs
  • Handling payments (StoreKit, Apple Pay)
  • Adding deep links or URL scheme handling
  • Working with WebView (WKWebView)

IMMEDIATELY activate when:

  • Security incident or vulnerability reported
  • Dependency has a known CVE
  • App Store rejection for privacy or security reasons
  • Preparing for App Store submission

Quick Reference

Severity Levels

LevelExamplesAction
CRITICALHardcoded secrets, unencrypted credentials, disabled ATSFix before ANY commit
HIGHMissing SSL pinning, insecure storage, no server-side auth validationFix before release
MEDIUMMissing rate limiting, weak input validation, no certificate pinningFix in next sprint
LOWMissing obfuscation, verbose logging, best practice gapsAdd to backlog

iOS Security Feature Requirements

FeatureMinimum iOS
Privacy ManifestiOS 17.0
evaluatedPolicyDomainStateiOS 16.0
StoreKit 2 (JWS verification)iOS 15.0
App AttestiOS 14.0
ASWebAuthenticationSessioniOS 12.0
Biometric (Face ID / Touch ID)iOS 8.0

Mandatory Checks Checklist (Before Every Commit)

Data Security:

  • No hardcoded secrets (API keys, tokens, credentials)
  • Keychain used for all sensitive data (with correct accessibility level)
  • Data Protection enabled for sensitive files
  • In-memory sensitive data cleared after use
  • No secrets in UserDefaults or Info.plist

Network Security:

  • ATS enabled (no NSAllowsArbitraryLoads without justification)
  • SSL pinning for critical APIs
  • Ephemeral sessions for sensitive requests
  • No credentials in logs (print, os_log, NSLog)

Authentication Security:

  • Biometric auth includes domain state validation
  • Secure token storage in Keychain
  • Re-authentication required for sensitive operations

Privacy & Compliance:

  • Privacy Manifest up to date (iOS 17+)
  • Required Reason APIs documented
  • ATT implemented if tracking users

UI Security:

  • Screenshot/recording protection for sensitive screens
  • Background snapshot blur/hide applied
  • Clipboard expiration set for sensitive data

Key Patterns

Keychain Usage (Brief)

// NEVER store sensitive data in UserDefaults
UserDefaults.standard.set(token, forKey: "authToken") // CRITICAL vulnerability

// ALWAYS use Keychain with proper accessibility
let query: [String: Any] = [
    kSecClass as String: kSecClassGenericPassword,
    kSecAttrAccount as String: "authToken",
    kSecValueData as String: tokenData,
    kSecAttrAccessible as String: kSecAttrAccessibleWhenUnlockedThisDeviceOnly
]
SecItemAdd(query as CFDictionary, nil)

Full implementation: see references/keychain.md

ATS Configuration (Brief)

<!-- Keep ATS enabled (default). Only add exceptions when necessary -->
<key>NSAppTransportSecurity</key>
<dict>
    <key>NSExceptionDomains</key>
    <dict>
        <key>legacy-api.example.com</key>
        <dict>
            <key>NSExceptionAllowsInsecureHTTPLoads</key>
            <true/>
            <key>NSExceptionMinimumTLSVersion</key>
            <string>TLSv1.2</string>
        </dict>
    </dict>
</dict>

Never set NSAllowsArbitraryLoads to true in production.

Full implementation with SSL pinning: see references/network-security.md

Biometric Authentication (Brief)

let context = LAContext()
context.touchIDAuthenticationAllowableReuseDuration = 0 // Always re-authenticate

// iOS 16+: Detect biometric changes
if let currentState = context.evaluatedPolicyDomainState,
   let saved = savedDomainState,
   currentState != saved {
    throw AuthError.biometricChanged
}

let success = try await context.evaluatePolicy(
    .deviceOwnerAuthenticationWithBiometrics,
    localizedReason: "Authenticate to access your account"
)
// ALWAYS validate with server after local biometric success

Full implementation: see references/network-security.md

Privacy Manifest Overview

Every app targeting iOS 17+ must include PrivacyInfo.xcprivacy declaring:

  1. NSPrivacyTracking -- whether the app tracks users
  2. NSPrivacyTrackingDomains -- domains used for tracking
  3. NSPrivacyCollectedDataTypes -- what data is collected and why
  4. NSPrivacyAccessedAPITypes -- Required Reason APIs used (UserDefaults, file timestamps, etc.)

Full checklist: see references/review-checklist.md


Security Review Report Format

When performing a security review, produce a report in this structure:

# iOS Security Review Report

**App/Component:** [Name]
**Reviewed:** YYYY-MM-DD
**Reviewer:** ios-security-review skill

## Summary

| Severity | Count |
|----------|-------|
| CRITICAL | X |
| HIGH     | Y |
| MEDIUM   | Z |
| LOW      | W |

**Overall Risk Level:** CRITICAL / HIGH / MEDIUM / LOW

---

## Findings

### [Finding Number]. [Issue Title]

**Severity:** CRITICAL | HIGH | MEDIUM | LOW
**OWASP Category:** M[1-10] - [Category Name]
**Location:** `FileName.swift:LineNumber`

**Issue:**
Description of what is wrong.

**Impact:**
What could happen if this is exploited.

**Remediation:**
[Code fix or configuration change]

**References:**
- OWASP Mobile: M[X]
- Apple Documentation: [Link]

---

## Checklist Results

### Data Storage
- [ ] No sensitive data in UserDefaults
- [ ] Keychain used with appropriate accessibility
- [ ] Files protected with correct protection class
- [ ] Core Data / SwiftData encrypted if storing sensitive data

### Network
- [ ] ATS enabled, exceptions justified
- [ ] Certificate pinning for sensitive APIs
- [ ] No cleartext traffic

### Authentication
- [ ] Biometrics server-validated
- [ ] Tokens stored securely
- [ ] Session management secure

### Code Quality
- [ ] No hardcoded secrets
- [ ] No debug code in release builds
- [ ] Logging sanitized

### App Store Compliance
- [ ] Privacy manifest complete
- [ ] Required Reason APIs documented
- [ ] Data deletion option provided

Common Mistakes (Top 5 Critical Anti-Patterns)

1. Storing Secrets in UserDefaults

// CRITICAL: UserDefaults is a plain plist -- trivially readable
UserDefaults.standard.set(accessToken, forKey: "accessToken")
UserDefaults.standard.set(password, forKey: "password")

// FIX: Use Keychain
try KeychainManager.shared.save(
    tokenData, service: "com.app.auth", account: "accessToken"
)

2. Disabling ATS Globally

<!-- CRITICAL: Allows all cleartext HTTP traffic -->
<key>NSAppTransportSecurity</key>
<dict>
    <key>NSAllowsArbitraryLoads</key>
    <true/>
</dict>

<!-- FIX: Only add per-domain exceptions with documented justification -->

3. Client-Only Biometric Bypass

// CRITICAL: Attacker can patch the binary to skip this check
context.evaluatePolicy(.deviceOwnerAuthentication, ...) { success, _ in
    if success { self.showSecureContent() } // No server validation!
}

// FIX: Retrieve server-validated token from Keychain after biometric success
// then validate that token with your backend

4. Logging Sensitive Data

// HIGH: Logs persist and may be collected by crash reporting tools
print("User token: \(token)")
NSLog("API response: \(response)")

// FIX: Use conditional compilation and os_log
#if DEBUG
print("Debug info: \(debugInfo)")
#endif

5. Client-Only Purchase Validation

// CRITICAL: Users can fake purchase state
func purchaseCompleted(_ transaction: SKPaymentTransaction) {
    UserDefaults.standard.set(true, forKey: "isPremium") // Tamper-able!
}

// FIX: Always validate receipts server-side
// Use StoreKit 2 JWS verification + server-side App Store Server API

References


Detailed References

For full implementation details and extended checklists, see:

  • references/keychain.md -- Keychain implementation, data protection, encryption, secret management
  • references/network-security.md -- ATS, SSL pinning, biometric auth, OAuth, StoreKit, Apple Pay
  • references/review-checklist.md -- OWASP M1-M10 full checklist, UI security, app integrity, response protocol

Remember: iOS apps handle sensitive user data and often financial transactions. One security vulnerability can lead to user data theft, financial loss, and App Store removal. Be thorough and proactive.

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

Automation

swift-tdd-workflow

No summary provided by upstream source.

Repository SourceNeeds Review
Automation

ios-architecture

No summary provided by upstream source.

Repository SourceNeeds Review
Automation

foundation-models

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

xcode-build-resolver

No summary provided by upstream source.

Repository SourceNeeds Review