Swift Application Security: Top 10 Vulnerabilities and Protection Methods
Developing in Swift for iOS and macOS requires special attention to security. Even a small mistake can lead to data leaks, hacking, or device compromise. In this article, we will analyze the 10 most common vulnerabilities in Swift applications, show examples of dangerous code, and provide practical recommendations for fixing them.
1. Insecure Data Storage
The most common mistake is saving confidential data in UserDefaults or Plist files without encryption.
Problematic code:
UserDefaults.standard.set("password123", forKey: "userPassword")UserDefaults.standard.synchronize()Secure solution: Use Keychain Services or Data Protection API.
import Security
func savePassword(_ password: String, for account: String) { let data = password.data(using: .utf8)! let query: [String: Any] = [ kSecClass as String: kSecClassGenericPassword, kSecAttrAccount as String: account, kSecValueData as String: data, kSecAttrAccessible as String: kSecAttrAccessibleWhenUnlockedThisDeviceOnly ] SecItemAdd(query as CFDictionary, nil)}2. Input Validation
User input often contains malicious data. Always validate and sanitize input.
Example of SQL injection:
let query = "SELECT * FROM users WHERE name = '\\(userInput)'" // Dangerous!Protection: Use parameterized queries.
let query = "SELECT * FROM users WHERE name = ?"let statement = try database.prepare(query)try statement.bind([userInput])3. Insecure Network Communication
Using HTTP instead of HTTPS, ignoring SSL certificates.
Dangerous code:
let url = URL(string: "http://example.com/api")! // HTTP, not HTTPSlet task = URLSession.shared.dataTask(with: url) { data, response, error in // Data processing}Secure approach:
let url = URL(string: "https://example.com/api")!let config = URLSessionConfiguration.defaultconfig.tlsMinimumSupportedProtocolVersion = .TLSv12let session = URLSession(configuration: config)let task = session.dataTask(with: url) { data, response, error in guard let httpResponse = response as? HTTPURLResponse, httpResponse.statusCode == 200 else { return } // Data processing}task.resume()4. WebView Injection
If you use WKWebView without restrictions, an attacker can execute JavaScript code.
Vulnerable code:
webView.loadHTMLString(htmlContent, baseURL: nil)Protection: Disable JavaScript or use Content Security Policy.
let config = WKWebViewConfiguration()let preferences = WKPreferences()preferences.javaScriptEnabled = falseconfig.preferences = preferenceslet webView = WKWebView(frame: .zero, configuration: config)5. Hardcoded Secrets
Never store API keys, tokens, or passwords in source code.
Incorrect:
let apiKey = "sk_live_1234567890abcdef"Correct: Use .env files, server-side authorization, or cloud services (e.g., AWS Secrets Manager).
// Encrypted key in Info.plistif let apiKey = Bundle.main.object(forInfoDictionaryKey: "API_KEY") as? String { // Use the key}