aaronshaf/dynamodb-admin

Scans and Queries fail if certain attribute names are used

knicholson32 opened this issue · 3 comments

Bug Description

Attribute name are not properly escaped via ExpressionAttributeNames, resulting in the following response when performing a query or scan with a complex attribute name such as hwid.metric.fidelity:

Error loading data: Error: [ValidationException] ExpressionAttributeNames contains invalid key: Syntax error; key: "#hwid.metric.fidelity"

This occurs because the full attribute name is being used in ExpressionAttributeNames instead of a placeholder name that is sure to not contain reserved keywords or syntax errors:

ExpressionAttributeNames[`#${key}`] = key

should be

ExpressionAttributeNames[`#key${i}`] = key

where i is incremented for each key.

Proposed Fix

Only minor changes would be required to backend.js (in particular, the for loop starting on line 431):

Current code backend.js:431

for (const key in filters) {
  if (filters[key].type === 'N') {
    filters[key].value = Number(filters[key].value)
  }
  ExpressionAttributeNames[`#${key}`] = key
  ExpressionAttributeValues[`:${key}`] = filters[key].value
  if (indexBeingUsed && indexBeingUsed.KeySchema.find(
    (keySchemaItem) => keySchemaItem.AttributeName === key)
  ) {
    KeyConditionExpression.push(`#${key} ${filters[key].operator} :${key}`)
  } else {
    ExpressionAttributeNames[`#${key}`] = key
    ExpressionAttributeValues[`:${key}`] = filters[key].value
    FilterExpressions.push(`#${key} ${filters[key].operator} :${key}`)
  }
}

Proposed Fix backend.js:431

let i = 0;
for (const key in filters) {
  if (filters[key].type === 'N') {
    filters[key].value = Number(filters[key].value)
  }
  ExpressionAttributeNames[`#key${i}`] = key
  ExpressionAttributeValues[`:key${i}`] = filters[key].value
  if (indexBeingUsed && indexBeingUsed.KeySchema.find(
    (keySchemaItem) => keySchemaItem.AttributeName === key)
  ) {
    KeyConditionExpression.push(`#key${i} ${filters[key].operator} :key${i}`)
  } else {
    ExpressionAttributeNames[`#key${i}`] = key
    ExpressionAttributeValues[`:key${i}`] = filters[key].value
    FilterExpressions.push(`#key${i} ${filters[key].operator} :key${i}`)
  }
  i = i + 1;
}

I would not mind making a pull request for these changes if that is easier.

rchl commented

Please feel free to create a PR.

rchl commented

Fixed by #103