HIGH sql injectionexpressapi keys

Sql Injection in Express with Api Keys

Sql Injection in Express with Api Keys — how this specific combination creates or exposes the vulnerability

SQL Injection in an Express API that uses API keys can occur when user-controlled data is concatenated into SQL queries, even when an API key is required for access control. The API key provides authentication—confirming who is making the request—but it does not enforce authorization or input validation. If the API key is valid but the endpoint builds SQL dynamically using string interpolation or concatenation, an attacker can supply malicious input that alters query logic.

For example, consider an endpoint that identifies a user by ID and returns profile information. If the ID is taken directly from request parameters and appended to a query string, an attacker can inject SQL fragments regardless of a valid API key. The API key check passes, but the database executes unintended commands, potentially bypassing row-level restrictions or extracting sensitive data.

In the context of middleBrick’s 12 security checks, this scenario maps to Authentication (API key presence), Input Validation (payload structure), and BOLA/IDOR (inadequate ownership checks). An unauthenticated attacker does not need to bypass the API key mechanism; they exploit the lack of input sanitization after authentication. Real-world patterns include using concatenated strings with template literals or query builders that do not enforce parameterized inputs. Without parameterized queries or strict schema validation, the API remains vulnerable despite having an API key gate.

A concrete risk pattern is when an endpoint reads an API key from headers, verifies it against a store, and then uses request parameters in a raw SQL string. This can lead to classic injection payloads such as ' OR 1=1 -- to bypass intended filters. The API key does not mitigate injection because it is checked separately from query construction. middleBrick’s detection of SQL Injection in Express with API keys focuses on runtime behavior: it observes whether inputs are sanitized or parameterized after authentication and whether error messages leak schema details.

Additionally, if the API key is leaked in logs, URLs, or error responses, it may aid an attacker in crafting targeted injection attempts. Proper handling requires treating API keys as credentials, storing them securely, and ensuring downstream SQL usage does not depend on raw user input. Middle-tier risks also arise when developers assume API keys alone are sufficient for data isolation, neglecting row-level policies and strict input validation.

Api Keys-Specific Remediation in Express — concrete code fixes

To remediate SQL Injection in Express when using API keys, enforce parameterized queries and strict input validation independent of authentication. API keys should be validated early in the request lifecycle, but they must not be conflated with safe data handling. Below are concrete examples demonstrating secure patterns.

Example 1: Secure endpoint with API key and parameterized queries

const express = require('express');
const mysql = require('mysql2/promise');
const app = express();

const pool = mysql.createPool({
  host: 'localhost',
  user: 'app_user',
  password: 'strong_password',
  database: 'app_db',
  waitForConnections: true,
  connectionLimit: 10,
});

const VALID_API_KEYS = new Set(['abc123', 'def456']);

app.get('/profile', async (req, res) => {
  const apiKey = req.headers['x-api-key'];
  if (!apiKey || !VALID_API_KEYS.has(apiKey)) {
    return res.status(401).json({ error: 'Unauthorized' });
  }

  const userId = req.query.userId;
  if (!userId || !/^[0-9]+$/.test(userId)) {
    return res.status(400).json({ error: 'Invalid input' });
  }

  try {
    const [rows] = await pool.execute(
      'SELECT id, username, email FROM users WHERE id = ?',
      [parseInt(userId, 10)]
    );
    if (rows.length === 0) {
      return res.status(404).json({ error: 'Not found' });
    }
    res.json(rows[0]);
  } catch (err) {
    console.error(err);
    res.status(500).json({ error: 'Internal server error' });
  }
});

app.listen(3000, () => console.log('Server running on port 3000'));

Example 2: Using environment variables for API keys and prepared statements

const express = require('express');
const { Pool } = require('pg');
const app = express();

const pool = new Pool({
  connectionString: process.env.DATABASE_URL,
});

const VALID_API_KEYS = new Set(process.env.API_KEYS?.split(',') || []);

app.get('/search', async (req, res) => {
  const apiKey = req.headers['x-api-key'];
  if (!apiKey || !VALID_API_KEYS.has(apiKey)) {
    return res.status(401).json({ error: 'Unauthorized' });
  }

  const term = req.query.q;
  if (typeof term !== 'string' || term.trim().length === 0) {
    return res.status(400).json({ error: 'Missing query' });
  }

  try {
    const query = {
      text: 'SELECT id, title, description FROM items WHERE title ILIKE $1 LIMIT 10',
      values: [`%${term}%`],
    };
    const { rows } = await pool.query(query);
    res.json(rows);
  } catch (err) {
    console.error(err);
    res.status(500).json({ error: 'Internal server error' });
  }
});

app.listen(3000, () => console.log('Server running on port 3000'));

Key practices

  • Validate and sanitize all inputs independently of API key checks.
  • Use parameterized queries or prepared statements to separate SQL logic from data.
  • Restrict API key scope and rotate them regularly; treat them like passwords.
  • Return generic error messages to avoid leaking schema or execution paths.
  • Apply regex or type checks to ensure inputs conform to expected formats.

These steps ensure that API keys fulfill their intended role—authentication—without introducing SQL Injection risks through improper query construction.

Related CWEs: inputValidation

CWE IDNameSeverity
CWE-20Improper Input Validation HIGH
CWE-22Path Traversal HIGH
CWE-74Injection CRITICAL
CWE-77Command Injection CRITICAL
CWE-78OS Command Injection CRITICAL
CWE-79Cross-site Scripting (XSS) HIGH
CWE-89SQL Injection CRITICAL
CWE-90LDAP Injection HIGH
CWE-91XML Injection HIGH
CWE-94Code Injection CRITICAL

Frequently Asked Questions

Does using API keys alone prevent SQL Injection in Express APIs?
No. API keys provide authentication but do not protect against SQL Injection. Injection occurs when user input is concatenated into SQL queries. Always use parameterized queries and input validation regardless of authentication.
How does middleBrick detect SQL Injection in Express APIs with API keys?
middleBrick runs black-box checks that observe whether inputs are parameterized after authentication. It tests injection payloads against authenticated endpoints and examines error handling, schema exposure, and query construction patterns to identify vulnerabilities.