SQL Injection Detection — ShipSafe

ShipSafe ships 127 SQL injection rules that understand Prisma, Drizzle, Knex, and raw pg/mysql2 drivers. It parses your code into an AST with Tree-sitter so it can tell the difference between a safe tagged-template query and a dangerous string-concatenated one — a distinction regex scanners consistently get wrong.

127 detection rulesLocal-only scanning

What is SQL Injection?

SQL injection occurs when untrusted user input is concatenated directly into SQL queries, allowing attackers to read, modify, or delete database data. It remains one of the most common and dangerous web vulnerabilities — consistently in the OWASP Top 10.

Why It Matters

A single SQL injection vulnerability can give an attacker full read access to your database — user emails, hashed passwords, payment records, everything. In the worst case, they can escalate to write access and modify or delete data, or use stacked queries and database-specific features (like xp_cmdshell on SQL Server or COPY TO PROGRAM on PostgreSQL) to execute operating system commands on the database server itself.

What ShipSafe Detects

Example: Vulnerable Code

Vulnerable Express.js route with SQL injection

// Vulnerable: user input directly in SQL query
app.get("/users", async (req, res) => {
  const { search } = req.query;
  const result = await db.query(
    `SELECT * FROM users WHERE name = '${search}'`
  );
  res.json(result.rows);
});

// An attacker sends: search=' OR '1'='1' --
// The query becomes: SELECT * FROM users WHERE name = '' OR '1'='1' --'
// This returns ALL users in the database.

ShipSafe Catches It

$ shipsafe scan

  CRITICAL  sql-injection/template-literal-in-query
  src/routes/users.ts:4
  User input from req.query is interpolated directly into SQL query.
  Fix: Use parameterized queries — db.query("SELECT * FROM users WHERE name = $1", [search])

What to Do Instead

Safe alternatives: parameterized queries with pg, Prisma, and Drizzle

// SAFE: parameterized query with pg driver
app.get("/users", async (req, res) => {
  const { search } = req.query;
  const result = await db.query(
    "SELECT * FROM users WHERE name = $1",
    [search]
  );
  res.json(result.rows);
});

// SAFE: Prisma tagged template (auto-parameterizes)
const users = await prisma.$queryRaw`
  SELECT * FROM users WHERE name = ${search}
`;
// Prisma converts this to: SELECT * FROM users WHERE name = $1

// SAFE: Drizzle query builder
const users = await db
  .select()
  .from(usersTable)
  .where(eq(usersTable.name, search));

Frequently Asked Questions

Does ShipSafe detect SQL injection in Prisma?

Yes. ShipSafe detects unsafe Prisma patterns like $queryRawUnsafe with string concatenation while correctly ignoring safe parameterized Prisma queries. Prisma-specific exceptions were added in v1.0.4.

Can ShipSafe find SQL injection in template literals?

Yes. ShipSafe has specific rules for detecting user input interpolated into SQL template literals, including cases where quotes around interpolation disable parameterization in Prisma and Drizzle.

How many SQL injection rules does ShipSafe have?

ShipSafe has 127 SQL injection detection rules covering raw SQL, ORM bypass, template literals, dynamic table names, stored procedures, second-order injection, and NoSQL injection.

Does ShipSafe detect NoSQL injection in MongoDB?

Yes. ShipSafe detects NoSQL injection patterns in MongoDB queries where user-controlled objects are passed directly to query operators like $where, $gt, and $regex.

Detect SQL Injection in Your Code

Install ShipSafe and scan your project in under 60 seconds.

npm install -g @shipsafe/cli

Related Security Categories