Interlace ESLint
ESLint Interlace
NestJSRules

no-exposed-private-fields

This rule detects sensitive fields (like passwords, tokens, secrets) in entity or DTO classes that are not excluded from serialization, which can lead to accide

Detect exposed sensitive fields in DTOs/entities

Rule Details

This rule detects sensitive fields (like passwords, tokens, secrets) in entity or DTO classes that are not excluded from serialization, which can lead to accidental exposure in API responses.

OWASP Mapping

  • OWASP Top 10 2021: A01:2021 - Broken Access Control
  • CWE: CWE-200 - Exposure of Sensitive Information to an Unauthorized Actor
  • CVSS: 7.5 (High)

❌ Incorrect

@Entity()
class User {
  id: string;
  email: string;
  password: string; // Exposed in API responses!
}

✅ Correct

import { Exclude } from 'class-transformer';

@Entity()
class User {
  id: string;
  email: string;

  @Exclude()
  password: string; // Hidden from API responses
}

// Make sure to use ClassSerializerInterceptor
@UseInterceptors(ClassSerializerInterceptor)
@Controller('users')
class UsersController {
  @Get(':id')
  findOne(@Param('id') id: string) {
    return this.usersService.findOne(id);
  }
}

Options

{
  // Skip rule in test files (default: true)
  allowInTests?: boolean;
}

Detected Sensitive Field Names

  • password, passwordHash, hashedPassword
  • secret, secretKey, apiSecret
  • token, accessToken, refreshToken, authToken
  • privateKey, encryptionKey
  • ssn, socialSecurityNumber
  • creditCard, cardNumber

When Not To Use It

  • For internal DTOs not used in API responses
  • For DTOs that are explicitly mapped before sending to clients

Known False Negatives

The following patterns are not detected due to static analysis limitations:

Dynamic Field Names

Why: Computed property names are not analyzed.

// ❌ NOT DETECTED - Dynamic field names
const sensitiveField = 'password';
class User {
  [sensitiveField]: string; // Not recognized as password
}

Mitigation: Use explicit field names. Avoid computed properties for sensitive data.

Custom Serializers

Why: Custom toJSON or serialize methods are not checked.

// ❌ NOT DETECTED - Password exposed in custom serializer
class User {
  @Exclude()
  password: string;

  toJSON() {
    return { ...this, password: this.password }; // Oops!
  }
}

Mitigation: Review custom serializers. Use class-transformer consistently.

Non-Standard Field Names

Why: Only predefined sensitive field names are detected.

// ❌ NOT DETECTED - Custom sensitive field name
class User {
  mySecretCode: string; // Not in default list
}

Mitigation: Configure custom sensitive field patterns in rule options.

Response Object Construction

Why: Manual response object building bypasses detection.

// ❌ NOT DETECTED - Manual response construction
@Get(':id')
async findOne(@Param('id') id: string) {
  const user = await this.userService.findOne(id);
  return { ...user, password: user.password }; // Exposed!
}

Mitigation: Always use serialization interceptors. Use DTOs for responses.

On this page