Interlace ESLint
ESLint Interlace
MongoDBRules

no-select-sensitive-fields

Detects queries that may return sensitive fields like passwords, tokens, or API keys.

Keywords: CWE-200, information exposure, password, Mongoose, security

Detects queries that may return sensitive fields like passwords, tokens, or API keys.

⚠️ This rule warns by default in the recommended config.

Quick Summary

AspectDetails
CWE ReferenceCWE-200 (Information Exposure)
OWASPA01:2021 - Broken Access Control
SeverityMedium (CVSS: 5.3)
CategorySecurity

Rule Details

Queries without field selection may inadvertently return sensitive data.

❌ Incorrect

// Returns all fields including password
const user = await User.findById(id);
res.json(user); // Password hash exposed!

// Explicit select of sensitive fields
const user = await User.findById(id).select('+password');

✅ Correct

// Exclude sensitive fields
const user = await User.findById(id).select('-password -refreshToken');

// Select only needed fields
const user = await User.findById(id).select('name email avatar');

// Use schema select: false for sensitive fields
const userSchema = new Schema({
  password: { type: String, select: false },
  refreshToken: { type: String, select: false },
});

Options

{
  "rules": {
    "mongodb-security/no-select-sensitive-fields": [
      "warn",
      {
        "sensitiveFields": [
          "password",
          "refreshToken",
          "apiKey",
          "secret",
          "ssn"
        ]
      }
    ]
  }
}

When Not To Use It

  • In authentication flows where password comparison is needed
  • When schema already has select: false on all sensitive fields

Known False Negatives

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

Schema-Level select: false

Why: Schema definitions in other files are not visible.

// ❌ NOT DETECTED - Schema has select: false (safe but not known)
// userSchema.ts: password: { type: String, select: false }
const user = await User.findById(id); // Password already excluded

Mitigation: This is a false positive risk. Use schema-level exclusion as primary defense.

Variable Field Selection

Why: Select arguments from variables are not analyzed.

// ❌ NOT DETECTED - Fields from variable
const fields = '+password';
const user = await User.findById(id).select(fields);

Mitigation: Use inline select strings. Define field lists as constants.

Aggregation Pipeline

Why: Aggregation $project stages are not checked.

// ❌ NOT DETECTED - Sensitive field in aggregation
const users = await User.aggregate([
  { $match: { active: true } },
  { $project: { password: 1 } }, // Includes password!
]);

Mitigation: Review aggregation pipelines. Use $unset for sensitive fields.

Lean Queries

Why: Lean queries bypass middleware that might filter fields.

// ❌ NOT DETECTED - Lean returns raw document
const user = await User.findById(id).lean(); // Includes all fields

Mitigation: Always use .select() with .lean(). Define projection inline.

References

On this page