Type Confusion in Express with Dynamodb
Type Confusion in Express with Dynamodb — how this specific combination creates or exposes the vulnerability
Type confusion in an Express application that uses DynamoDB can occur when data supplied by the client is deserialized into JavaScript values and then used to construct DynamoDB query parameters without strict type validation. Because JavaScript is dynamically typed, a value that appears to be a string or number can be replaced at runtime with an object, causing the SDK to serialize the input differently than expected.
For example, an endpoint that accepts a numeric id parameter and builds a GetItem request may receive a crafted payload that replaces the numeric value with an object like { S: { username: "attacker" } }. If the server passes this directly to docClient.get, the type mismatch leads to unexpected behavior, such as querying with malformed key schemas or bypassing intended access controls that rely on type-specific conditions.
In the context of the 12 checks run by middleBrick, this manifests as an input validation and property authorization finding. The scan tests unauthenticated endpoints that accept user-controlled input used in DynamoDB operations and checks whether type constraints are enforced before the data reaches the database layer. Without strict schema validation, an attacker may supply nested objects or unexpected attribute structures that confuse equality checks, leading to inconsistent authorization decisions or information leakage through error messages.
An Express route that builds a DynamoDB UpdateItem request from parsed JSON body illustrates the risk. If numeric fields like version are not validated, an object injection can change the update expression or condition expression, potentially modifying different items than intended or elevating privileges by altering administrative flags.
const params = {
TableName: 'accounts',
Key: { id: { S: String(req.body.id) } },
UpdateExpression: 'SET balance = :balance',
ExpressionAttributeValues: {
':balance': { N: String(req.body.balance) }
}
};
docClient.update(params, (err, data) => { /* ... */ });
If req.body.id is an object instead of a string, the conversion String(req.body.id) yields '[object Object]', causing the key to become invalid and exposing internal handling logic. middleBrick detects such patterns by correlating OpenAPI definitions with runtime payloads and flags endpoints where DynamoDB key construction depends on unchecked input types.
Dynamodb-Specific Remediation in Express — concrete code fixes
To prevent type confusion when Express routes interact with DynamoDB, validate and sanitize all incoming data before constructing SDK parameters. Use a schema validation library to enforce types and reject objects where primitives are expected. Ensure that numeric values remain numbers, strings remain strings, and that no nested objects are injected into key attributes.
Below is a secure example that validates input types explicitly before building DynamoDB parameters. This approach avoids implicit conversions and ensures the SDK receives the expected attribute value shapes.
const { DynamoDB } = require('aws-sdk');
const { body, param } = require('express-validator');
const docClient = new DynamoDB.DocumentClient();
app.put('/accounts/:id', [
param('id').isString().isLength({ min: 1 }),
body('balance').isNumeric().toFloat()
], async (req, res) => {
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.status(400).json({ errors: errors.array() });
}
const params = {
TableName: 'accounts',
Key: { id: req.params.id },
UpdateExpression: 'SET balance = :balance',
ExpressionAttributeValues: {
':balance': req.body.balance
}
};
try {
const data = await docClient.update(params).promise();
res.json(data);
} catch (err) {
res.status(500).json({ error: err.message });
}
});
For read operations using GetItem, enforce that the key schema matches the table definition. If the table uses a composite primary key, validate each component individually and avoid concatenating or transforming user input into key objects.
const params = {
TableName: 'profiles',
Key: {
userId: { S: String(req.query.userId) },
timestamp: { N: String(req.query.timestamp) }
}
};
docClient.get(params, (err, data) => { /* ... */ });
middleBrick’s scans include input validation checks that verify whether DynamoDB key construction is protected against type confusion. The tool also correlates findings with compliance mappings such as OWASP API Top 10 and SOC2 controls, helping you prioritize fixes without implementing fixes directly.
When using the middleBrick CLI (middlebrick scan <url>) or the GitHub Action to add API security checks to your CI/CD pipeline, you can fail builds when insecure patterns are detected in unauthenticated scans, encouraging early remediation before deployment.
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 |