HIGH pii leakageadonisjsdynamodb

Pii Leakage in Adonisjs with Dynamodb

Pii Leakage in Adonisjs with Dynamodb — how this specific combination creates or exposes the vulnerability

AdonisJS is a Node.js web framework that encourages structured request handling and model-based interactions. When integrating AdonisJS with Amazon DynamoDB as the persistence layer, PII leakage can occur through several realistic patterns tied to how data is modeled, serialized, and returned from DynamoDB.

DynamoDB stores items as attribute-value maps, which means fields containing sensitive information—such as email, phone, or government identifiers—reside in the same item as operational data. If query or scan responses in AdonisJS controllers directly forward DynamoDB output to clients (e.g., JSON HTTP responses), any PII present in those attributes is exposed. This commonly happens when models or service layers do not explicitly filter or transform sensitive fields before serialization.

Another vector arises from incomplete or misconfigured DynamoDB queries. For example, using a query without a precise key condition may unintentionally return multiple items, increasing the likelihood of exposing more PII than intended. Additionally, DynamoDB supports sparse indexes; if an index omits sensitive attributes but the base table includes them, developers might mistakenly assume the index is safe, whereas runtime reads from the main table can still expose PII when referenced indirectly.

AdonisJS-specific risks include overly broad model definitions that map 1:1 to DynamoDB item structures. Without explicit getters or serialization logic, attributes like user_phone or ssn can appear directly in JSON responses. In a typical API route, code such as return User.query().where('email', email).first() might return the full DynamoDB item, including raw PII fields, to the client.

Furthermore, logging or error handling in AdonisJS that inadvertently includes DynamoDB item contents can expose PII in server logs or error traces, especially when debugging information is enabled in production. Since DynamoDB responses include metadata such as ConsumedCapacity, developers might inadvertently serialize the entire response object rather than the relevant data subset.

To mitigate these risks, treat DynamoDB items as raw data records and enforce strict serialization in AdonisJS. Use model fields or view models to expose only necessary attributes, and avoid passing DynamoDB responses directly to HTTP responses. Apply consistent input validation and output filtering in controller methods to ensure PII is either redacted or transformed before leaving the application layer.

Dynamodb-Specific Remediation in Adonisjs — concrete code fixes

Remediation focuses on controlling what leaves the server and ensuring DynamoDB interactions in AdonisJS never expose PII inadvertently. Below are concrete patterns and code examples tailored for AdonisJS with DynamoDB.

1. Explicit projection and attribute filtering

Use DynamoDB ProjectionExpression to retrieve only required, non-sensitive attributes. In AdonisJS, this means configuring the DynamoDB client call within your model or service to limit returned fields.

const { DynamoDBClient, QueryCommand } = require('@aws-sdk/client-dynamodb');
const client = new DynamoDBClient({ region: 'us-east-1' });

async function getUserPublicFields(email) {
  const command = new QueryCommand({
    TableName: process.env.USERS_TABLE,
    IndexName: 'email-index',
    KeyConditionExpression: 'email = :email',
    ExpressionAttributeValues: {
      ':email': { S: email }
    },
    ProjectionExpression: 'user_id, username, created_at' // excludes email, phone, ssn
  });
  const response = await client.send(command);
  return response.Items;
}

2. Model-level serialization with getters

Define explicit getters in your AdonisJS model to control serialization. This ensures that whenever the model is converted to JSON, sensitive fields are omitted or masked.

const BaseModel = use('Model');

class User extends BaseModel {
  static get computed () {
    return ['publicProfile'];
  }

  toJSON() {
    const data = this.serialize();
    // Remove PII fields before sending
    delete data.email;
    delete data.phone;
    delete data.ssn;
    return data;
  }

  getPublicProfile() {
    return {
      user_id: this.user_id,
      username: this.username,
      created_at: this.created_at
    };
  }
}

module.exports = User;

3. Service layer transformation

Create a service that transforms DynamoDB responses into safe output objects, centralizing the logic and preventing accidental PII exposure across routes.

class UserService {
  async getUserById(userId) {
    const command = new GetCommand({
      TableName: process.env.USERS_TABLE,
      Key: { user_id: { S: userId } },
      ProjectionExpression: 'user_id, username, settings' // excludes contact info
    });
    const { Item } = await dynamo.send(command);
    // Transform to plain object without PII
    return {
      user_id: Item.user_id.S,
      username: Item.username.S,
      settings: JSON.parse(Item.settings.S || '{}')
    };
  }
}

4. Input validation and least privilege queries

Validate incoming query parameters rigorously and avoid scanning entire tables. Use conditional queries with key expressions to minimize the dataset returned by DynamoDB.

async function getUserByEmail(email) {
  if (!isValidEmail(email)) {
    throw new Error('Invalid email format');
  }
  const command = new QueryCommand({
    TableName: process.env.USERS_TABLE,
    KeyConditionExpression: 'email = :email',
    ExpressionAttributeValues: { ':email': { S: email } },
    Limit: 1
  });
  const { Items } = await client.send(command);
  return Items ? Items[0] : null;
}

5. Redact logs and error objects

Ensure that logging utilities in AdonisJS do not serialize full DynamoDB items. Use selective logging and scrub sensitive fields explicitly.

const logger = use('Logger');

app.exceptionHandler(async (error, { response }) => {
  if (error.name === 'ResourceNotFoundException') {
    logger.info('Resource not found', { table: process.env.USERS_TABLE });
    return response.status(404).send({ message: 'Not found' });
  }
  // Avoid logging full error.meta or DynamoDB items
  logger.error('Request error', { code: error.code, path: error.path });
  response.status(500).send({ error: 'Internal error' });
});

By combining projection, serialization, and service-layer transformation, AdonisJS applications can safely work with DynamoDB while minimizing the risk of PII leakage.

Related CWEs: dataExposure

CWE IDNameSeverity
CWE-200Exposure of Sensitive Information HIGH
CWE-209Error Information Disclosure MEDIUM
CWE-213Exposure of Sensitive Information Due to Incompatible Policies HIGH
CWE-215Insertion of Sensitive Information Into Debugging Code MEDIUM
CWE-312Cleartext Storage of Sensitive Information HIGH
CWE-359Exposure of Private Personal Information (PII) HIGH
CWE-522Insufficiently Protected Credentials CRITICAL
CWE-532Insertion of Sensitive Information into Log File MEDIUM
CWE-538Insertion of Sensitive Information into Externally-Accessible File HIGH
CWE-540Inclusion of Sensitive Information in Source Code HIGH

Frequently Asked Questions

Can DynamoDB sparse indexes be relied upon to protect PII in AdonisJS?
No. Sparse indexes in DynamoDB only include items that have the indexed attribute; they do not prevent access to PII in the base table. Always apply explicit attribute filtering in AdonisJS to avoid exposing sensitive data.
Does middleBrick detect PII leakage risks in AdonisJS integrations with DynamoDB?
Yes. middleBrick scans API endpoints and can identify insecure data exposure patterns, including PII leakage in responses that originate from DynamoDB-backed AdonisJS services. Use the CLI (middlebrick scan ) or Web Dashboard to review findings and follow the provided remediation guidance.