FlawOpen

flawopen.com/SQL-инъекция в JavaScript/Prisma

Защищает ли Prisma $queryRaw от SQL-инъекций?

Справочное руководство
Краткий ответ

Представьте параметр как запечатанное поле значения в SQL-форме: база данных воспринимает его как данные, а не синтаксис. Tagged template $queryRaw связывает интерполированные значения. $queryRawUnsafe тоже может связывать значения, если передать placeholders и аргументы отдельно; риск возникает при конкатенации недоверенного текста в SQL. Ни один из методов не параметризует имена таблиц или столбцов.

НЕБЕЗОПАСНО — конкатенация ввода в SQL
const userId = request.query.userId;
const query =
  `SELECT id FROM users WHERE id = ${userId}`;
const rows = await prisma.$queryRawUnsafe(query);
ЗАЩИЩЕНО — связывать значения и выбирать структуру по allowlist
const rows = await prisma.$queryRaw`
  SELECT id FROM users WHERE id = ${userId}
`;

// PostgreSQL example: $1 binds data, not an identifier.
const columns = { name: 'name', created: 'created_at' } as const;
const column = columns[requestedSort as keyof typeof columns] ?? 'created_at';
const pageSize = 25;
const sortedRows = await prisma.$queryRawUnsafe(
  `SELECT id FROM users ORDER BY ${column} LIMIT $1`,
  pageSize
);
// The selected SQL structure comes from a fixed map.

Что делают параметры Prisma — и чего они не делают

Для $queryRaw используйте непосредственно вызов tagged template: каждое интерполированное значение становится параметром базы данных. Не собирайте сначала SQL-строку, передавая её единственным аргументом. Prisma также поддерживает placeholders в $queryRawUnsafe(query, ...values): значения связываются, но текст SQL должен оставаться доверенным. Параметры представляют данные, а не идентификаторы, операторы или фрагменты SQL. Выбирайте столбцы из фиксированного allowlist, заданного приложением. Для многих типизированных raw-запросов Prisma рекомендует TypedSQL.

Проверка raw-запросов Prisma

grep -rn "\$queryRawUnsafe\|\$executeRawUnsafe" --include="*.ts" --include="*.js" .

Вопросы и ответы

Зачем нужен $queryRawUnsafe?

Он принимает raw SQL и поддерживает placeholders, если значения передаются отдельно. Гибкость упрощает небезопасное формирование строк, поэтому проверяйте SQL и аргументы вместе. Динамические идентификаторы от этого не становятся безопасными: используйте фиксированный allowlist.

Источники

См. также SQL-инъекции (CWE-89): как они работают и как их предотвратить в любом языке — flawopen.com Безопасна ли интерполяция в Rails where()? Защищает ли Sequelize query() от SQL-инъекций? Защищает ли SQLAlchemy text() от SQL-инъекций? Предотвращает ли проверка sqlx при компиляции SQL-инъекции? Защищают ли хранимые процедуры от SQL-инъекций? Защищает ли TypeORM QueryBuilder от SQL-инъекций?