// A
await prisma.$queryRaw`SELECT * FROM "User" WHERE email = ${email}`;
// B
await prisma.$queryRawUnsafe(`SELECT * FROM "User" WHERE email = '${email}'`);
A is safe because the tagged template sends
email as a bound parameter; B interpolates it into the SQL string and is injectableA is safe and B is injectable. When you use $queryRaw as a tagged template, Prisma receives the values separately and sends them as bound parameters. The database never treats them as SQL.$queryRawUnsafe with a pre-built string runs whatever SQL it gets. So "B is safe because the value is wrapped in quotes" is wrong: the quotes do nothing against input like ' OR '1'='1.
"Prisma escapes all raw queries" is also wrong, and so is "any raw SQL bypasses the ORM". An ORM only protects you when you use its parameterising APIs.
Read more