Có. ORM chỉ an toàn ở phần nó tự sinh câu lệnh; mọi chỗ bạn tự ghép chuỗi đều quay lại rủi ro cũ.
Ba chỗ hở hay gặp:
1. Raw query nối chuỗi. Escape hatch của ORM ($queryRawUnsafe, createQuery với chuỗi, query() của driver) không tự tham số hoá.
ts
// vulnerable
await prisma.$queryRawUnsafe(`SELECT * FROM users WHERE email = '${email}'`)
// safe: tagged template binds parameters
await prisma.$queryRaw`SELECT * FROM users WHERE email = ${email}`2. ORDER BY / tên cột / tên bảng động. Đây là chỗ placeholder không dùng được — parameter chỉ thay được giá trị, không thay được định danh.
Bắt buộc phải allowlist:
ts
const SORTABLE = { created: 'created_at', name: 'full_name' } as const
const column = SORTABLE[req.query.sort as keyof typeof SORTABLE] ?? 'created_at'
const dir = req.query.dir === 'asc' ? 'ASC' : 'DESC'3. LIKE và IN ghép tay. Ghép danh sách id thành chuỗi IN (...), hoặc nối % vào input rồi mới bind — phần nối chuỗi vẫn là lỗ hổng.
Còn một loại nữa ít gặp hơn: second-order injection — dữ liệu độc được lưu sạch vào DB, nhưng sau đó một job đọc ra và ghép vào câu lệnh khác.