HIGH prototype pollutionexpresshmac signatures

Prototype Pollution in Express with Hmac Signatures

Prototype Pollution in Express with Hmac Signatures — how this specific combination creates or exposes the vulnerability

Prototype pollution in Express applications becomes particularly concerning when Hmac signatures are used to validate object integrity or authorization tokens. In this context, an attacker can supply crafted query or body parameters that modify the prototype of shared objects (for example, Object.prototype), and if the server later constructs Hmac signatures over the manipulated object, the signature may still verify successfully despite unexpected properties. This occurs because signature generation often iterates over object keys, and a polluted prototype introduces inherited enumerable properties that get included in the signature input, changing the hashed payload in ways the server may not explicitly validate.

Consider an Express route that accepts JSON input and creates an Hmac signature using a shared secret:

const crypto = require('crypto');
function buildHmac(data) {
  const hmac = crypto.createHmac('sha256', 'super-secret');
  hmac.update(JSON.stringify(data));
  return hmac.digest('hex');
}
app.post('/api/merge', express.json(), (req, res) => {
  const received = req.body;
  const expected = buildHmac(received);
  const provided = req.headers['x-hmac'];
  if (provided !== expected) {
    return res.status(401).send('Invalid signature');
  }
  // further processing
  res.json({ merged: Object.assign({}, received) });
});

If the client sends {__proto__: { admin: true }} and the server uses JSON.stringify naively, some JSON parsers may produce an object where __proto__ modifies the prototype chain before signature verification, depending on the runtime and parsing behavior. The Hmac signature computed over the polluted object may differ from what the client provides, causing rejection, but in other scenarios the server might compute the signature after pollution has occurred, leading to a situation where an attacker can influence properties that are included in the signature without changing the Hmac value they must match. This can expose logic that trusts signature integrity while not strictly isolating own properties from inherited ones.

Within the 12 security checks run by middleBrick, this pattern is flagged under BOLA/IDOR and Unsafe Consumption checks because the server trusts object shapes derived from external input. The scan detects that Hmac signature comparisons may involve properties introduced via prototype pollution, which can bypass authorization assumptions. Such findings align with OWASP API Top 10 A01:2023 broken object level authorization and highlight how signature schemes alone do not prevent object state manipulation if the data fed into signing is not cleaned.

Hmac Signatures-Specific Remediation in Express — concrete code fixes

Remediation focuses on ensuring that Hmac signatures are computed over a canonical, pollution‑free representation and that object construction never relies on prototype chain properties. Prefer explicit property whitelisting and strict parsing to avoid inherited keys being included in the signature or used in business logic.

1. Use a strict JSON reviver and whitelist allowed keys

const crypto = require('crypto');
const allowed = new Set(['action', 'resource', 'value', 'timestamp']);
function sanitize(input) {
  const seen = new Set();
  return JSON.parse(input, (key, value) => {
    if (key === '' || allowed.has(key)) {
      if (typeof value === 'object' && value !== null) {
        if (seen.has(value)) return undefined; // break cycles
        seen.add(value);
      }
      return value;
    }
    return undefined;
  });
}
function buildHmac(data) {
  const hmac = crypto.createHmac('sha256', 'super-secret');
  hmac.update(JSON.stringify(data, Object.keys(data).sort()));
  return hmac.digest('hex');
}

2. Validate own properties only using Object.prototype.hasOwnProperty and avoid Object.assign with polluted sources

app.post('/api/merge', express.json(), (req, res) => {
  const raw = req.body;
  const clean = {};
  for (const key of Object.keys(raw)) {
    if (Object.prototype.hasOwnProperty.call(raw, key)) {
      clean[key] = raw[key];
    }
  }
  const expected = buildHmac(clean);
  const provided = req.headers['x-hmac'];
  if (provided !== expected) {
    return res.status(401).send('Invalid signature');
  }
  // safe merge using clean only
  const merged = Object.assign({}, clean);
  res.json({ merged });
});

3. Use a canonical serialization for signing (sorted keys, no undefined)

function buildHmac(data) {
  const keys = Object.keys(data).sort();
  const canonical = {};
  for (const k of keys) canonical[k] = data[k];
  const hmac = crypto.createHmac('sha256', 'super-secret');
  hmac.update(JSON.stringify(canonical));
  return hmac.digest('hex');
}

These patterns ensure that Hmac signature generation excludes inherited prototype properties and that comparisons are performed over a deterministic object shape. When integrating with CI/CD, the middleBrick GitHub Action can be configured to fail builds if risk scores exceed your threshold, while the CLI enables quick local verification with middlebrick scan <url>. For ongoing assurance, the Pro plan provides continuous monitoring that can schedule regular scans and deliver Slack or Teams alerts when object-level integrity risks are detected.

Frequently Asked Questions

How does prototype pollution affect Hmac signature validation in Express?
If an attacker can inject properties into Object.prototype, those inherited properties may be included when serializing the object for Hmac signing, changing the computed signature. Unless the server explicitly excludes non‑own properties, this can lead to mismatches or, in some parsing scenarios, allow the attacker to influence signed data without changing the expected Hmac.
What are the best practices for securing Hmac signatures against object manipulation in Express?
Use a strict JSON reviver or a property whitelist, validate own properties only with hasOwnProperty, canonicalize by sorting keys before signing, and avoid merging polluted sources. Automate checks in CI/CD with the middleBrick GitHub Action and use the CLI for local scans to detect risky object handling patterns.