HIGH race conditionfeathersjshmac signatures

Race Condition in Feathersjs with Hmac Signatures

Race Condition in Feathersjs with Hmac Signatures — how this specific combination creates or exposes the vulnerability

A race condition in a FeathersJS service that uses Hmac Signatures typically arises when the application verifies the Hmac signature of an incoming request after performing a state-changing read or write operation, or when multiple requests with the same or predictable Hmac material are processed concurrently. The vulnerability occurs because the server-side logic does not guarantee that the data used to compute and verify the Hmac remains consistent from verification to the point where authorization or business logic is applied.

Consider a FeathersJS service that creates a financial transfer. The client computes an Hmac over a canonical representation of the request (e.g., timestamp, userId, amount, nonce) using a shared secret and sends the signature in a header. If the server verifies the Hmac after checking an account balance or before applying rate limiting, an attacker can race two requests: one that reads a stale balance to compute a valid Hmac, and another that changes the balance between the read and the verification. Because the Hmac only covers request parameters and not the server-side state at verification time, the second request may still pass Hmac validation but produce an incorrect or unauthorized outcome.

In FeathersJS, this can be exacerbated by hooks that run in parallel or by service methods that perform asynchronous operations (e.g., database queries) before validating integrity. For example, an attacker may send two authenticated API calls that both present valid Hmac Signatures but operate on slightly different resource versions or permissions. If the server applies business logic or updates state between Hmac verification and action execution, the integrity guarantee of the Hmac is effectively bypassed for that window. This maps to common OWASP API Top 10 categories such as Broken Object Level Authorization (BOLA) and Race Conditions in Business Logic, and can be reflected in findings reported by a scan from middleBrick, which tests unauthenticated attack surfaces and flags inconsistencies between authentication, integrity checks, and state handling.

Another concrete scenario involves idempotency and replay: if the Hmac includes a timestamp or nonce but the server does not enforce strict one-time validation or ordering, concurrent requests with the same signed payload may be processed multiple times. Because Hmac Signatures ensure integrity and authenticity of the signed data, but not the execution context or ordering, a race between two identical signed requests can lead to duplicate transactions or privilege escalation when combined with BOLA/IDOR patterns. middleBrick’s LLM/AI Security and property authorization checks can highlight such gaps by correlating authentication and authorization findings with timing and state inconsistencies.

To detect this class of issue, scans should correlate the API spec (e.g., OpenAPI/Swagger with full $ref resolution) with runtime behavior, checking whether Hmac verification occurs before or after stateful operations. A well-architected approach ensures that Hmac verification is part of the earliest, atomic guard that incorporates relevant server-side state (e.g., current version tokens or locks), and that hooks and service methods are ordered to prevent verification after mutable operations. middleBrick’s per-category breakdowns and prioritized findings include guidance to align Hmac usage with the exact point where authorization and state are decided, reducing the window for race conditions.

Hmac Signatures-Specific Remediation in Feathersjs — concrete code fixes

Remediation centers on ensuring Hmac verification is atomic with respect to the server-side state and occurs before any state-changing or authorization-sensitive logic. In FeathersJS, this is typically implemented in a custom authentication hook that validates the Hmac over a canonical string built from request metadata, and that incorporates current server-side values (such as resource version or a short-lived lock) before allowing the service method to proceed.

Below is a concrete, working example of an Hmac authentication hook for FeathersJS that mitigates race conditions by validating the signature against a combination of client-supplied data and server-side state retrieved in the same atomic step. The hook computes an Hmac using the request body, selected query parameters, a timestamp, and a server-side nonce fetched under a lock or transaction to ensure consistency.

const crypto = require('crypto');

function hmacAuthentication(secret) {
  return async context => {
    const { headers, method, url, body, query } = context;
    const timestamp = headers['x-timestamp'];
    const receivedSignature = headers['x-signature'];

    if (!timestamp || !receivedSignature) {
      throw new Error('Missing authentication headers');
    }

    // Reject requests with stale timestamps (replay protection)
    const now = Date.now();
    const skew = 30000; // 30 seconds
    if (Math.abs(now - Number(timestamp)) > skew) {
      throw new Error('Request timestamp out of skew');
    }

    // Fetch server-side state that must be part of the Hmac,
    // e.g., current resource version or a short-lived nonce.
    // This step should be executed in a transaction or atomic read
    // to avoid race conditions between read and verification.
    const serverNonce = await getServerNonceFor(context.params);

    const canonical = [
      method.toUpperCase(),
      url,
      JSON.stringify(body || {}),
      JSON.stringify(query || {}),
      timestamp,
      serverNonce
    ].join('|');

    const computed = crypto.createHmac('sha256', secret)
      .update(canonical)
      .digest('hex');

    if (!crypto.timingSafeEqual(Buffer.from(receivedSignature), Buffer.from(computed))) {
      throw new Error('Invalid Hmac signature');
    }

    // Attach identity or permissions derived from validated Hmac
    context.params.user = { authenticated: true, scheme: 'hmac' };
    return context;
  };
}

// Example usage in a FeathersJS service configuration
const app = require('@feathersjs/feathers')();
app.configure(express());
app.use('/api/transfer', authenticate('hmac').configure({
  entity: 'account',
  service: app.service('transfer')
}));

// Helper to fetch server-side nonce atomically (pseudo-implementation)
async function getServerNonceFor(params) {
  // In practice, this would read a versioned record or obtain a lock
  const record = await app.service('accounts').get(params.accountId, {
    fields: ['version']
  });
  return record.version;
}

Key points in this remediation:

  • The serverNonce is fetched within the same logical operation as verification, ideally under a transaction or atomic read, so that the value used in the Hmac cannot change between verification and subsequent logic.
  • Hmac includes method, URL, body, query, timestamp, and server-side nonce, binding the signature to the exact request and server state.
  • Timestamp validation mitigates replay attacks; timingSafeEqual prevents timing-based side channels.
  • The hook runs as an early FeathersJS authentication hook, ensuring that any service method depending on this context only proceeds after successful, state-aware Hmac validation.

For broader protection across services, combine this with FeathersJS hooks that enforce ordering: perform Hmac verification before any database reads or writes for the request. This reduces the window where state can change between integrity check and authorization, addressing the root cause of race conditions when Hmac Signatures are used.

Frequently Asked Questions

How does including a server-side nonce in the Hmac mitigate race conditions in FeathersJS?
Including a server-side nonce that is fetched atomically as part of the same operation as Hmac verification ensures that the signed data reflects the current server state. Because the nonce changes between requests and is read within a consistent transactional context, an attacker cannot reliably predict or reuse a valid Hmac across concurrent requests, closing the race condition window.
Can middleBrick detect race conditions involving Hmac Signatures in FeathersJS APIs?
Yes, middleBrick scans the API spec and runtime behavior to identify timing and state inconsistencies, such as Hmac verification occurring after stateful operations. Its findings highlight potential race conditions and provide remediation guidance aligned with OWASP API Top 10 and compliance mappings.