HIGH nosql injectionfeathersjshmac signatures

Nosql Injection in Feathersjs with Hmac Signatures

Nosql Injection in Feathersjs with Hmac Signatures — how this specific combination creates or exposes the vulnerability

FeathersJS is a framework for real-time applications that often exposes services via REST or Socket.io. When HMAC signatures are used for custom authentication, developers may assume the signature protects the entire request. However, if service parameters, query fields, or route placeholders are bound directly to MongoDB or NeDB queries without validation, an authenticated request can still lead to NoSQL injection.

Consider a Feathers service that accepts a user-supplied query object. If the developer verifies an HMAC on selected headers or a token payload but then forwards the unchecked query to the database, attacker-controlled keys can be used to alter query logic. For example, a field like $where or $ne inside a JSON payload may be interpreted by the underlying database as a NoSQL injection operator. Even when the request includes a valid HMAC signature, the framework’s service layer may not sanitize or type-check the payload, allowing injection to proceed.

The risk is compounded when the HMAC is used to sign only a subset of the data, such as an API key or timestamp, while the rest of the parameters are trusted. An attacker who can partially control the authenticated request may inject conditions that bypass intended filters, escalate permissions, or extract sensitive records. Since FeathersJS typically abstracts the database layer, developers might overlook how unchecked input propagates to the query, especially when using $or, $and, or nested objects. This combination of authenticated channels with unchecked NoSQL-friendly inputs creates a pathway for unauthorized data access or manipulation despite the presence of HMAC-based integrity checks.

Hmac Signatures-Specific Remediation in Feathersjs — concrete code fixes

To mitigate NoSQL injection in FeathersJS while using HMAC signatures, treat authenticated input with the same scrutiny as unauthenticated input. Validate and sanitize all query and payload fields before they reach the service layer. Use strict schema validation and avoid passing raw user objects directly to the database.

Example of insecure code that should be avoided:

// Insecure: directly using params.query without validation
app.service('users').hooks({
  before: {
    create: [context => {
      const hmac = context.params.headers['x-api-hmac'];
      if (!verifyHmac(hmac, context.params)) {
        throw new Error('Invalid signature');
      }
      // WARNING: context.query or context.data may still contain injection-prone keys
      return context;
    }]
  }
});

Secure approach with explicit allowlisting and validation:

const Ajv = require('ajv');
const ajv = new Ajv();

const querySchema = {
  type: 'object',
  properties: {
    $limit: { type: 'integer', minimum: 1, maximum: 100 },
    $skip: { type: 'integer', minimum: 0 },
    query: {
      type: 'object',
      properties: {
        email: { type: 'string', format: 'email' },
        role: { type: 'string', enum: ['user', 'admin'] }
      },
      additionalProperties: false
    }
  },
  additionalProperties: false
};

const validateQuery = ajv.compile(querySchema);

app.service('users').hooks({
  before: {
    create: [context => {
      const hmac = context.params.headers['x-api-hmac'];
      if (!verifyHmac(hmac, context.params)) {
        throw new Error('Invalid signature');
      }
      if (!validateQuery(context.query)) {
        throw new Error('Invalid query structure');
      }
      // Ensure only expected keys are forwarded
      const safeQuery = {
        $limit: context.query.$limit || 50,
        $skip: context.query.$skip || 0,
        query: context.query.query || {}
      };
      context.params.query = safeQuery;
      return context;
    }]
  }
});

Additionally, configure the Feathers adapter to avoid operator propagation. If using feathers-mongodb, prefer explicit field selection and avoid dynamic $where or $whereIn populated from user input. For HMAC verification, ensure the signing scope is comprehensive — include the full set of parameters that influence the query to prevent selective bypass. Combine schema validation, strict allowlisting, and server-side query constraints to neutralize NoSQL injection risks even when HMAC signatures confirm request authenticity.

Frequently Asked Questions

Does using Hmac Signatures in Feathersjs automatically prevent NoSQL injection?
No. Hmac signatures verify integrity and authenticity but do not sanitize or validate query content. If unchecked user input is forwarded to the database, NoSQL injection can still occur despite a valid signature.
What specific remediation steps are recommended for Feathersjs services using Hmac authentication?
Implement strict schema validation (e.g., Ajv) on all query parameters, use allowlisting to limit forwarded keys, avoid passing raw user objects to the database, and ensure HMAC covers all inputs that influence query construction.