Mass Assignment in Feathersjs with Dynamodb
Mass Assignment in Feathersjs with Dynamodb — how this specific combination creates or exposes the vulnerability
Mass assignment occurs when a service accepts user-supplied data and writes it directly to a data source without filtering which fields can be set. In a Feathersjs application using Dynamodb as the persistence layer, this typically happens through a create or patch call that passes an unfiltered payload into a DynamoDB PutItem or UpdateItem request. Feathersjs hooks often forward data straight to the service, and if the service uses a low-level DynamoDB client without a strict schema or field allowlist, an attacker can inject unexpected attributes such as metadata flags, administrative roles, or conditional expression tokens that influence how DynamoDB processes the write.
Because DynamoDB stores schemaless JSON-like documents, unexpected keys are accepted silently. This enables attackers to set reserved or sensitive attributes (e.g., aws:Reserved, custom policy fields, or versioning keys) that the application logic did not intend to be user-writable. If the application later reads those attributes to make authorization or business decisions, the injected values can bypass controls. For example, an attacker could supply { "role": "admin", "shouldImpersonate": true } in a user profile update, and if the hook does not strip or reject these fields, the DynamoDB record will reflect them.
The risk is compounded when combined with other checks in the 12-scan suite, such as Property Authorization and Input Validation. Without an allowlist strategy, the attack surface grows as new fields are added to the client model but not enforced server-side. An OpenAPI spec that does not tightly constrain request properties can further mask the issue, because schema validation may be absent or permissive. This is why runtime findings from tools that compare the spec to actual behavior are important for surfacing unchecked writable properties.
Dynamodb-Specific Remediation in Feathersjs — concrete code fixes
Remediation focuses on explicit field filtering and schema enforcement in Feathersjs hooks before interacting with DynamoDB. Use a whitelist approach to pick only the fields that are safe to update, and validate input types and lengths to reduce injection risk. Below are concrete code examples that demonstrate how to secure both create and patch operations when using the AWS SDK for JavaScript v3 with DynamoDB in a Feathersjs service.
Example: Securing create with a whitelist
const { DynamoDBClient, PutItemCommand } = require('@aws-sdk/client-dynamodb');
const client = new DynamoDBClient({ region: 'us-east-1' });
function safeCreate(data) {
const ALLOWED = ['name', 'email', 'preferences'];
const item = {};
ALLOWED.forEach((key) => {
if (data[key] !== undefined) {
// Basic scalar validation can be added here
item[key] = { S: String(data[key]) };
}
});
return item;
}
app.service('todos').hooks({
before: {
create: [context => {
context.data = safeCreate(context.data);
return context;
}]
}
});
Example: Securing patch with partial updates and expression attribute values
function buildUpdateExpression(allowed, data) {
const updateParts = [];
const expressionAttrValues = {};
const keys = Object.keys(data);
keys.forEach((key, idx) => {
if (!allowed.includes(key)) return;
const placeholder = `#val${idx}`;
const attrPlaceholder = `:val${idx}`;
updateParts.push(`${key} = ${placeholder}`);
expressionAttrValues[placeholder] = { S: String(data[key]) };
expressionAttrValues[attrPlaceholder] = { S: String(data[key]) };
});
return {
UpdateExpression: 'SET ' + updateParts.join(', '),
ExpressionAttributeNames: Object.keys(expressionAttrValues).reduce((acc, k) => {
acc[k] = k; return acc;
}, {}),
ExpressionAttributeValues: expressionAttrValues
};
}
app.service('todos').hooks({
before: {
patch: [context => {
const ALLOWED = ['name', 'email', 'preferences'];
const update = buildUpdateExpression(ALLOWED, context.data);
context.params.request = {
TableName: 'Todos',
Key: { id: { S: context.id } },
...update
};
// Replace low-level call with service method or SDK wrapper as appropriate
return context;
}]
}
});
Additional DynamoDB hardening tips
- Define a JSON schema for your entities and validate payloads before constructing DynamoDB expressions.
- Use ConditionExpression for critical constraints (e.g., attribute existence) rather than relying solely on application logic.
- Avoid passing raw user input into ExpressionAttributeNames; map known safe names instead.
- Combine these hooks with Property Authorization checks to ensure users can only modify fields they are permitted to change.
These steps ensure that even if a client sends extra fields, they are ignored by the DynamoDB write operations, effectively mitigating mass assignment in this stack.
Related CWEs: propertyAuthorization
| CWE ID | Name | Severity |
|---|---|---|
| CWE-915 | Mass Assignment | HIGH |