HIGH prototype pollutionfeathersjsdynamodb

Prototype Pollution in Feathersjs with Dynamodb

Prototype Pollution in Feathersjs with Dynamodb — how this specific combination creates or exposes the vulnerability

Prototype pollution in a Feathersjs service that uses Dynamodb can occur when user-controlled data is merged into objects that later influence property lookups or key construction, without sanitization. Feathersjs services often accept payloads that update parameters, query conditions, or DynamoDB expression attribute values. If an attacker can inject properties like __proto__, constructor.prototype, or other special keys into these payloads, and those keys are later used to build condition expressions or object keys, the application behavior can be altered in unexpected ways.

Consider a Feathersjs service configured with the DynamoDB adapter, where a patch or create operation merges request data into an update expression or condition. For example, an attacker might supply {"price": 100, "constructor.prototype.isAdmin": true}. If the service code builds expression attribute names or values using this object without validation, the injected property may affect how attribute names are resolved or how condition expressions are evaluated, potentially bypassing intended checks.

Dynamodb-specific risks emerge when user input influences key names in KeyConditionExpression or FilterExpression. If polluted properties are used to construct these expressions, an attacker might manipulate which items are retrieved or which conditions are applied. For instance, injecting a key that alters the attribute name in a condition could lead to reading or modifying items outside the intended partition key or sort key logic. This does not mean DynamoDB itself is compromised at the storage layer, but the application’s access patterns and authorization checks can be subverted.

Another vector is the use of expression attribute names that are derived from user input. If a service dynamically builds ExpressionAttributeNames using keys from request parameters, an injected prototype property could map to a reserved name or change the meaning of the expression. While DynamoDB does not evaluate JavaScript, the application logic that assembles the request becomes unreliable, potentially exposing sensitive items or enabling privilege escalation when combined with weak authorization checks.

In the context of middleBrick’s 12 security checks, this vector would be flagged under BOLA/IDOR and Input Validation, because improperly constrained user data is reaching query construction. The scanner does not modify code or block requests; it reports the finding with severity and remediation guidance, such as validating and sanitizing all inputs, using allowlists for property names, and avoiding direct concatenation of user data into expression strings.

Example of unsafe usage that can expose prototype pollution issues in a Feathersjs DynamoDB service:

// Unsafe: using user input directly in expression construction
app.service('items').hooks({
  before: {
    update: [context => {
      const { id, data } = context.params;
      // If data contains polluted keys, they may affect condition or key assembly
      const filterExp = data.filterExp || '';
      context.params.requestExpression = filterExp;
      return context;
    }]
  }
});

In this snippet, if data.filterExp includes injected properties, the resulting expression used by the adapter may behave unexpectedly. Always validate and sanitize input, and prefer explicit parameterization over dynamic assembly.

Dynamodb-Specific Remediation in Feathersjs — concrete code fixes

To mitigate prototype pollution when using Feathersjs with Dynamodb, ensure that user input is never directly merged into objects that influence key construction or expression assembly. Use strict validation, explicit allowlists, and avoid dynamic property access based on untrusted data. Below are concrete patterns and code examples that reduce risk.

1. Validate and sanitize incoming data before using it in DynamoDB expressions. Use a library or custom logic to remove or reject prototype pollution keys.

// Safe: sanitize payload before using in service logic
function sanitizePayload(input) {
  if (typeof input !== 'object' || input === null) return input;
  const safe = { ...input };
  // Remove common pollution keys
  delete safe.__proto__;
  delete safe.constructor;
  delete safe.prototype;
  return safe;
}

app.service('items').hooks({
  before: {
    create: [context => {
      context.data = sanitizePayload(context.data);
      return context;
    }]
  }
});

2. Use explicit parameterization for DynamoDB expression attribute names and values instead of dynamic concatenation. This prevents user-controlled keys from affecting expression structure.

// Safe: explicit expression names and values
const params = {
  TableName: 'Items',
  Key: {
    partitionKey: { S: 'items' },
    sortKey: { S: context.params.query.id || 'default' }
  },
  ExpressionAttributeNames: {
    '#price': 'price',
    '#stock': 'stock'
  },
  ExpressionAttributeValues: {
    ':minPrice': { N: '10' },
    ':inStock': { BOOL: true }
  },
  FilterExpression: '#price >= :minPrice AND #stock = :inStock'
};

// Execute with low-level DynamoDB client or via adapter with explicit params

3. Avoid using user input to construct key condition expressions dynamically. If filtering is required, map user values to predefined attributes using a controlled mapping.

// Safe: controlled mapping for filter attributes
const allowedFilters = {
  price: 'price',
  stock: 'stock'
};

function buildKeyCondition(attributeName, value) {
  const mappedName = allowedFilters[attributeName];
  if (!mappedName) throw new Error('Invalid filter attribute');
  return {
    KeyConditionExpression: `${mappedName} = :val`,
    ExpressionAttributeValues: { ':val': { N: String(value) } }
  };
}

const filter = buildKeyCondition('price', 20);
const queryParams = {
  TableName: 'Items',
  KeyConditionExpression: filter.KeyConditionExpression,
  ExpressionAttributeValues: filter.ExpressionAttributeValues
};

4. Enforce schema validation for payloads using libraries that reject unexpected properties, reducing the chance that polluted keys affect internal objects.

// Safe: schema validation with explicit shape
const Ajv = require('ajv');
const ajv = new Ajv();
const schema = {
  type: 'object',
  required: ['name', 'price'],
  properties: {
    name: { type: 'string' },
    price: { type: 'number' },
    stock: { type: 'integer' }
  },
  additionalProperties: false
};
const validate = ajv.compile(schema);

app.service('items').hooks({
  before: {
    create: [context => {
      if (!validate(context.data)) {
        throw new Error('Invalid payload');
      }
      return context;
    }]
  }
});

These practices help ensure that user-controlled data does not affect the structure of keys or expressions when interacting with Dynamodb through Feathersjs. Combine these measures with regular scanning using middleBrick to detect input validation and BOLA/IDOR findings early, and refer to the remediation guidance provided in scan reports.

Frequently Asked Questions

Can prototype pollution in Feathersjs with Dynamodb lead to unauthorized data access?
Yes, if user-controlled properties alter key names or filter expressions, an attacker may read or modify items they should not access. Always validate and parameterize inputs.
Does middleBrick fix prototype pollution vulnerabilities in Feathersjs?
middleBrick detects and reports these issues with severity and remediation guidance; it does not modify code or block requests. Apply the suggested input validation and expression parameterization patterns to remediate.