# So beheben Sie unsicheres SQL in KI-generiertem Code

> KI-Agenten erstellen SQL-Abfragen mit String-Interpolation anstelle von parametrisierten Anweisungen, wodurch SQL-Injection-Schwachstellen in produktiven Datenbankcode eingeschleust werden.

**Type:** Failure  
**Tools:** Cursor, Claude Code, Codex, Windsurf  
**Stack:** PostgreSQL, TypeScript  
**Updated:** 2026-06-08

---

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.

## Das Symptom

Vom Benutzer gesteuerte Werte werden direkt in einen SQL-String interpoliert.

```ts
// WRONG — SQL injection vulnerability
async function getUserByEmail(email: string) {
  const result = await db.query(
    `SELECT * FROM users WHERE email = '${email}'`
    //                                  ^^^^^^^ attacker-controlled
  );
  return result.rows[0];
}

// Attacker input: ' OR '1'='1
// Resulting query: SELECT * FROM users WHERE email = '' OR '1'='1'
// Returns every row in the table.
```

## Warum es passiert

Template-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.

## Wie man es erkennt

- SQL-Strings, die `${...}`-Interpolationen enthalten.
- Abfragefunktionen, die Benutzereingaben akzeptieren und an einen Raw-Query-Helper ohne separates params-Array übergeben.
- `db.query(sql)` wird mit einem einzigen Argument aufgerufen statt mit `db.query(sql, [params])`.
- `LIKE '%${term}%'`-Muster.

## Wie man es behebt

Verwenden Sie immer parametrisierte Abfragen. Der Datenbanktreiber übernimmt das Escaping; Ihr Code berührt niemals die Anführungszeichen.

```ts
// CORRECT — parameterized query (node-postgres / pg)
async function getUserByEmail(email: string) {
  const result = await db.query(
    "SELECT id, name, email FROM users WHERE email = $1",
    [email]  // second argument: params array
  );
  return result.rows[0] ?? null;
}

// CORRECT — with Postgres.js (template tag)
async function searchUsers(term: string) {
  return sql`SELECT id, name FROM users WHERE name ILIKE ${"%" + term + "%"}`;
  // postgres.js automatically parameterizes template expressions
}
```

```txt
[ ] No ${...} inside raw SQL strings — use $1/$2 placeholders instead
[ ] Every db.query() call passes user input via the params array, not the SQL string
[ ] Use an ORM (Prisma, Drizzle) or query builder for complex queries
[ ] LIKE wildcards are appended in the param value, not concatenated into the SQL
[ ] Run sqlfluff or a SQL linter in CI to catch interpolated strings
```

## Korrektur-Prompt

```txt title="Fix Prompt"
This SQL query uses string interpolation with user-supplied values, which is a
SQL injection vulnerability. Rewrite every raw query to use parameterized
statements ($1, $2 placeholders for pg, or the tagged template literal form for
postgres.js). Never interpolate variables directly into SQL strings. If the
query is complex, migrate it to Prisma or Drizzle ORM instead.
```

## Test

```bash
# Detect template literal interpolation inside SQL-looking strings
grep -rn 'query(`\|sql`\|execute(`' --include="*.ts" --include="*.tsx" . \
  | grep '\${' \
  | grep -v "node_modules" \
  && echo "FAIL: interpolated SQL found" || echo "OK"
```