SQL‑Injection in Prisma ist ein Problem, das selbst bei modernen ORMs auftreten kann, wenn keine geeigneten Praktiken angewendet werden. In diesem Artikel stellen wir das Bedrohungsmodell, die Funktionsweise von Prisma, einen Vergleich von anfälligem und verbessertem Code sowie eine Checkliste zur Minderung basierend auf OWASP Top 10, CWE und dem Prinzip der minimalen Rechte vor.
Bedrohungsmodell – wie SQL‑Injection entsteht
Ein SQL‑Injection‑Angriff besteht darin, dass ein nicht autorisierter SQL‑Code‑Abschnitt in die von der Anwendung generierte Abfrage eingeschleust wird. Im Kontext von Prisma geschieht dies meist, wenn der Entwickler sogenannte raw-Abfragen nutzt oder Variablen ohne Validierung in Strings interpoliert. Prisma selbst sanitisiert Parameter, die als Objekte übergeben werden, schützt jedoch nicht vor gefährlicher Nutzung von prisma.$queryRaw oder prisma.$executeRaw mit falscher Formatierung.
Wie Prisma und TypeScript das Risiko reduzieren
Prisma bietet zwei Schutzebenen: statisch (TypeScript‑Typen) und zur Laufzeit (parametrisierte Abfragen). Typen stellen sicher, dass Felder, die an Abfragen übergeben werden, im Schema existieren, und zur Laufzeit werden Werte automatisch in gebundene Parameter umgewandelt, was das Einschleusen von SQL‑Code verhindert. Entscheidend ist jedoch die konsequente Nutzung von Methoden wie findUnique, findMany, create usw., anstatt Abfragen manuell zu bauen.
Beispiel: anfälliger vs. verbesserter Code
Nachfolgend zeigen wir zwei Code‑Snippets – das erste verletzt Sicherheitsrichtlinien, das zweite nutzt das volle Potenzial von Prisma und TypeScript.
// anfälliger Code – Nutzung von $queryRaw mit String‑Interpolation
const userId = req.query.id; // vom Nutzer bereitgestellt
const result = await prisma.$queryRaw(`SELECT * FROM "User" WHERE id = ${userId}`);
Im obigen Beispiel wird userId direkt in die Abfrage eingesetzt, wodurch ein Angreifer z. B. 1; DROP TABLE "User"; einfügen kann. Der korrekte Ansatz verwendet gebundene Parameter:
// verbesserter Code – gebundener Parameter
const userId = Number(req.query.id);
if (Number.isNaN(userId)) {
throw new Error('Invalid user id');
}
const result = await prisma.$queryRaw`
SELECT * FROM "User" WHERE id = ${userId}`;
Prisma wandelt ${userId} automatisch in den Platzhalter $1 um und übergibt den Wert separat, wodurch ein Einschleusen verhindert wird.
Checkliste zur Minderung – was zu tun ist, um Fehler zu vermeiden
- Verwenden Sie ausschließlich ORM‑Methoden (find*, create*, update*, delete*) statt
$queryRawund$executeRaw. - Wenn Sie eine Raw‑Abfrage benötigen, immer Parameterisierung einsetzen (
prisma.$queryRaw`...${value}`). - Validieren und konvertieren Sie alle Eingaben (z. B.
Number(),zod,class‑validator). - Setzen Sie in der Datenbank minimale Berechtigungen (least‑privilege) – das Prisma‑Konto sollte keine DDL‑Rechte besitzen.
- Scannen Sie den Code regelmäßig auf CWE‑89 (SQL Injection) mit SAST‑Tools.
Verweise auf Standards – OWASP, CWE und das Prinzip der minimalen Rechte
OWASP Top 10 klassifiziert SQL‑Injection als A03 – „Injection“. CWE‑89 beschreibt die Technik im Detail und empfiehlt Gegenmaßnahmen wie vorbereitete Anweisungen und das Vermeiden dynamischer Abfragen. Das Prinzip der minimalen Rechte erzwingt, dass das Datenbankkonto nur die unbedingt notwendigen Rechte erhält – in der Praxis sollte das Prisma‑Konto nur SELECT, INSERT, UPDATE und DELETE für die benötigten Tabellen besitzen.
„Sicherheit ist kein einmaliger Test, sondern ein kontinuierlicher Prozess – jeder neue Code‑Abschnitt ist ein potenzieller Angriffsvektor.“
Typische Fehler und Kompromisse
Der häufigste Fehler ist die Abhängigkeit von „magischen“ Strings in der Geschäftslogik und deren späteres Einfügen in Raw‑Queries. Ein weiteres Problem ist das Fehlen von Typ‑Validierung bei der Konvertierung von Eingaben, was zu unerwarteten NaN und letztlich zu einem Fallback auf Strings führt. Ein Kompromiss kann die Nutzung von prisma.$queryRawUnsafe sein, wenn keine Alternative existiert; dann muss jedoch manuell gesäubert und der Zugriff auf diese Funktion auf ein gut getestetes Modul beschränkt werden.
Praktische Implementierungs‑Checkliste
- Code‑Audit auf Nutzung von
$queryRawund$executeRaw. - Erzwingen Sie die Typisierung aller Parameter in TypeScript (z. B.
type UserId = number). - Konfigurieren Sie das Prisma‑Schema mit den richtigen Rollen –
@@mapund@@idmüssen zur Laufzeit nicht verändert werden. - Implementieren Sie Integrationstests, die versuchen, bösartige Strings in Endpunkte zu injizieren.
- Setzen Sie CI/CD‑Regeln, die einen Merge blockieren, wenn CWE‑89 in SAST‑Ergebnissen gefunden wird.
Durch die Anwendung dieser Praktiken minimieren Sie das Risiko von SQL‑Injection in Node.js‑Anwendungen, die Prisma und TypeScript verwenden, und erhalten gleichzeitig hohe Performance und Code‑Lesbarkeit.
Wenn Sie Unterstützung beim Hardening der Datenschicht, bei Sicherheits‑Audits oder bei der Implementierung von OWASP‑konformen CI/CD‑Pipelines benötigen, kontaktieren Sie Coderia.it – wir helfen Ihnen, robuste und sichere Backend‑Lösungen zu bauen.



