SQL injection from event payload in MySQL query in AWS Lambda

Critical Risk sql-injection
javascriptnodejsaws-lambdamysqlmysql2sqlinjection

What it is

SQL injection vulnerability where Lambda event data is concatenated into SQL strings passed to mysql/mysql2 query methods without parameterization, allowing crafted input to alter queries and potentially read or modify database data, bypass authorization, or execute destructive queries.

const mysql = require('mysql2');

exports.handler = async (event) => {
    const userId = event.pathParameters.id;
    const status = event.queryStringParameters.status;
    const { email } = JSON.parse(event.body);
    
    const connection = mysql.createConnection({
        host: 'database.example.com',
        user: 'dbuser',
        password: 'dbpass',
        database: 'mydb'
    });
    
    // VULNERABLE: String concatenation
    const query1 = `SELECT * FROM users WHERE id = ${userId}`;
    const [users] = await connection.promise().query(query1);
    
    // VULNERABLE: Template literal
    const query2 = `SELECT * FROM orders WHERE status = '${status}'`;
    await connection.promise().query(query2);
    
    // VULNERABLE: String concatenation
    const query3 = "SELECT * FROM accounts WHERE email = '" + email + "'";
    await connection.promise().query(query3);
    
    return {
        statusCode: 200,
        body: JSON.stringify(users)
    };
};
const mysql = require('mysql2');

exports.handler = async (event) => {
    const userId = event.pathParameters.id;
    const status = event.queryStringParameters.status;
    const { email } = JSON.parse(event.body);
    
    const connection = mysql.createConnection({
        host: 'database.example.com',
        user: 'dbuser',
        password: 'dbpass',
        database: 'mydb'
    });
    
    // SECURE: Parameterized query with ?
    const [users] = await connection.promise().execute(
        'SELECT * FROM users WHERE id = ?',
        [userId]
    );
    
    // SECURE: Parameterized query
    await connection.promise().execute(
        'SELECT * FROM orders WHERE status = ?',
        [status]
    );
    
    // SECURE: Parameterized query
    await connection.promise().execute(
        'SELECT * FROM accounts WHERE email = ?',
        [email]
    );
    
    return {
        statusCode: 200,
        body: JSON.stringify(users)
    };
};

💡 Why This Fix Works

The vulnerable code uses string concatenation and template literals to build SQL queries with Lambda event data, allowing SQL injection attacks. The fixed version uses parameterized queries with ? placeholders and the execute() method to safely bind parameters.

Why it happens

Building SQL queries by concatenating Lambda event data directly into query strings.

Root causes

String Concatenation in MySQL Queries

Building SQL queries by concatenating Lambda event data directly into query strings.

Not Using MySQL Prepared Statements

Using query() instead of execute() with placeholders in mysql2.

Fixes

1

Use Parameterized Queries with mysql2

Use execute() with ? placeholders for safe parameter binding.

View implementation
pool.execute('SELECT * FROM users WHERE id = ?', [userId])
2

Use Prepared Statements

Use mysql2's prepared statement support for repeated queries.

View implementation
const stmt = await connection.prepare('SELECT * FROM users WHERE email = ?')
await stmt.execute([email])
3

Validate Lambda Event Data

Validate and sanitize all event data before use in queries.

View implementation
Parse IDs as integers, validate email formats, check against allowlists

Detect This Vulnerability in Your Code

Sourcery automatically identifies sql injection from event payload in mysql query in aws lambda and many other security issues in your codebase.