HIGH prototype pollutionfiberdynamodb

Prototype Pollution in Fiber with Dynamodb

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

Prototype pollution in a Fiber application that interacts with DynamoDB can occur when user-controlled input is merged into objects that later influence DynamoDB construction, condition expressions, or attribute values. In JavaScript, objects inherit properties from their prototypes; if an attacker can add or modify properties on Object.prototype or other shared prototypes, those properties can appear unexpectedly during object iteration, serialization, or comparison. When the application builds DynamoDB parameters (such as ExpressionAttributeValues or UpdateExpression) using polluted objects, the resulting parameters may include unintended attribute names or values.

For example, if a route handler directly copies req.body into an object used to construct a DynamoDB update, a polluted property like __proto__ or constructor can alter the shape of the object or be interpreted as a DynamoDB attribute name. Consider an update that uses a key built from user input without strict validation:

const updateParams = {
  TableName: 'Items',
  Key: { id: { S: req.params.id } },
  UpdateExpression: 'SET #name = :name, #tags = list_append(if_not_exists(#tags, :empty), :newTags)',
  ExpressionAttributeNames: {
    '#name': req.body.fieldName,
    '#tags': req.body.tagsField
  },
  ExpressionAttributeValues: {
    ':name': { S: req.body.name },
    ':newTags': { L: req.body.tags.map(t => ({ S: t })) },
    ':empty': { L: [] }
  }
};

If req.body.fieldName or req.body.tagsField contains a polluted property (e.g., constructor), the attacker can influence which DynamoDB attribute names are used or attempt to bypass intended update paths. This can lead to conditions such as overwriting critical attributes, bypassing conditional checks, or causing unexpected behavior in downstream logic that interprets the response.

Additionally, when constructing query or scan filters using user input, polluted properties can inject extra condition expressions or attribute names. For example, merging request query parameters into a filter object without sanitization might introduce constructor or hasOwnProperty as attribute names, which can change the semantics of the filter. Although DynamoDB itself does not evaluate JavaScript prototypes, the application logic that builds and interprets these parameters may misinterpret them, leading to information disclosure or privilege escalation patterns aligned with BOLA/IDOR or Property Authorization failures.

In the context of middleBrick’s 12 security checks, this scenario maps to Input Validation and Property Authorization: untrusted input used to build DynamoDB parameters without strict schema validation increases the risk of prototype pollution affecting authorization boundaries. The scanner will flag missing type checks, missing allowlists for attribute names, and unsafe merging of user data into objects that feed into AWS SDK calls.

Dynamodb-Specific Remediation in Fiber — concrete code fixes

Remediation focuses on strict input validation, avoiding direct use of user-controlled objects for DynamoDB parameter construction, and using allowlists for attribute names. Prefer explicit mapping of allowed fields and avoid merging user input into shared object prototypes.

Use explicit parameter construction

Instead of passing user objects directly into DynamoDB expressions, map known-safe fields explicitly:

const allowedFields = new Set(['name', 'tags', 'status', 'updatedAt']);

function buildUpdateParams(req) {
  const updateParams = {
    TableName: 'Items',
    Key: { id: { S: req.params.id } },
    UpdateExpression: 'SET #name = :name',
    ExpressionAttributeNames: {},
    ExpressionAttributeValues: {}
  };

  if (allowedFields.has(req.body.fieldName)) {
    updateParams.ExpressionAttributeNames['#name'] = req.body.fieldName;
    updateParams.ExpressionAttributeValues[':name'] = { S: req.body.name };
  } else {
    throw new Error('Invalid field name');
  }

  if (Array.isArray(req.body.tags)) {
    updateParams.ExpressionAttributeNames['#tags'] = req.body.tagsField || 'tags';
    updateParams.ExpressionAttributeValues[':newTags'] = {
      L: req.body.tags.map(t => ({ S: t }))
    };
    updateParams.ExpressionAttributeValues[':empty'] = { L: [] };
    updateParams.UpdateExpression = 'SET #name = :name, #tags = list_append(if_not_exists(#tags, :empty), :newTags)';
  }

  return updateParams;
}

Validate and sanitize attribute names

When using ExpressionAttributeNames, ensure the provided logical names are validated against an allowlist and never directly reflect untrusted keys:

const validAttributeNames = { name: true, tags: true, status: true };

function safeAttributeName(userKey) {
  if (!validAttributeNames[userKey]) {
    throw new Error('Invalid attribute name');
  }
  return userKey;
}

// Usage
const attrName = safeAttributeName(req.body.fieldName);
const updateParams = {
  TableName: 'Items',
  Key: { id: { S: req.params.id } },
  UpdateExpression: `SET #${attrName} = :val`,
  ExpressionAttributeNames: { ['#' + attrName]: attrName },
  ExpressionAttributeValues: { ':val': { S: req.body.value } }
};

Avoid prototype pollution vectors in request handling

Sanitize incoming JSON to remove or ignore dangerous properties before any object merging. In Fiber, you can use middleware to clean payloads:

app.post('/items/:id', async (req, res) => {
  const cleanBody = {};
  if (typeof req.body.name === 'string') cleanBody.name = req.body.name;
  if (Array.isArray(req.body.tags)) cleanBody.tags = req.body.tags;
  // Proceed with cleanBody instead of req.body
  const params = buildUpdateParams(cleanBody);
  // Execute DynamoDB update with params
  res.json({ message: 'ok' });
});

These patterns reduce the risk that prototype-polluted properties influence DynamoDB parameter construction, condition expressions, or attribute naming, aligning with secure input validation and property authorization practices.

Frequently Asked Questions

Can prototype pollution affect DynamoDB queries even if the database itself is not vulnerable?
Yes. Prototype pollution affects the application logic that builds DynamoDB parameters, condition expressions, and attribute names. An attacker can manipulate which attributes are read or updated by influencing how the application constructs requests, potentially bypassing authorization checks or exposing unintended data.
Does using DynamoDB document client or marshall/unmarshall APIs prevent prototype pollution?
No. The AWS SDK marshalling does not protect against prototype pollution in your JavaScript objects. If you construct input objects using polluted sources (e.g., merging req.body into parameter objects), the pollution is preserved in the marshalling step and can affect attribute names and values passed to DynamoDB.