Nosql Injection in Adonisjs with Dynamodb
Nosql Injection in Adonisjs with Dynamodb — how this specific combination creates or exposes the vulnerability
AdonisJS is a Node.js web framework that encourages structured request handling and validation. When building endpoints that interact with Amazon DynamoDB, developers often pass request parameters directly into DynamoDB operations without adequate sanitization or type enforcement. This creates a NosQL Injection surface because DynamoDB’s query and scan APIs interpret expression attribute values and key conditions in a structured but flexible way.
In AdonisJS, a typical handler might destructure query parameters and forward them to a DynamoDB DocumentClient or raw SDK calls. If these values are not strictly validated, an attacker can supply values that alter the logical structure of the request. For example, a string intended to represent a partition key might contain JSON-like fragments or conditional expressions that DynamoDB parses, leading to unauthorized data retrieval or enumeration.
Because DynamoDB does not support server-side prepared statements in the same way relational databases do, the burden of sanitization falls on the application. AdonisJS middleware or route validation schemas may not enforce strict type checks for DynamoDB-specific constraints, allowing injection through operators such as BETWEEN, begins_with, or by injecting reserved keywords into expression attribute names. The unauthenticated attack surface that middleBrick tests includes input validation checks that can flag these risks when scanning an exposed endpoint.
Consider a search endpoint that accepts a userId and a statusFilter. If the implementation builds a DynamoDB query by concatenating user input into the KeyConditionExpression, an attacker could provide userId as user123 AND attribute_exists(admin) --. While DynamoDB may reject malformed expressions, crafted inputs can still traverse to scan operations or conditional writes, leading to data exposure or privilege escalation patterns covered by BOLA/IDOR checks.
In the context of middleBrick’s 12 security checks, such issues are surfaced under Input Validation, Property Authorization, and Unsafe Consumption. The scanner does not alter runtime behavior; it detects deviations from secure patterns and provides remediation guidance. Real-world references include injection patterns analogous to CVE-classic injection vectors, mapped loosely to OWASP API Top 10 #1 (Broken Object Level Authorization) when overlaid on API semantics.
Dynamodb-Specific Remediation in Adonisjs — concrete code fixes
Remediation centers on strict validation, type coercion, and avoiding dynamic construction of expression strings. Use AdonisJS schema validation to enforce expected types and whitelist values before they reach DynamoDB operations. Prefer parameterized expressions with placeholders and let the SDK handle value substitution safely.
Example: Unsafe dynamic query
// UNSAFE: directly interpolating request input into DynamoDB expression
const { userId, statusFilter } = request.params()
const params = {
TableName: 'Tasks',
KeyConditionExpression: `userId = :uid AND status = :status`,
ExpressionAttributeValues: {
':uid': userId,
':status': statusFilter
}
}
const data = await dynamoDb.send(new QueryCommand(params))
Example: Secure parameterized query with Zod schema validation
import { schema } from '@ioc:AdonisJS/Core/Validator'
import { DynamoDBClient, QueryCommand } from '@aws-sdk/client-dynamodb'
const TaskQuerySchema = schema.create({
userId: schema.string({ trim: true, escape: false }, [
(value, { reporter }) => {
if (!/^[a-zA-Z0-9_-]{3,64}$/.test(value)) {
reporter.report('userId', 'regex', 'Invalid format')
}
}
]),
statusFilter: schema.enum(['active', 'completed', 'archived'])
})
export default class TasksController {
public async show({ request, response }) {
const validated = await request.validate({ schema: TaskQuerySchema })
const params = {
TableName: 'Tasks',
KeyConditionExpression: 'userId = :uid AND status = :status',
ExpressionAttributeValues: {
':uid': { S: validated.userId },
':status': { S: validated.statusFilter }
}
}
const dynamoDb = new DynamoDBClient({})
const data = await dynamoDb.send(new QueryCommand(params))
return response.json(data.Items)
}
}
This approach ensures that userId conforms to a strict pattern and statusFilter is limited to known values, preventing injection through malformed expressions. The use of :uid and :status placeholders ensures that the DynamoDB DocumentClient treats them strictly as values, not executable fragments.
For scan operations, avoid building FilterExpression from raw input. Instead, map user-provided filters to predefined safe attributes and use expression attribute names only when necessary, with a strict allowlist. middleBrick’s Input Validation checks can highlight endpoints where dynamic expression building occurs without safeguards.
Additional hardening includes enforcing least-privilege IAM roles for the DynamoDB credentials used by AdonisJS, enabling CloudTrail logging for auditability, and monitoring for anomalous query patterns. While these are operational controls, they complement code-level fixes and are often highlighted in compliance reports available through the Pro plan when integrating middleBrick into CI/CD pipelines.