HIGH crlf injectionstrapihmac signatures

Crlf Injection in Strapi with Hmac Signatures

Crlf Injection in Strapi with Hmac Signatures — how this specific combination creates or exposes the vulnerability

Crlf Injection occurs when an attacker can inject CRLF sequences (\r\n) into a header or value that is later reflected in an HTTP response. In Strapi, this can intersect with Hmac Signatures when user-controlled data is included in the data that is signed or when signed values are reflected in headers without proper sanitization. For example, if Strapi generates a signed token or signature based on a header such as X-Forwarded-For or a user-controlled query parameter, and that header contains newline characters, an attacker can inject additional headers or split the response.

Consider a scenario where Strapi uses Hmac Signatures to sign a JSON Web Token or a custom header derived from user input. If the input is not validated and contains \r\n, an attacker can inject a second header line such as X-Injected: true. Because the signature may be computed over the original, unsanitized value, the server might still treat the request as valid while exposing unintended headers. This can lead to response splitting, HTTP response smuggling, or bypass of security controls that rely on header integrity.

In the context of Strapi’s auth flow, if an API endpoint accepts an Authorization header or a custom header that is later included in a signed payload without canonicalization (e.g., trimming or rejecting \r\n), the Hmac Signature does not protect against injection—it only ensures the payload has not been altered after signing. An attacker can exploit this by sending a crafted request such as:

GET /api/public/endpoint HTTP/1.1
Host: example.com
X-Request-ID: abc123\r\nX-Admin: 1
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...

If Strapi uses the X-Request-ID header (containing \r\n) as part of the data that influences authorization logic or response headers, the injected X-Admin header may be processed, potentially bypassing intended access restrictions. The Hmac Signature may still validate if the signature is computed over a subset of headers or a normalized request, but if the implementation does not strictly sanitize inputs before processing, the signature does not prevent the injection.

Additionally, when Strapi exposes unauthenticated endpoints that accept query parameters used to compute Hmac Signatures, an attacker can probe for injection points by appending \r\n sequences to parameter values and observing whether reflected headers or cookies change. Because the scan tests unauthenticated attack surfaces and includes checks for Input Validation and Data Exposure, middleBrick can identify whether user-controlled data is reflected in headers without proper sanitization, even when Hmac Signatures are used for integrity.

Hmac Signatures-Specific Remediation in Strapi — concrete code fixes

Remediation focuses on strict input validation and canonicalization before using any user-controlled data in signature computation or header reflection. In Strapi, ensure that values used in Hmac Signatures are normalized by removing or rejecting CRLF characters and that signatures are computed over a canonical representation of the data.

Below are concrete code examples for Strapi controllers and services that demonstrate safe handling of Hmac Signatures.

1. Validate and sanitize input before signing:

const crypto = require('crypto');
const sanitizeHeaderValue = (value) => {
  if (typeof value !== 'string') return value;
  // Reject or strip CRLF to prevent injection
  if (/[\r\n]/.test(value)) {
    throw new Error('Invalid header value: contains newline characters');
  }
  return value.trim();
};
module.exports = {
  generateSignedToken: async (ctx) => {
    const userAgent = sanitizeHeaderValue(ctx.request.header['x-user-agent']);
    const timestamp = Date.now().toString();
    const payload = `${userAgent}:${timestamp}`;
    const secret = strapi.config.get('plugin.middleware.hmacSecret');
    const signature = crypto.createHmac('sha256', secret).update(payload).digest('hex');
    ctx.body = { token: `${payload}.${signature}`, timestamp };
  },
};

2. Verify signature and re-sanitize before use:

const verifySignedToken = (token) => {
  const [payload, receivedSignature] = token.split('.');
  if (!payload || !receivedSignature) {
    throw new Error('Invalid token format');
  }
  const [userAgent, timestamp] = payload.split(':');
  // Re-sanitize during verification
  if (/[\r\n]/.test(userAgent) || /[\r\n]/.test(timestamp)) {
    throw new Error('Invalid payload: contains newline characters');
  }
  const secret = strapi.config.get('plugin.middleware.hmacSecret');
  const expectedSignature = crypto.createHmac('sha256', secret).update(payload).digest('hex');
  if (!crypto.timingSafeEqual(Buffer.from(receivedSignature), Buffer.from(expectedSignature))) {
    throw new Error('Invalid signature');
  }
  return { userAgent, timestamp: Number(timestamp) };
};

3. Ensure headers reflected in responses are sanitized:

module.exports = {
  sendSafeResponse: async (ctx) => {
    const customHeader = sanitizeHeaderValue(ctx.request.header['x-custom']);
    ctx.set('X-Custom-Safe', customHeader);
    ctx.body = { message: 'OK' };
  },
};

These examples show how to integrate validation directly into Strapi’s middleware or service layer. By rejecting or stripping CRLF characters before using data in signature input or header reflection, you ensure that Hmac Signatures protect integrity without inadvertently enabling injection. Combine this with the scanner’s checks for Input Validation and Data Exposure to confirm that user-controlled values are properly constrained.

Frequently Asked Questions

Can a valid Hmac Signature prevent Crlf Injection in Strapi?
No. A Hmac Signature ensures data integrity but does not sanitize input. If user-controlled data containing \r\n is used to compute the signature or reflected in headers, injection can still occur. You must explicitly validate and canonicalize inputs.
How does middleBucket detect Crlf Injection risks in Strapi APIs?