Exercise 2: Fixing an Injectable Query — Possible Solution ============================================================ The vulnerable code: prisma.$queryRawUnsafe(`SELECT * FROM "User" WHERE "email" = '${req.query.email}'`) The attack: GET /users?email=x' OR '1'='1 builds this SQL: SELECT * FROM "User" WHERE "email" = 'x' OR '1'='1' '1'='1' is always true, so every user is returned — emails, and any other columns such as password hashes. Other payloads could read other tables with UNION, or (with $executeRawUnsafe) change or delete data. Safe version 1 — Prisma Client (best here, no SQL needed at all): const email = String(req.query.email ?? ""); const user = await prisma.user.findUnique({ where: { email }, select: { id: true, name: true, email: true }, }); Safe version 2 — raw SQL with a tagged template: const users = await prisma.$queryRaw` SELECT "id", "name", "email" FROM "User" WHERE "email" = ${email} `; Safe version 3 — if you really must use the Unsafe method: await prisma.$queryRawUnsafe( 'SELECT "id", "name", "email" FROM "User" WHERE "email" = $1', email, ); WHY THIS WORKS AS AN ANSWER ------------------------------ All three fixes keep the user's text out of the SQL itself: it travels as a parameter, so the database compares it as a value and the hostile input simply matches no email. The answer also stops selecting "*", because even a safe query shouldn't send password hashes to the client. The best fix is the plainest: this query never needed raw SQL.