Crlf Injection in Nestjs with Firestore
Crlf Injection in Nestjs with Firestore — how this specific combination creates or exposes the vulnerability
Crlf Injection occurs when user-controlled data is reflected in HTTP headers without sanitization, allowing an attacker to inject newline characters (\r\n) to split headers and inject additional content. In a NestJS application that uses Google Cloud Firestore as a backend, this risk arises when Firestore document fields or query parameters are used to construct HTTP responses or headers without validation.
Consider a NestJS controller that retrieves a user profile from Firestore and sets a custom header with the user’s display name:
@Get('profile/:userId')
async getProfile(@Param('userId') userId: string, @Header('x-api-key') apiKey: string) {
const profile = await this.firestore.doc(`profiles/${userId}`).get();
const displayName = profile.get('displayName');
return {
headers: { 'X-Display-Name': displayName },
data: profile.data(),
};
}
If the displayName field contains a value like Alice\r\nX-Injected: malicious, the response header will be split, and the injected header will be interpreted by the recipient (e.g., a downstream proxy or browser). This can lead to HTTP response splitting, cache poisoning, or header-based attacks.
Another common scenario involves logging or error messages that include Firestore document IDs or field values. If an attacker can influence a Firestore document field (e.g., via a compromised account or insecure client-side write), and that field is later echoed in a log line or error response without sanitization, a CRLF sequence can alter the structure of the log or protocol-level messages.
Firestore itself does not introduce CRLF Injection, but its use in NestJS APIs often places user-influenced data into contexts where headers, logs, or structured outputs are generated. The risk is amplified when Firestore documents are used to dynamically construct responses, redirect URLs, or authentication tokens that are then reflected in headers.
Because middleBrick scans the unauthenticated attack surface and tests input validation across 12 security checks in parallel, it can detect CRLF Injection patterns when Firestore-driven data reaches response headers or logs. Findings include severity ratings and remediation guidance mapped to frameworks such as OWASP API Top 10 and PCI-DSS.
Firestore-Specific Remediation in Nestjs — concrete code fixes
Remediation focuses on sanitizing any Firestore-derived data before it is used in HTTP headers, log entries, or other protocol-sensitive contexts. The following patterns are recommended within NestJS services and controllers.
1. Header Sanitization Utility
Create a utility function that strips or encodes newline characters before using data in headers:
export function sanitizeHeader(value: string): string {
return value.replace(/[\r\n]+/g, '');
}
// Usage in controller
@Get('profile/:userId')
async getProfile(@Param('userId') userId: string) {
const profile = await this.firestore.doc(`profiles/${userId}`).get();
const displayName = profile.get('displayName');
return {
headers: { 'X-Display-Name': sanitizeHeader(displayName) },
data: profile.data(),
};
}
2. Firestore Write Validation
When accepting user input to write to Firestore, validate and sanitize string fields to prevent injection of control characters:
import { PipeTransform, BadRequestException } from '@nestjs/common';
export class SanitizeStringPipe implements PipeTransform {
transform(value: string): string {
if (typeof value !== 'string') return value;
const sanitized = value.replace(/[\r\n]+/g, ' ');
return sanitized.trim();
}
}
// DTO example
class UpdateProfileDto {
@IsString()
@Validate(SanitizeStringPipe)
displayName: string;
}
// In controller
async updateProfile(@Body() dto: UpdateProfileDto) {
await this.firestore.doc(`profiles/${dto.userId}`).set(dto, { merge: true });
return { message: 'Profile updated' };
}
3. Structured Logging with Safe Values
When logging Firestore data, ensure log entries do not contain raw header-like sequences. Use structured logging with explicit keys:
import { Logger } from '@nestjs/common';
const logger = new Logger('ProfileService');
async logProfile(profile) {
const safeData = {
id: profile.id,
displayName: profile.get('displayName').replace(/[\r\n]+/g, ''),
email: profile.get('email'),
};
logger.log(`Profile accessed: ${JSON.stringify(safeData)}`);
}
4. MiddleBrick Integration
Using the middleBrick CLI, you can scan your NestJS endpoints to identify CRLF Injection risks. Run middlebrick scan <url> to get a per-category breakdown, including input validation and header reflection tests. The Pro plan enables continuous monitoring so that new Firestore-driven endpoints are automatically scanned on a configurable schedule, and findings can be integrated into GitHub Actions or Slack for team visibility.