Swift SQL Injection

Swift SQL injection

Description

Executing SQL constructed from user input can let an attacker change the query structure, bypass authentication, or read, modify, and delete data.

Potential impact

  • Authentication or authorization bypass
  • Sensitive data access and modification
  • Data deletion or service disruption

Remediation

  1. Do not concatenate or interpolate user input into SQL strings.
  2. Use APIs that separate query structure from values, such as SQLite bindings, prepared statements, or ORM query builders.
  3. Select identifiers that cannot be bound, such as table and column names, only from an allow-list.

Examples

Before

swift
let query = "SELECT * FROM users WHERE name = '\(username)'"
try db.execute(query)

After

swift
import GRDB

func findUser(db: Database, username: String) throws -> Row? {
    return try Row.fetchOne(
        db,
        sql: "SELECT * FROM users WHERE name = ?",
        arguments: [username])
}

Explanation:

  • Before: User input becomes part of the SQL structure.
  • After: GRDB's Row.fetchOne reads the result using bound arguments. The query structure and values remain separate, so input is treated as data.

References