{
  "id": "ai-writes-insecure-sql",
  "type": "failures",
  "category": "failures",
  "locale": "de",
  "url": "/de/failures/ai-writes-insecure-sql",
  "title": "So beheben Sie unsicheres SQL in KI-generiertem Code",
  "description": "KI-Agenten erstellen SQL-Abfragen mit String-Interpolation anstelle von parametrisierten Anweisungen, wodurch SQL-Injection-Schwachstellen in produktiven Datenbankcode eingeschleust werden.",
  "tools": [
    "Cursor",
    "Claude Code",
    "Codex",
    "Windsurf"
  ],
  "stack": [
    "PostgreSQL",
    "TypeScript"
  ],
  "tags": [
    "sql",
    "security",
    "postgres"
  ],
  "difficulty": null,
  "updated": "2026-06-08",
  "markdown": "Der Agent greift auf Template-Literale zurück, um SQL-Abfragen zu erstellen, wodurch klassische SQL-Injection-Vektoren entstehen, die in Tests einwandfrei funktionieren, aber in der Produktion ausnutzbar sind.\n\n## Das Symptom\n\nVom Benutzer gesteuerte Werte werden direkt in einen SQL-String interpoliert.\n\n```ts\n// WRONG — SQL injection vulnerability\nasync function getUserByEmail(email: string) {\n  const result = await db.query(\n    `SELECT * FROM users WHERE email = '${email}'`\n    //                                  ^^^^^^^ attacker-controlled\n  );\n  return result.rows[0];\n}\n\n// Attacker input: ' OR '1'='1\n// Resulting query: SELECT * FROM users WHERE email = '' OR '1'='1'\n// Returns every row in the table.\n```\n\n## Warum es passiert\n\nTemplate-Literale sind das natürlichste Werkzeug zum Erstellen von Strings in JavaScript, und viele Tutorial-Beispiele, mit denen das Modell trainiert wurde, verwenden sie für SQL ohne Parametrisierung. Der Agent modelliert auch keine böswilligen Eingaben – er stellt sich vor, dass wohlgeformte Daten durchlaufen.\n\n## Wie man es erkennt\n\n- SQL-Strings, die `${...}`-Interpolationen enthalten.\n- Abfragefunktionen, die Benutzereingaben akzeptieren und an einen Raw-Query-Helper ohne separates params-Array übergeben.\n- `db.query(sql)` wird mit einem einzigen Argument aufgerufen statt mit `db.query(sql, [params])`.\n- `LIKE '%${term}%'`-Muster.\n\n## Wie man es behebt\n\nVerwenden Sie immer parametrisierte Abfragen. Der Datenbanktreiber übernimmt das Escaping; Ihr Code berührt niemals die Anführungszeichen.\n\n```ts\n// CORRECT — parameterized query (node-postgres / pg)\nasync function getUserByEmail(email: string) {\n  const result = await db.query(\n    \"SELECT id, name, email FROM users WHERE email = $1\",\n    [email]  // second argument: params array\n  );\n  return result.rows[0] ?? null;\n}\n\n// CORRECT — with Postgres.js (template tag)\nasync function searchUsers(term: string) {\n  return sql`SELECT id, name FROM users WHERE name ILIKE ${\"%\" + term + \"%\"}`;\n  // postgres.js automatically parameterizes template expressions\n}\n```\n\n```txt\n[ ] No ${...} inside raw SQL strings — use $1/$2 placeholders instead\n[ ] Every db.query() call passes user input via the params array, not the SQL string\n[ ] Use an ORM (Prisma, Drizzle) or query builder for complex queries\n[ ] LIKE wildcards are appended in the param value, not concatenated into the SQL\n[ ] Run sqlfluff or a SQL linter in CI to catch interpolated strings\n```\n\n## Korrektur-Prompt\n\n```txt title=\"Fix Prompt\"\nThis SQL query uses string interpolation with user-supplied values, which is a\nSQL injection vulnerability. Rewrite every raw query to use parameterized\nstatements ($1, $2 placeholders for pg, or the tagged template literal form for\npostgres.js). Never interpolate variables directly into SQL strings. If the\nquery is complex, migrate it to Prisma or Drizzle ORM instead.\n```\n\n## Test\n\n```bash\n# Detect template literal interpolation inside SQL-looking strings\ngrep -rn 'query(`\\|sql`\\|execute(`' --include=\"*.ts\" --include=\"*.tsx\" . \\\n  | grep '\\${' \\\n  | grep -v \"node_modules\" \\\n  && echo \"FAIL: interpolated SQL found\" || echo \"OK\"\n```"
}