Common Vulnerabilities
OWASP Mobile Top 10
The OWASP Mobile Top 10 lists the most critical mobile security risks:
- Improper Credential Usage: Hardcoded API keys, weak storage
- Inadequate Supply Chain Security: Compromised third-party libraries
- Insecure Authentication: Weak session management
- Insufficient Input Validation: Injection attacks
- Insecure Communication: Unencrypted data transmission
- Inadequate Privacy Controls: Excessive data collection
- Insufficient Binary Protections: Lack of code obfuscation
- Security Misconfiguration: Incorrect ATS, overly permissive entitlements
- Insecure Data Storage: Plaintext sensitive data
- Insufficient Cryptography: Weak or outdated algorithms
Hardcoded Secrets
Never hardcode API keys, passwords, or secrets in source code:
// BAD: Hardcoded API key
let apiKey = "sk_live_abc123def456"
// GOOD: Read from environment or secure storage
let apiKey = Bundle.main.infoDictionary?["API_KEY"] as? String
// Or better: fetch from Keychain or server at runtime
Insecure Logging
// BAD: Logging sensitive data
print("User password: \(password)")
print("Credit card: \(cardNumber)")
// GOOD: Use os_log with privacy annotations
import os.log
let logger = Logger(subsystem: "com.app", category: "auth")
logger.info("Login attempt for user: \(privacy: .public, username)")
// Sensitive data is redacted automatically
Clipboard Exposure
Sensitive data in the clipboard can be accessed by other apps:
// BAD: Copying sensitive data to clipboard
UIPasteboard.general.string = authToken
// GOOD: Use ephemeral clipboard with timeout
UIPasteboard.general.string = otpCode
DispatchQueue.main.asyncAfter(deadline: .now() + 30) {
if UIPasteboard.general.string == otpCode {
UIPasteboard.general.string = nil
}
}
Input Validation
Server-Side Validation
Never trust client-side validation alone. Always validate on the server:
// Client-side validation for UX
func validateEmail(_ email: String) -> Bool {
let pattern = "^[A-Z0-9._%+-]+@[A-Z0-9.-]+\\.[A-Z]{2,}$"
return email.range(of: pattern, options: .regularExpression) != nil
}
// Server validates again regardless of client validation
SQL Injection Prevention
Use parameterized queries or Core Data instead of string interpolation:
// BAD: SQL injection vulnerability
let query = "SELECT * FROM users WHERE name = '\(userInput)'"
// GOOD: Parameterized query
let statement = try database.prepare(
"SELECT * FROM users WHERE name = ?"
)
try statement.bind(userInput)
// BETTER: Use CoreData with predicate
let predicate = NSPredicate(format: "name == %@", userInput)
let request = NSFetchRequest<User>(entityName: "User")
request.predicate = predicate
URL Scheme Validation
Validate URLs before opening them to prevent phishing:
func handleIncomingURL(_ url: URL) {
guard url.scheme == "myapp" else { return }
guard url.host == "callback" else { return }
// Validate and sanitize query parameters
guard let components = URLComponents(url: url, resolvingAgainstBaseURL: false) else { return }
let token = components.queryItems?.first(where: { $0.name == "token" })?.value
// Validate token format
guard let token = token, token.count == 32 else { return }
processToken(token)
}
WebView Security
// BAD: Allowing arbitrary JavaScript
webView.configuration.preferences.javaScriptEnabled = true
// GOOD: Restrict web content
let config = WKWebViewConfiguration()
config.suppressesIncrementalRendering = true
// Validate URLs loaded in webview
func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction) async -> WKNavigationActionPolicy {
guard let url = navigationAction.request.url else { return .cancel }
let allowedHosts = ["trusted-domain.com"]
if allowedHosts.contains(url.host ?? "") {
return .allow
}
return .cancel
}
Privacy & Permissions
Info.plist Permissions
iOS requires usage descriptions for privacy-sensitive APIs:
<key>NSCameraUsageDescription</key>
<string>We need camera access to scan documents</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>We need photo access to save your edits</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>We use your location to show nearby stores</string>
<key>NSFaceIDUsageDescription</key>
<string>Face ID secures your account</string>
Runtime Permission Checks
Always check permission before accessing sensitive APIs:
import AVFoundation
class CameraManager {
func checkPermission() async -> Bool {
switch AVCaptureDevice.authorizationStatus(for: .video) {
case .authorized: return true
case .notDetermined:
return await AVCaptureDevice.requestAccess(for: .video)
case .denied, .restricted:
return false
@unknown default: return false
}
}
}
App Tracking Transparency
Required for tracking users across apps:
import AppTrackingTransparency
func requestTracking() async -> Bool {
let status = await ATTrackingManager.requestTrackingAuthorization()
return status == .authorized
}
Data Collection Minimization
Follow the principle of least privilege:
- Only request permissions you actually need
- Collect only the data required for your feature
- Provide clear explanations for each permission request
- Allow users to use your app with limited permissions when possible
Privacy Nutrition Labels
App Store requires privacy labels that declare data collection. Be accurate about:
- What data you collect
- How it is used
- Whether it is linked to identity
- Whether it is used for tracking
Quiz
1. Which OWASP category covers hardcoded API keys?
2. Why should you never log sensitive data?
3. How do you prevent SQL injection in iOS?
4. What must you add to Info.plist for camera access?
Flashcards
Question
What are the OWASP Mobile Top 10?
Click to reveal answer
Answer
The ten most critical mobile security risks: improper credentials, supply chain, auth, input validation, insecure communication, privacy, binary protection, misconfiguration, data storage, and cryptography.
Question
Why use parameterized queries instead of string interpolation?
Click to reveal answer
Answer
Parameterized queries separate SQL code from user data, preventing SQL injection where malicious input is interpreted as SQL commands.
Question
What is App Tracking Transparency?
Click to reveal answer
Answer
An iOS framework that requires user permission before apps can track their activity across other companies apps and websites for advertising.
Revision Notes
Key Takeaways
- 1. Never hardcode API keys or secrets in source code
- 2. Always validate input on both client and server sides
- 3. Use parameterized queries to prevent injection attacks
- 4. Check and request permissions before accessing sensitive APIs
- 5. Minimize data collection and follow privacy principles
Interview Tips
- • Discuss common iOS security vulnerabilities from OWASP Mobile Top 10
- • Explain how to prevent SQL injection in a CoreData app
- • Describe best practices for handling user credentials
- • Walk through implementing proper input validation
Cheat Sheet
Secure Coding Quick Reference
- Never hardcode secrets in source code
- Use os_log with privacy annotations
- Validate all input on both client and server
- Use parameterized queries to prevent SQL injection
- Check permissions before accessing sensitive APIs
- Follow data collection minimization principle