00:00

#0306

Batch Insert Builder

Medium+100 XPA03:2021 InjectionCWE-89
SQL InjectionBatch

Scenario

A user-import feature accepts an array of { name, email } records and builds a single bulk INSERT statement for efficiency.

The buggy implementation concatenates every name and email directly into the VALUES list. Any injected quote in a name or email can break out of the string literal and execute arbitrary SQL.

A single malicious record like { name: "x'); DROP TABLE users;--", email: "e@f.com" } can destroy the entire table at import time.

Batch inserts are often written once and rarely reviewed. A single un-parameterized bulk import can give an attacker the ability to inject SQL into thousands of rows simultaneously, or drop critical tables during a data migration.

Your Tasks

  1. Fix buildBatchInsert so every value is passed as a parameter rather than concatenated inline.
  2. Generate numbered placeholders ($1,$2),($3,$4),... for each record.
  3. The params array must contain all values flattened in order: [name1, email1, name2, email2, ...].
  4. An empty records array should return { sql: "INSERT INTO users (name,email) VALUES ", params: [] }.

Examples

Example 1Injection in name blocked

buildBatchInsert([{name:"x'); DROP TABLE users;--", email:"e@f.com"}])
// FIX → { sql: '...VALUES ($1,$2)', params: ["x'); DROP...", 'e@f.com'] }

Example 2Two clean records

buildBatchInsert([{name:'alice',email:'a@b.com'},{name:'bob',email:'b@c.com'}])
// → { sql: '...VALUES ($1,$2),($3,$4)', params: ['alice','a@b.com','bob','b@c.com'] }

Constraints

  • Only edit the function body — do not change the function signature.
  • The returned sql must use sequential $N placeholders starting at $1.
  • Params must be flattened: name first, then email, for each record in input order.
  • No external packages.

Hint

References

solution.js
Ln 1, Col 1UTF-8JavaScript
Sandbox ready
0/0/0not run