Sql Injection in Adonisjs with Api Keys
Sql Injection in Adonisjs with Api Keys — how this specific combination creates or exposes the vulnerability
SQL injection in AdonisJS when API keys are involved typically arises when an API key influences dynamic query construction without proper sanitization or parameterization. AdonisJS encourages the use of parameterized queries via the query builder or Lucid ORM to prevent injection; however, if a developer uses raw query building driven by values derived from API key metadata (such as tenant ID, scopes, or rate-limit counters), unsafe string concatenation can reintroduce injection risk.
Consider an example where an API key is decoded to extract a tenant identifier that is then interpolated into a raw SQL string:
const apiKey = request.headers().authorization?.replace('Bearer ', '');
const { tenantId } = await decryptAndValidateKey(apiKey);
const users = await Database.from('users').where('tenant_id', tenantId).select('*'); // safe if using bindings
const unsafe = await Database.rawQuery(`SELECT * FROM users WHERE tenant_id = '${tenantId}'`); // vulnerable
The unsafe variant concatenates tenantId directly into the SQL string. Even if the API key validation step appears robust, using the extracted value in a raw query without parameterization enables classic SQL injection (OWASP API Top 10:2023 A1: Broken Object Level Authorization can intersect with A3: Injection). Attackers who obtain or guess a valid API key might attempt to pivot by injecting crafted tenant identifiers to extract or modify data across tenant boundaries.
Another scenario involves dynamic ordering or filtering supplied by the client and applied to a query built on top of API key context. For instance, if an API key implies a default sort column and the developer builds an ORDER BY clause via string concatenation, injection can occur:
const sortColumn = request.input('sort', 'created_at');
const orderDirection = request.input('dir', 'ASC');
const query = `SELECT * FROM profiles ORDER BY ${sortColumn} ${orderDirection}`; // vulnerable
const results = await Database.rawQuery(query);
Here, the API key may determine which profiles are accessible (scoping), but unsanitized input used in ORDER BY enables injection. Because API keys are often treated as trusted, developers may overlook that the data derived from them can still be abused when combined with untrusted input.
LLM/AI Security checks included by middleBrick can help detect such patterns by analyzing request handling logic and flagging unsafe query construction near API key validation routines. These checks are part of the broader scan that reviews authentication handling and input validation, providing findings mapped to frameworks such as OWASP API Top 10.
Api Keys-Specific Remediation in Adonisjs — concrete code fixes
To remediate SQL injection risks tied to API key usage in AdonisJS, always use parameterized queries or the query builder rather than string interpolation. When scoping by API key metadata, bind values explicitly and validate inputs independently of the key.
Safe parameterized approach using the query builder:
const apiKey = request.headers().authorization?.replace('Bearer ', '');
const { tenantId } = await decryptAndValidateKey(apiKey);
const users = await Database.from('users').where('tenant_id', tenantId).select('*'); // safe
Safe parameterized approach using raw query with bindings:
const apiKey = request.headers().authorization?.replace('Bearer ', '');
const { tenantId } = await decryptAndValidateKey(apiKey);
const users = await Database.rawQuery('SELECT * FROM users WHERE tenant_id = ?', [tenantId]); // safe with bindings
For dynamic sorting, strictly allowlist column names and directions rather than interpolating:
const allowedColumns = ['created_at', 'updated_at', 'email', 'name'];
const allowedDirections = ['ASC', 'DESC'];
const sortColumn = allowedColumns.includes(request.input('sort', 'created_at')) ? request.input('sort', 'created_at') : 'created_at';
const orderDirection = allowedDirections.includes(request.input('dir', 'ASC').toUpperCase()) ? request.input('dir', 'ASC').toUpperCase() : 'ASC';
const users = await Database.from('profiles').orderBy(sortColumn, orderDirection).select('*'); // safe
Additionally, apply input validation schemas (e.g., using Joi or Yup) for any parameters influenced by API key context, and avoid treating API key metadata as inherently safe. For automation, the CLI tool (middlebrick scan <url>) can be integrated into development workflows to detect risky patterns; teams using CI/CD can adopt the GitHub Action to enforce security gates before deployment.
When monitoring at scale, the Pro plan’s continuous monitoring can flag regressions in query handling, and the MCP Server enables scanning API behaviors directly from AI coding assistants to catch insecure patterns early.
Related CWEs: inputValidation
| CWE ID | Name | Severity |
|---|---|---|
| CWE-20 | Improper Input Validation | HIGH |
| CWE-22 | Path Traversal | HIGH |
| CWE-74 | Injection | CRITICAL |
| CWE-77 | Command Injection | CRITICAL |
| CWE-78 | OS Command Injection | CRITICAL |
| CWE-79 | Cross-site Scripting (XSS) | HIGH |
| CWE-89 | SQL Injection | CRITICAL |
| CWE-90 | LDAP Injection | HIGH |
| CWE-91 | XML Injection | HIGH |
| CWE-94 | Code Injection | CRITICAL |