HIGH header injectionfeathersjshmac signatures

Header Injection in Feathersjs with Hmac Signatures

Header Injection in Feathersjs with Hmac Signatures

Header Injection in a Feathersjs service that uses Hmac Signatures occurs when an attacker can influence HTTP or protocol-level headers that the server uses to compute or validate the Hmac. Feathersjs itself is framework-agnostic about transport, but applications often add Hmac-based integrity checks (for webhook validation, internal service calls, or message authentication). If user-controlled data—such as query parameters, path segments, or incoming headers—flows into the logic that builds the string-to-sign or is included in the signed payload, an attacker can inject newlines or duplicate headers to forge a valid Hmac.

For example, many Hmac implementations in Feathersjs concatenate a timestamp and a raw header value (e.g., x-api-key or a custom x-signature) and then sign the result. If an attacker can inject a newline (\n) into a header value, they may force the server to treat part of the attacker’s data as a new header line, bypassing signature verification. A classic newline injection looks like: X-Forwarded-For: 127.0.0.1\nX-Internal: true. Depending on how the server parses headers, the second line may be processed as a separate header, and if that header is included in the Hmac computation, the attacker can influence the signature without knowing the secret.

Another common pattern in Feathersjs apps is signing the raw request method, URL path, selected headers, and a timestamp. If the header selection logic is too permissive—such as taking all headers that start with x-—an attacker who can inject a crafted header like x-signature: foo can directly manipulate the signed data. Additionally, if the server reuses header names across different contexts (e.g., using x-user-id both from the client and internally), an injected header may be misinterpreted as authoritative, leading to privilege escalation or BOLA/IDOR-like outcomes even when the Hmac appears valid.

Because Feathersjs often integrates with transports like REST and Socket.io, the risk depends on how services normalize and validate headers before Hmac computation. For REST, unchecked headers from the HTTP layer may be passed into hooks where the Hmac is built. For Socket.io, custom framing headers or message properties may be treated similarly. In both cases, failing to strictly validate and sanitize header names and values—especially those that influence the signature—turns an integrity mechanism into an injection vector.

Real-world analogues include CVE-classic web signature bypass patterns where newline injection in the MessageSignature header leads to authentication bypass. In an API security scan run by middleBrick, such issues are surfaced under Data Exposure and Unsafe Consumption checks, alongside Property Authorization and Input Validation findings that highlight missing canonicalization. The scanner does not fix the code, but its prioritized findings include remediation guidance to ensure headers are stripped, canonicalized, and excluded from the Hmac unless explicitly required.

Hmac Signatures-Specific Remediation in Feathersjs

Remediation focuses on strict header canonicalization, deterministic construction of the string-to-sign, and excluding attacker-influenced data from Hmac computation. Below are concrete, safe patterns for Feathersjs services.

1. Canonicalize and filter headers

Never sign raw or concatenated header strings that include untrusted input. Instead, explicitly select the headers you trust, normalize their names to lowercase, and reject unexpected headers early in the request lifecycle.

// Safe header canonicalization in a Feathers hook
function canonicalizeHeaders(headers) {
  const allowed = new Set([
    'x-request-id',
    'x-timestamp',
    'x-nonce'
  ]);
  const canonical = {};
  for (const [key, value] of Object.entries(headers || {})) {
    const k = key.toLowerCase();
    if (allowed.has(k)) {
      // Reject newlines and other control characters
      if (/[\n\r]/.test(value)) {
        throw new Error('Invalid header value: contains control characters');
      }
      canonical[k] = value.trim();
    }
  }
  return canonical;
}

// Usage in a Feathers before hook
function hmacValidationHook(context) {
  const { headers } = context.params;
  const safeHeaders = canonicalizeHeaders(headers);
  const payload = {
    method: context.method.toLowerCase(),
    path: context.path,
    timestamp: safeHeaders['x-timestamp'],
    nonce: safeHeaders['x-nonce']
  };
  context.params._hmacPayload = payload;
  return context;
}

2. Deterministic string-to-sign

Build the data to sign from canonical fields only, and serialize it in a stable format (e.g., JSON with sorted keys). Do not include raw header strings that may contain injected lines.

const crypto = require('crypto');

function buildStringToSign(payload) {
  // Ensure deterministic ordering
  const sorted = {
    method: payload.method,
    path: payload.path,
    timestamp: payload.timestamp,
    nonce: payload.nonce
  };
  const json = JSON.stringify(sorted);
  return crypto.createHmac('sha256', process.env.HMAC_SECRET)
               .update(json, 'utf8')
               .digest('hex');
}

// Verify in a hook or service method
function verifyHmac(context) {
  const expected = buildStringToSign(context.params._hmacPayload);
  const incoming = context.headers['x-signature'];
  if (!incoming || !crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(incoming))) {
    throw new Error('Invalid Hmac');
  }
  return context;
}

3. Reject duplicate and ambiguous headers

Some servers merge repeated headers into arrays; this can be abused if the Hmac logic picks the wrong element. Enforce a single-value policy for signed headers and fail the request if duplicates are present.

function noDuplicateHeaders(headers) {
  const seen = new Set();
  for (const key of Object.keys(headers || {})) {
    const lower = key.toLowerCase();
    if (seen.has(lower)) {
      throw new Error('Duplicate header not allowed');
    }
    seen.add(lower);
  }
}

By combining these steps—canonicalizing headers, building a deterministic string-to-sign, and rejecting injection-friendly formats—you reduce the risk of Header Injection in Feathersjs services that rely on Hmac Signatures. The middleBrick scanner surfaces related findings under Authentication, BOLA/IDOR, and Unsafe Consumption checks, and its prioritized remediation guidance complements these coding practices.

Frequently Asked Questions

Can header injection bypass Hmac verification even if the secret is not leaked?
Yes. If the string-to-sign includes attacker-influenced headers—such as via newline injection or duplicate headers—an attacker can forge a valid Hmac without learning the secret. Canonicalization and strict header filtering are required.
Does middleBrick fix header injection issues automatically?
No. middleBrick detects and reports issues with remediation guidance. Developers must apply fixes such as canonicalizing headers and excluding untrusted data from Hmac computation.