HIGH missing authenticationexpresshmac signatures

Missing Authentication in Express with Hmac Signatures

Missing Authentication in Express with Hmac Signatures — how this specific combination creates or exposes the vulnerability

HMAC signatures are often used in Express routes to verify that a request originates from a trusted sender. The typical pattern is for the client to compute a hash-based message authentication code (HMAC) over selected parts of the request—such as the request method, path, timestamp, and body—using a shared secret, and to send the signature in a header (e.g., x-signature). If the server does not require authentication or does not validate the HMAC before processing business logic, the route effectively runs unauthenticated, which is a classic Missing Authentication finding.

What makes this combination particularly risky in an Express service is the mismatch between the presence of a signature and the absence of any requirement to verify it. Consider an endpoint that initiates a fund transfer or changes an email address. If this endpoint only checks for the existence of a signature header but does not validate the HMAC against the shared secret, an attacker can simply omit the header or send an arbitrary value. Even if the server computes the HMAC internally, failing to enforce verification means the route trusts client-supplied data, enabling IDOR or BOLA-style tampering of identifiers within the payload.

Another common pitfall is the misuse of a static or low-entropy shared secret across many clients, or embedding the secret in client-side code or JavaScript bundles. If the secret leaks, an attacker can compute valid HMACs for any request, bypassing the intended integrity protection. In Express, this is often exacerbated by inconsistent application of middleware: some routes validate signatures while others do not, or validation is performed only for certain HTTP methods. Inconsistent enforcement widens the unauthenticated attack surface, which is what middleBrick’s Authentication check is designed to surface.

Timestamp or nonce misuse further amplifies the risk. If an endpoint accepts requests without verifying that the timestamp is recent or that the nonce is unique, replay attacks become feasible even when HMAC signatures are present. An attacker can capture a valid request—such as a payment initiation—and replay it later, potentially within the allowed time window. Because the server may skip signature validation or rely solely on idempotency keys, the unauthenticated path allows the replay to succeed, leading to unauthorized operations.

Finally, the interplay with other checks such as BOLA/IDOR and Input Validation is critical. Missing Authentication can turn a seemingly harmless parameter manipulation into a full compromise when combined with weak authorization. For example, an API that validates HMAC format but does not ensure the caller is entitled to act on the target resource may allow horizontal privilege escalation. middleBrick’s parallel scan checks for these conditions by probing unauthenticated attack paths and correlating findings with spec-defined security schemes, highlighting where HMAC-based integrity exists without authentication enforcement.

Hmac Signatures-Specific Remediation in Express — concrete code fixes

To address Missing Authentication when HMAC signatures are in use, enforce strict verification on every relevant route before performing any business logic. The server must compute its own HMAC over the canonical representation of the request and compare it in constant time with the value provided by the client. Below is a concise, production-grade example for Express that demonstrates this approach.

const crypto = require('crypto');
const express = require('express');
const app = express();

app.use(express.json());

const SHARED_SECRET = process.env.HMAC_SHARED_SECRET;
if (!SHARED_SECRET) {
  throw new Error('HMAC_SHARED_SECRET must be set');
}

function computeSignature(payload) {
  return crypto.createHmac('sha256', SHARED_SECRET)
    .update(payload.timestamp + payload.path + JSON.stringify(payload.body))
    .digest('hex');
}

function verifyHmac(req, res, next) {
  const received = req.get('x-signature');
  if (!received) {
    return res.status(401).json({ error: 'Missing signature' });
  }
  const computed = computeSignature({
    timestamp: req.body.timestamp,
    path: req.path,
    body: req.body
  });
  const isValid = crypto.timingSafeEqual(
    Buffer.from(received, 'hex'),
    Buffer.from(computed, 'hex')
  );
  if (!isValid) {
    return res.status(403).json({ error: 'Invalid signature' });
  }
  // Optional: reject replay by checking timestamp window
  const requestTime = parseInt(req.body.timestamp, 10);
  const now = Math.floor(Date.now() / 1000);
  if (Math.abs(now - requestTime) > 300) {
    return res.status(400).json({ error: 'Request expired' });
  }
  next();
}

app.post('/api/transfer', verifyHmac, (req, res) => {
  // Business logic: ensure the subject of the request matches the authenticated context if applicable
  const { from, to, amount } = req.body;
  // Process transfer...
  res.json({ status: 'ok' });
});

app.listen(3000, () => console.log('Server running on port 3000'));

This pattern ensures that every request carries a valid HMAC derived from a shared secret and request-specific components. The use of crypto.timingSafeEqual prevents timing attacks during signature comparison. For production, rotate the shared secret periodically and avoid committing it to source control; prefer environment injection or secret management integration.

In addition to verification, consider adding replay protection with a short timestamp window and unique nonces stored in a fast cache. If your API supports third-party clients, document clearly which parts of the request are included in the HMAC and require authentication for sensitive endpoints even when signatures are present. Tools like the middleBrick CLI can scan your Express routes and highlight where HMAC headers exist but are not enforced, helping you align implementation with expected security guarantees.

Related CWEs: authentication

CWE IDNameSeverity
CWE-287Improper Authentication CRITICAL
CWE-306Missing Authentication for Critical Function CRITICAL
CWE-307Brute Force HIGH
CWE-308Single-Factor Authentication MEDIUM
CWE-309Use of Password System for Primary Authentication MEDIUM
CWE-347Improper Verification of Cryptographic Signature HIGH
CWE-384Session Fixation HIGH
CWE-521Weak Password Requirements MEDIUM
CWE-613Insufficient Session Expiration MEDIUM
CWE-640Weak Password Recovery HIGH

Frequently Asked Questions

Does including an HMAC header guarantee the request is authenticated?
No. An HMAC header alone does not imply authentication; the server must explicitly verify the signature and treat missing or invalid results as unauthorized. If verification is skipped, the route remains effectively unauthenticated regardless of the header's presence.
Can an HMAC shared secret be safely embedded in client-side JavaScript?
No. Embedding the shared secret in client-side code exposes it to anyone who can view the source, allowing attackers to forge valid HMACs. Keep the secret server-side and use additional mechanisms such as short-lived tokens or OAuth where appropriate.