HIGH denial of servicefeathersjsapi keys

Denial Of Service in Feathersjs with Api Keys

Denial Of Service in Feathersjs with Api Keys — how this specific combination creates or exposes the vulnerability

FeathersJS is a framework that typically sits on top of Express and uses transport adapters such as REST or Socket.io. When API keys are used for authentication, they are commonly validated in a service hook before business logic runs. If the key validation or subsequent service logic does not enforce strict rate limiting, an unauthenticated or low-cost endpoint can be targeted to exhaust server resources. For example, an endpoint that performs a database query keyed by an attacker-supplied parameter can result in heavy query loads or excessive memory usage when repeated rapidly.

Consider a service that accepts an API key via an authorization header and queries a database without constraints:

// services/search/service.js
class SearchService {
  find(params) {
    const { query, apikey } = params.query;
    // Risk: no validation on query size or rate per key
    return db.search({ $text: { $search: query } });
  }
}

An attacker who knows or guesses a valid API key can send many concurrent requests with large or complex query strings. If the service does not enforce request limits per key, this can consume CPU, memory, and database connections, leading to a Denial of Service (DoS) condition for legitimate users. This pattern is relevant to the BFLA/Privilege Escalation and Rate Limiting checks in middleBrick, which test whether operations are constrained by authentication context and whether rate limits are applied per consumer.

Additionally, if API key validation is performed asynchronously or involves expensive operations (e.g., fetching key details from a remote system), an attacker can amplify the cost of each request. Combined with missing request size limits or unbounded query parameters, this can trigger resource exhaustion on the service host, a scenario covered by the Input Validation and Rate Limiting checks in the 12 parallel security checks.

Api Keys-Specific Remediation in Feathersjs — concrete code fixes

To reduce DoS risk when using API keys in FeathersJS, apply validation early in the hook chain and enforce rate limits scoped to the key. Use hooks to normalize and verify keys before the service logic runs, and apply per-key rate limits to restrict request volume.

Example of a hook that validates an API key and attaches the resolved key metadata:

// hooks/validate-api-key.js
const apiKeys = new Set(['trusted-key-123', 'trusted-key-456']); // in practice, use a secure store

module.exports = function () {
  return async context => {
    const key = context.params.headers['x-api-key'];
    if (!key || !apiKeys.has(key)) {
      throw new Error('Not authenticated');
    }
    // Attach normalized key info for downstream use
    context.params.apiKey = key;
    return context;
  };
};

Apply the hook in your service configuration:

// src/hooks/index.js
const validateApiKey = require('./validate-api-key');

module.exports = {
  before: {
    all: [validateApiKey()],
    find: [],
    get: [],
    create: []
  },
  after: { all: [] },
  error: { all: [], create: [] }
};

Add per-key rate limiting using a token-bucket or fixed-window approach. Below is a simplified in-memory fixed-window example; in production, use a shared store like Redis for multi-instance consistency:

// hooks/rate-limit-by-key.js
const limits = new Map(); // key -> { count, windowStart }

module.exports = function (options = { limit: 60, windowMs: 60_000 }) {
  return async context => {
    const key = context.params.apiKey;
    if (!key) return context;
    const now = Date.now();
    const record = limits.get(key);
    if (!record || now - record.windowStart >= options.windowMs) {
      limits.set(key, { count: 1, windowStart: now });
      return context;
    }
    if (record.count >= options.limit) {
      throw new Error('Rate limit exceeded');
    }
    record.count += 1;
    return context;
  };
};

Register the rate-limiting hook alongside validation:

// src/hooks/index.js
const validateApiKey = require('./validate-api-key');
const rateLimitByKey = require('./rate-limit-by-key');

module.exports = {
  before: {
    all: [
      validateApiKey(),
      rateLimitByKey({ limit: 60, windowMs: 60_000 })
    ],
    find: [],
    get: [],
    create: []
  },
  after: { all: [] },
  error: { all: [], create: [] }
};

Also restrict query inputs to prevent excessively complex searches that can degrade performance:

// src/services/search/hooks.js
module.exports = {
  before: {
    find: [require('feathers-hooks-common')].map(hook =>
      hook.validate({ query: { maxLength: 100 } })
    )
  }
};

These steps ensure API key usage is bounded and monitored, reducing the likelihood of resource exhaustion. The findings from middleBrick’s Rate Limiting and Input Validation checks can help verify that such controls are effective in your runtime configuration.

Related CWEs: resourceConsumption

CWE IDNameSeverity
CWE-400Uncontrolled Resource Consumption HIGH
CWE-770Allocation of Resources Without Limits MEDIUM
CWE-799Improper Control of Interaction Frequency MEDIUM
CWE-835Infinite Loop HIGH
CWE-1050Excessive Platform Resource Consumption MEDIUM

Frequently Asked Questions

Can API keys alone prevent DoS attacks in FeathersJS?
No. API keys provide authentication and help identify consumers, but they do not prevent resource exhaustion. You must combine keys with rate limiting, input validation, and query constraints to mitigate DoS risks.
How does middleBrick assess DoS risk for API keys?
middleBrick runs parallel checks including Rate Limiting and Input Validation against the unauthenticated attack surface. It examines whether operations are constrained per authenticated context and whether limits are enforced for identified API key usage patterns.