HIGH crlf injectionnestjstypescript

Crlf Injection in Nestjs (Typescript)

Crlf Injection in Nestjs with Typescript — how this specific combination creates or exposes the vulnerability

Crlf Injection occurs when an attacker can inject a carriage return (CR, \r) and line feed (\n) sequence into a header or redirect value, causing the server to prematurely terminate a header block and inject additional headers or body content. In NestJS with TypeScript, this risk arises when user-controlled input is passed into HTTP utilities that forward or construct headers, status codes, or redirect URLs without strict validation.

NestJS applications often use Express under the hood, and Node.js HTTP utilities (e.g., res.writeHead, res.setHeader, res.redirect) allow header assignment. If a developer builds a redirect or header response using concatenated strings or poorly validated inputs — such as a URL from query parameters or a request body — an attacker can inject %0D%0A (or literal \r\n) sequences. For example, a status code or URL like http://example.com\r\nX-Injected: true can break header boundaries.

In TypeScript, the type system does not inherently prevent this; if a string is accepted as a header value or redirect target, an attacker can supply crafted input at runtime. Common vulnerable patterns in NestJS include using user input directly in res.redirect() or setting custom headers via res.setHeader(). Since NestJS encourages a structured, decorator-driven approach, developers may assume validation pipes eliminate risks, but pipes that only check format or length won’t neutralize CRLF characters.

Consider an endpoint that redirects users to a provided URL:

import { Controller, Get, Query } from '@nestjs/common';
import { Response } from 'express';

@Controller('redirect')
export class RedirectController {
  @Get()
  redirect(@Query('url') url: string, @Res() res: Response) {
    res.redirect(url);
  }
}

If the url query parameter contains http://example.com\r\nSet-Cookie: malicious=1, the injected CRLF can cause an additional Set-Cookie header to be interpreted by the client, leading to session fixation or other header-smuggling issues. Similarly, status codes or headers built from user data can be compromised.

Because NestJS APIs often serve as backend-for-frontend or microservice endpoints, such injection can have downstream effects, especially if responses are chained through proxies or API gateways. The black-box scanning approach used by middleBrick tests these unauthenticated surfaces by probing inputs that reach headers and redirects, highlighting where CRLF sequences can escape intended boundaries.

Typescript-Specific Remediation in Nestjs — concrete code fixes

Remediation focuses on input validation, output encoding, and avoiding direct concatenation of user input into headers or redirects. In TypeScript, leverage class-validator and NestJS validation pipes to enforce strict patterns, and sanitize strings by removing or encoding CR and LF characters before they reach HTTP primitives.

1. Use validation pipes with a custom whitelist regex that disallows CR and LF characters. For URL fields that must not contain newlines or carriage returns, define a DTO with a pattern constraint:

import { IsString, Matches } from 'class-validator';

export class RedirectDto {
  @IsString()
  @Matches(/^https?:\/\/[^\r\n]+$/, {
    message: 'URL must not contain newline or carriage return characters',
  })
  url: string;
}

Then apply the pipe in your controller:

import { Controller, Get, Query, ValidationPipe } from '@nestjs/common';
import { RedirectDto } from './redirect.dto';
import { Response } from 'express';

@Controller('redirect')
export class RedirectController {
  @Get()
  redirect(@Query(new ValidationPipe({ transform: true })) dto: RedirectDto, @Res() res: Response) {
    res.redirect(dto.url);
  }
}

2. If you must allow dynamic redirects, canonicalize and sanitize the URL by removing any CRLF sequences programmatically before passing it to res.redirect(). For example:

import { Controller, Get, Query, BadRequestException } from '@nestjs/common';
import { Response } from 'express';

function sanitizeUrl(input: string): string {
  // Remove CRLF characters to prevent header injection
  return input.replace(/[\r\n]+/g, '');
}

@Controller('redirect')
export class RedirectController {
  @Get()
  redirect(@Query('url') rawUrl: string, @Res() res: Response) {
    const safeUrl = sanitizeUrl(rawUrl);
    if (!safeUrl.startsWith('http')) {
      throw new BadRequestException('Invalid URL');
    }
    res.redirect(safeUrl);
  }
}

3. For custom headers, avoid building header values from concatenated user input. If you must set a header derived from user data, strip or encode CRLF characters:

import { Controller, Get, Header, Query } from '@nestjs/common';
import { Response } from 'express';

@Controller('headers')
export class HeadersController {
  @Get()
  setHeader(@Query('value') value: string, @Res() res: Response) {
    const safeValue = value.replace(/[\r\n]/g, '');
    res.setHeader('X-Custom', safeValue);
    res.send('OK');
  }
}

4. For APIs that integrate with middleBrick, you can continuously monitor your endpoints by adding the middleBrick GitHub Action to your CI/CD pipeline to fail builds if a security score drops below your chosen threshold, ensuring CRLF and other issues are caught before deployment.

Frequently Asked Questions

Why does TypeScript not prevent CRLF injection by itself?
TypeScript's static typing ensures correct shapes at compile time but does not sanitize or validate runtime string content. If user input reaches headers or redirects as a string, injected \r\n sequences are treated as valid characters unless explicitly rejected by validation logic or sanitization.
How can I test my NestJS endpoints for CRLF injection reliably?
Use black-box testing tools that probe inputs with CRLF sequences in headers, redirects, and cookie-like values. middleBrick scans unauthenticated attack surfaces and can detect whether injected CRLF sequences break header boundaries, returning findings with severity and remediation guidance.