HIGH crlf injectionfeathersjsbasic auth

Crlf Injection in Feathersjs with Basic Auth

Crlf Injection in Feathersjs with Basic Auth — how this specific combination creates or exposes the vulnerability

Crlf Injection occurs when an attacker can inject carriage return (CR, \r) and line feed (\n) characters into a header or status-line context, causing the server to prematurely terminate a header block and inject additional headers or split responses. In Feathersjs, this risk exists when user-controlled input is reflected in HTTP headers or status codes without proper sanitization. When Basic Auth is used, the Authorization header value (e.g., Basic base64(username:password)) is typically extracted and parsed by Feathersjs or underlying frameworks like Express. If the application uses any part of the parsed credentials—such as username or realm strings—in constructing response headers, status lines, or log entries, and does not strip or encode CR/LF characters, an attacker can inject header lines.

Basic Auth-Specific Remediation in Feathersjs — concrete code fixes

To mitigate Crlf Injection in Feathersjs with Basic Auth, ensure that any data derived from authentication inputs is sanitized before being used in header construction or status-line formatting. Below are concrete remediation steps and code examples.

1. Validate and sanitize Basic Auth parsed values

After extracting the username and password from the Basic Auth header, validate that the username does not contain CR or LF characters. Reject or normalize the input before using it in any header or status context.

// src/hooks/auth-crlf-sanitize.hooks.js
module.exports = function sanitizeAuthCrlf() {
  return async context => {
    const { headers } = context.params;
    if (headers && headers.authorization && headers.authorization.startsWith('Basic ')) {
      const base64 = headers.authorization.slice('Basic '.length);
      const decoded = Buffer.from(base64, 'base64').toString('utf8');
      const [username, password] = decoded.split(':');
      // Reject if username contains CR or LF
      if (username.includes('\r') || username.includes('\n')) {
        throw new Error('Invalid credentials');
      }
      // Optionally rewrite context for downstream use
      context.params.authUser = username;
    }
    return context;
  };
};

Add this hook to your Feathersjs service configuration to run before authentication logic.

2. Avoid reflecting authentication data in headers or status

Do not include raw username or realm strings in custom headers or status codes. If you must include user-specific information in headers, sanitize by removing or encoding CR/LF characters.

// src/hooks/response-header-sanitize.hooks.js
const CARRIAGE_RETURN = /\r/g;
const NEWLINE = /\n/g;

module.exports = function sanitizeResponseHeaders() {
  return async context => {
    const { user } = context.params.authUser || {};
    if (user) {
      // Sanitize before using in any header value
      const safeUser = user.replace(CARRIAGE_RETURN, '').replace(NEWLINE, '');
      context.params.headers = {
        ...context.params.headers,
        'X-User-Safe': safeUser
      };
    }
    return context;
  };
};

3. Configure Feathersjs transport layer safely

If you are using a custom transport (e.g., overriding send hooks), ensure that status messages and header values are sanitized. Do not directly concatenate user input into status strings.

// src/hooks/send-hooks.js
module.exports = function sendCrlfSafe() {
  return async context => {
    const { result, app } = context;
    if (result && typeof result.send === 'function') {
      const originalSend = result.send.bind(result);
      result.send = function(chunk) {
        // Ensure no CR/LF in custom status or headers set by app logic
        const safeStatus = (context.status || 200).toString();
        // Example: setting a sanitized custom header
        this.setHeader('X-Status-User', (context.params.authUser || 'anon').replace(/[\r\n]/g, ''));
        return originalSend(chunk);
      };
    }
    return context;
  };
};

4. Use framework-level security middleware

Combine Feathersjs hooks with helmet-style protections to strip dangerous headers and enforce safe header values. Ensure that any logging of auth events does not echo unsanitized input.

sendStatus uses unsanitized input
Risk Mitigation Feathersjs Implementation
CR/LF in username used in headers Reject or sanitize newline characters Hook that validates authUser before use
Status line injection via auth-derived dataUse numeric status codes; avoid string concatenation

These steps reduce the attack surface by ensuring that authentication-derived data cannot alter the structure of HTTP messages. Combine these hooks with regular scans using tools like middleBrick to detect any remaining injection risks in your Feathersjs endpoints.

Frequently Asked Questions

Can a CRLF injection in Basic Auth lead to response splitting even if the framework escapes HTML?
Yes. HTML escaping does not protect HTTP header parsing. CR/LF characters in header values can still split responses regardless of HTML context; therefore sanitize at the header layer.
Does middleBrick detect CRLF Injection in Feathersjs with Basic Auth during scans?
middleBrick runs 12 parallel security checks including Input Validation and Property Authorization. It tests unauthenticated attack surfaces and maps findings to frameworks like OWASP API Top 10, providing prioritized remediation guidance.