Swift Security: SQL Injections and XSS — How to Protect Your Code

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

Swift on the Front Line: Why Security is Not an Option, But a Necessity

\n

You write in Swift, proud of its performance and code elegance. But have you considered how vulnerable your application is to attacks? SQL injections and XSS (Cross-Site Scripting) are not just scary stories from textbooks. They are real threats that can cost you user data, reputation, and money.

\n

In this article, we will break down how to protect a Swift application (whether it's an iOS client or a server-side Vapor app) from the two most dangerous types of attacks. No fluff — only practical examples, ready-made solutions, and live code. Let's go!

\n\n

SQL Injections in Swift: How Hackers "Trick" the Database

\n

Imagine: a user enters '; DROP TABLE Users; -- into a text field. If you directly insert this string into an SQL query, the database will execute the delete command. A classic scenario.

\n

In Swift, this vulnerability is most often found in server-side frameworks (Vapor, Kitura) or when working with Core Data and SQLite through unsafe wrappers.

\n\n

Dangerous Example: How NOT to Do It

\n
import SQLite\n\nlet username = userInput.text // "admin' OR '1'='1"\nlet query = "SELECT * FROM users WHERE name = '\\(username)'"\ntry db.execute(query) // THREAT! Compromised query\n
\n

This code is a red flag. An attacker can gain access to any data or destroy the table.

\n\n

The Right Approach: Parameterized Queries

\n

Golden Rule: never insert user data directly into a query string. Use parameterization.

\n
import SQLite\n\nlet db = try Connection("path/to/db.sqlite3")\nlet users = Table("users")\nlet name = Expression<String>("name")\n\nlet username = userInput.text // "admin' OR '1'='1"\nlet query = users.filter(name == username) // SAFE\nlet result = try db.prepare(query)\n
\n

The SQLite.swift library escapes special characters automatically. For Vapor with Fluent, use models and filters:

\n
import Fluent\nimport Vapor\n\nstruct UserController: RouteCollection {\n    func login(req: Request) async throws -> String {\n        let input = try req.content.decode(LoginRequest.self)\n        // Fluent automatically parameterizes the query\n        let user = try await User.query(on: req.db)\n            .filter(\\.$name == input.username)\n            .first()\n        return user?.name ?? "Not found"\n    }\n}\n
\n

Important: even if you use raw SQL in Vapor, apply SQLBind for parameter binding.

\n\n

ORM and Core Data: The Illusion of Security

\n

Many developers believe that Core Data or Fluent automatically protect against injections. This is true — if you don't use NSExpression with string formatting or raw SQL. But remember: any NSPredicate built via string interpolation is a risk.

\n
// DANGEROUS\nlet predicate = NSPredicate(format: "name == %@", userInput) // Safe?\n// NO! If userInput contains '%', injection can occur through substitution.\n
\n

Always use %@ with variables, not %K with keys, and never insert strings via \\().

\n\n

XSS Attacks in Swift: When an Attacker Injects JavaScript

\n

XSS is an attack where a malicious script executes in the user's browser. For iOS applications, XSS is relevant when using WKWebView to display HTML content (e.g., in news feeds or chats).

\n\n

Real Scenario: Chat with HTML Formatting

\n

A user writes: Hello! <script>alert('XSS')</script>. If you display this message in a WebView without processing — the script will execute.

\n
// DANGEROUS\nlet html = "<div>\\(message.text)</div>"\nwebView.loadHTMLString(html, baseURL: nil)\n

Blogs

Book Recommendations