HIGH crlf injectionnestjsapi keys

Crlf Injection in Nestjs with Api Keys

Crlf Injection in Nestjs with Api Keys — 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 sent to the client. In NestJS, this typically arises when dynamic values—often sourced from request headers, query parameters, or user-controlled payloads—are used to construct custom HTTP headers or status codes without sanitization. When an API key is used for identification or rate-limiting, developers sometimes embed the key or key-derived values directly into headers or logs, inadvertently providing a pathway for injection if those values are attacker-influenced.

Consider an endpoint that reads an apiKey from a header and reflects it in a custom header in the response. If the apiKey value contains \r\n sequences and the server concatenates it into a header line, an attacker can inject additional headers or split the response, leading to HTTP response splitting, cache poisoning, or cross-site scripting in downstream intermediaries. For example:

const raw = request.headers['apikey'] || '';
res.set('X-API-Key-Echo', raw);

If the apiKey is attacker-controlled and contains \r\nSet-Cookie: injected=1, the injected line can create a new header, bypassing intended defenses. NestJS does not inherently sanitize custom header values derived from user input, so the developer must validate and encode any data that will be placed into headers or status text. The risk is compounded in logging or error handling where apiKey values are written into status lines or headers that later get forwarded to logs or monitoring systems, potentially enabling log injection or header smuggling.

Another scenario involves using the apiKey to select a downstream service or tenant, where the key is reflected in a Location header during a redirect. If the key or a derived value contains \r\n, an attacker can inject a new Location, causing open redirects or proxy confusion. Because API keys are often treated as opaque identifiers, developers may assume they are safe, but their use in header construction without validation introduces a Crlf Injection surface that can compromise integrity and isolation.

Api Keys-Specific Remediation in Nestjs — concrete code fixes

Remediation focuses on strict validation, canonicalization, and safe construction of headers and status codes. Never directly concatenate user-supplied values into headers or status lines. Instead, enforce a strict character set for apiKey values and use framework utilities to set headers safely. Below are concrete examples demonstrating secure handling in NestJS.

1. Validate and sanitize apiKey values

Treat apiKey as an opaque token and reject any value containing control characters or whitespace. Use a strict allowlist (e.g., alphanumeric plus a limited set of safe symbols) and enforce length constraints.

import { Injectable, BadRequestException } from '@nestjs/common';

export function validateApiKey(apiKey: string): string {
  if (!apiKey) {
    throw new BadRequestException('Missing apiKey');
  }
  // Allow only safe characters and enforce length
  if (!/^[A-Za-z0-9\-._~+]+$/.test(apiKey)) {
    throw new BadRequestException('Invalid apiKey format');
  }
  if (apiKey.length < 16 || apiKey.length > 128) {
    throw new BadRequestException('Invalid apiKey length');
  }
  return apiKey;
}

@Injectable()
export class ApiKeyService {
  verify(key: string): boolean {
    const safeKey = validateApiKey(key);
    // proceed with lookup
    return true;
  }
}

2. Use framework facilities to set headers

Avoid manually constructing header lines. Use NestJS’s built-in methods to set headers, which do not interpret \r\n as line breaks. For custom headers derived from validated keys, assign the value directly without concatenation.

import { Controller, Get, Header, Req } from '@nestjs/common';

@Controller('resource')
export class ResourceController {
  @Get()
  @Header('X-API-Key-Echo', (req) => {
    const raw = req.headers['apikey'] || '';
    return validateApiKey(raw); // validated safe value
  })
  getResource() {
    return { data: 'ok' };
  }
}

// Alternatively, set headers after validation in the handler:
import { HttpException, HttpStatus, Injectable } from '@nestjs/common';

@Injectable()
export class SafeResourceService {
  getWithHeader(apiKey: string) {
    const safeKey = validateApiKey(apiKey);
    // Return data and let the layer set headers safely
    return { safeKey };
  }
}

// In a route handler:
import { Res } from '@nestjs/common';
import { Response } from 'express';

@Get('profile')
profile(@Res() res: Response, @Req() req) {
  const safeKey = validateApiKey(req.headers['apikey']);
  res.set('X-API-Key-Echo', safeKey);
  res.json({ profile: 'ok' });
}

3. Avoid using apiKey-derived values in redirects and status text

When using the apiKey in redirects, canonicalize and encode the target URL. Do not embed raw key values into Location headers. For status codes, use numeric constants and never interpolate user input into the reason phrase.

import { HttpException, HttpStatus } from '@nestjs/common';

@Injectable()
export class RedirectService {
  redirectWithSafeKey(apiKey: string, target: string) {
    const safeKey = validateApiKey(apiKey);
    // Use a canonical redirect URL; do not append raw key as a header
    const url = new URL(target, 'https://api.example.com');
    url.searchParams.set('key_id', safeKey.substring(0, 8)); // safe subset
    throw new HttpException(url.toString(), HttpStatus.FOUND);
  }
}

By combining strict input validation, safe header-setting practices, and avoidance of user-controlled data in status lines, you mitigate Crlf Injection risks while still leveraging apiKey-based identification securely.

Frequently Asked Questions

Can Crlf Injection be exploited through API keys even if the keys are validated on the server?
Yes, if validation is applied only after the key is read but before it is used in headers, an attacker may still supply a key containing \r\n if validation is permissive or inconsistent across services. Ensure validation is strict and applied at the earliest point, and avoid reflecting raw keys in headers.
Does middleBrick detect Crlf Injection in API keys during scans?
middleBrick scans the unauthenticated attack surface and includes header injection checks among its 12 security checks. It will flag endpoints where user-controlled input (such as apiKey values) is reflected in headers without proper sanitization, providing findings with severity and remediation guidance.