HIGH double freefeathersjsapi keys

Double Free in Feathersjs with Api Keys

Double Free in Feathersjs with Api Keys — how this specific combination creates or exposes the vulnerability

In FeathersJS, a Double Free scenario can occur when API keys are handled inconsistently across authentication hooks and service logic, leading to attempts to free or revoke a key more than once during a single request lifecycle. This typically manifests when an authentication strategy using API keys interacts with authorization checks that redundantly validate or revoke credentials.

Consider a FeathersJS application that uses custom API key validation via hooks. If the hook verifies the key and attaches a result to the connection context, and a later authorization or service-level check also attempts to invalidate or revalidate the same key reference, the runtime may encounter an error due to double cleanup or double state mutation. This is especially risky when keys are stored in objects that are mutated in-place across multiple middleware steps without proper cloning or state guards.

For example, an attacker could craft requests that trigger both the authentication hook and a misconfigured authorization guard in rapid succession, forcing the application to process the same key revocation logic twice within the same event loop. In languages or runtimes that manage underlying resources explicitly (e.g., native addons or bindings), this can lead to use-after-free conditions or memory corruption. Even in JavaScript runtime environments, double-free-like behavior can surface as unhandled promise rejections or inconsistent context states, which middleBrick’s LLM/AI Security and Input Validation checks are designed to surface.

middleBrick’s Authentication and Input Validation checks can detect patterns where API key handling lacks idempotency guards. By scanning unauthenticated endpoints and analyzing OpenAPI specs, it identifies whether authorization logic redundantly interacts with authentication state, flagging potential Double Free risks before they reach production.

Api Keys-Specific Remediation in Feathersjs — concrete code fixes

To remediate Double Free risks when using API keys in FeathersJS, ensure that authentication and authorization steps are idempotent and that key state is never mutated more than once per request. Use immutable data patterns and avoid in-place mutations of context objects across hooks.

Below is a secure example of API key handling in FeathersJS that prevents double-free-like behavior by validating the key once and attaching a normalized result to the context without further mutation.

// src/hooks/authenticate-api-key.js
module.exports = function authenticateApiKey(options = {}) {
  return async context => {
    const { headers } = context;
    const apiKey = headers['x-api-key'] || context.query.apiKey;

    if (!apiKey) {
      throw new Error('API key is required');
    }

    // Validate key against a store (e.g., database or cache)
    const keyRecord = await context.app.service('api-keys').Model.findOne({
      where: { key: apiKey, active: true }
    });

    if (!keyRecord) {
      throw new Error('Invalid API key');
    }

    // Attach immutable, normalized key metadata to context
    context.state = context.state || {};
    Object.defineProperty(context.state, 'apiKeyMeta', {
      value: Object.freeze({
        id: keyRecord.id,
        scope: keyRecord.scope,
        created: keyRecord.createdAt
      }),
      writable: false,
      configurable: false
    });

    return context;
  };
};

Ensure downstream hooks and services read from context.state.apiKeyMeta without attempting to modify or revoke the same key reference. Avoid additional hooks that call key invalidation logic for the same request.

// src/hooks/authorize-scope.js
module.exports = function authorizeScope(requiredScope) {
  return async context => {
    const keyMeta = context.state?.apiKeyMeta;
    if (!keyMeta) {
      throw new Error('Authentication state is missing');
    }

    // Use frozen metadata; no mutation of key state
    if (!keyMeta.scope.split(',').includes(requiredScope)) {
      throw new Error('Insufficient scope');
    }

    return context;
  };
};

In your service definitions, configure hooks to run authentication once and skip redundant validation:

// src/services/items/items.hooks.js
const authenticateApiKey = require('../../hooks/authenticate-api-key');
const authorizeScope = require('../../hooks/authorize-scope');

module.exports = {
  before: {
    all: [authenticateApiKey()],
    find: [authorizeScope('read:items')],
    get: [authorizeScope('read:items')],
    create: [authorizeScope('write:items')],
    update: [authorizeScope('write:items')],
    patch: [authorizeScope('write:items')],
    remove: [authorizeScope('write:items')]
  }
};

With these patterns, the API key is validated once, stored immutably, and never subjected to double cleanup or state changes. middleBrick’s Authorization and BOLA/IDOR checks can verify that hooks do not introduce conflicting state transitions, while the CLI and GitHub Action integrations help enforce these rules across deployments.

Frequently Asked Questions

How can I verify that my API key hooks are idempotent and safe from double-free-like behavior?
Use middleBrick’s CLI to scan your FeathersJS app and review the Authentication and Input Validation findings. The report will highlight redundant key-state mutations and suggest isolating validation to a single hook with immutable context state.
Does middleBrick’s LLM/AI Security check detect prompt injection risks in API key handling logic?
Yes. The LLM/AI Security checks include active prompt injection testing and system prompt leakage detection, which can surface insecure logging or exposure of key handling logic in AI-integrated endpoints.