HIGH data exposurefeathersjsdynamodb

Data Exposure in Feathersjs with Dynamodb

Data Exposure in Feathersjs with Dynamodb — how this specific combination creates or exposes the vulnerability

FeathersJS is a popular framework for building JavaScript APIs with a service-oriented architecture. When using Dynamodb as the database adapter, data exposure risks arise from misconfigured service queries, insufficient authorization checks, and the default behavior of returning full database records. Unlike relational databases, Dynamodb stores data as semi-structured items, which can include nested attributes, secondary indexes, and large fields. If a FeathersJS service does not explicitly limit returned fields or validate the result set, sensitive data such as internal identifiers, administrative flags, or personal information may be returned to the client.

The combination of FeathersJS hooks and Dynamodb query patterns can inadvertently expose data when developers rely on the framework to enforce access controls without implementing explicit field-level restrictions. For example, a service defined with find or get

Real-world attack patterns include enumeration via predictable IDs in get endpoints, where an attacker iterates through identifiers to locate records belonging to other users. Sensitive metadata such as creation timestamps, status flags, or internal processing fields may be included in Dynamodb responses and exposed through FeathersJS services that do not sanitize output. Another scenario involves the misuse of DynamoDB Scan operations within FeathersJS services, which can read every item in a table and return unfiltered data when access controls are not enforced at the query level.

Compliance frameworks such as OWASP API Top 10 categorize this as a broken object level authorization issue when data exposure occurs due to insufficient access controls. In PCI-DSS and GDPR contexts, exposure of personal data through unsecured API endpoints can result in regulatory implications. middleBrick detects these patterns during black-box scanning by analyzing the unauthenticated attack surface of FeathersJS services that interact with Dynamodb, identifying endpoints that return sensitive fields without proper authorization or field filtering.

To mitigate these risks, developers must explicitly define which fields are allowed in responses and enforce authorization at the record level. MiddleBrick scans can highlight endpoints where full item retrieval is possible and where DynamoDB query patterns may bypass intended restrictions. The scanner does not modify code but provides prioritized findings with remediation guidance to help teams secure their API surfaces.

Dynamodb-Specific Remediation in Feathersjs — concrete code fixes

Remediation focuses on controlling which attributes are returned and ensuring that every query respects user permissions. In FeathersJS, this involves customizing service logic and hooks to filter fields and validate ownership of records before returning data.

1. Explicit field selection using projection expressions

When querying Dynamodb, use projection expressions to return only required attributes. This reduces the risk of exposing sensitive fields such as internalNotes, ssn, or passwordHash. Below is an example of a custom FeathersJS hook that modifies the query to include a projection expression.

// src/hooks/select-fields.hooks.js
module.exports = function selectFields(allowedFields) {
  return async context => {
    const { params } = context;
    if (params.query) {
      const { $select, ...query } = params.query;
      const projectionExpression = allowedFields.join(',');
      params.body = params.body || {};
      params.body.ProjectionExpression = projectionExpression;
      // Preserve non-attribute query parameters
      params.query = query;
    }
    return context;
  };
};

// Usage in a FeathersJS service
const selectPublicFields = selectFields(['userId', 'email', 'profileName']);
service.hooks.push(selectPublicFields);

2. Record-level ownership checks in before hooks

Ensure that users can only access records they own by adding a before hook that enforces row-level security. This example assumes the user ID is available in params.user.sub.

// src/hooks/ownership-check.hooks.js
module.exports = function ownershipCheck() {
  return async context => {
    const { user } = context.params;
    if (user && user.sub) {
      context.params.query = context.params.query || {};
      // For get requests, validate owner ID matches
      if (context.id) {
        context.params.query.ownerId = user.sub;
      } else if (context.params.query) {
        context.params.query.FilterExpression = '(ownerId = :uid) AND ' +
          (context.params.query.FilterExpression || 'attribute_exists(id)');
        context.params.query.ExpressionAttributeValues = {
          ':uid': user.sub,
          ...context.params.query.ExpressionAttributeValues
        };
      }
    }
    return context;
  };
};

3. Avoid returning sensitive fields in get responses

Customize the get method to exclude internal attributes by transforming the result before sending it to the client. This is particularly important when using Dynamodb document clients that return entire items.

// src/services/secure-data.service.js
const { Service } = require('feathersjs');
const dynamodb = require('aws-sdk/clients/dynamodb');
const docClient = new dynamodb.DocumentClient();

class SecureDataService extends Service {
  async get(id, params) {
    const result = await docClient.get({
      TableName: process.env.DYNAMODB_TABLE,
      Key: { id }
    }).promise();

    const item = result.Item;
    if (!item) {
      throw new Error('Not found');
    }

    // Explicitly return only safe fields
    return {
      id: item.id,
      email: item.email,
      displayName: item.displayName,
      createdAt: item.createdAt
    };
  }
}

module.exports = function init() {
  const app = this;
  app.use('/secure-data', new SecureDataService());
};

4. Limit use of Scan operations and enforce filtering

Prefer query operations over Scan to avoid full table reads. If Scan is necessary, apply strict filter expressions and projection expressions to limit returned data.

// src/hooks/limit-scan.hooks.js
module.exports = function limitScan() {
  return async context => {
    const query = context.params.query || {};
    if (query.$scan) {
      context.params.body = context.params.body || {};
      context.params.body.FilterExpression = query.filterExpression || 'attribute_exists(id)';
      context.params.body.ProjectionExpression = query.projectionExpression || 'id,email';
      delete context.params.query.$scan;
    }
    return context;
  };
};

5. Validate and sanitize index usage

If using GSIs, ensure that the index projections do not include sensitive attributes. When querying a GSI, map only required fields and avoid relying on index keys that may expose internal state.

// Example GSI query with restricted projection
const queryParams = {
  TableName: 'UsersTable',
  IndexName: 'EmailIndex',
  KeyConditionExpression: 'email = :emailVal',
  ExpressionAttributeValues: { ':emailVal': '[email protected]' },
  ProjectionExpression: 'id,email,displayName'
};

await docClient.query(queryParams).promise();

These patterns help ensure that data exposure through Dynamodb in FeathersJS services is minimized. By combining field-level selection, ownership enforcement, and careful query design, teams can reduce the likelihood of sensitive data being returned unintentionally.

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

How does middleBrick detect data exposure in FeathersJS services using Dynamodb?
middleBrick performs black-box scanning of the unauthenticated attack surface, analyzing API behavior and DynamoDB query patterns to identify endpoints that return sensitive fields without proper authorization or field filtering.
Can middleBrick automatically fix data exposure issues in FeathersJS?
middleBrick detects and reports findings with remediation guidance but does not automatically fix, patch, block, or remediate. Developers must implement the suggested code changes, such as field selection and ownership checks, to address data exposure.