Interlace ESLint
ESLint Interlace
MongoDBRules

require-lean-queries

Suggests using `.lean()` for read-only Mongoose queries to reduce memory usage.

Keywords: CWE-400, lean, performance, Mongoose, memory

Suggests using .lean() for read-only Mongoose queries to reduce memory usage.

⚠️ This rule is off by default in the recommended config.

Quick Summary

AspectDetails
CWE ReferenceCWE-400 (Resource Exhaustion)
OWASPA04:2021 - Insecure Design
SeverityLow (CVSS: 4.3)
CategoryPerformance

Error Message Format

The rule provides LLM-optimized error messages (Compact 2-line format) with actionable security guidance:

🔒 CWE-400 OWASP:A06 CVSS:7.5 | Uncontrolled Resource Consumption (ReDoS) detected | HIGH
   Fix: Review and apply the recommended fix | https://owasp.org/Top10/A06_2021/

Message Components

ComponentPurposeExample
Risk StandardsSecurity benchmarksCWE-400 OWASP:A06 CVSS:7.5
Issue DescriptionSpecific vulnerabilityUncontrolled Resource Consumption (ReDoS) detected
Severity & ComplianceImpact assessmentHIGH
Fix InstructionActionable remediationFollow the remediation steps below
Technical TruthOfficial referenceOWASP Top 10

Rule Details

Mongoose documents are fully-featured objects with:

  • Change tracking
  • Virtuals
  • Getters/setters
  • Instance methods

For read-only operations, this overhead is unnecessary and wastes memory.

❌ Incorrect

// Full Mongoose documents - 2-5x memory overhead
const users = await User.find({ active: true });
res.json(users); // Just doing JSON conversion anyway

✅ Correct

// Plain JavaScript objects - minimal memory
const users = await User.find({ active: true }).lean();

// With virtuals if needed
const users = await User.find().lean({ virtuals: true });

// For documents that need modification, skip lean()
const user = await User.findById(id); // Full document
user.lastLogin = new Date();
await user.save();

When Not To Use It

  • When documents need to be modified and saved
  • When virtuals or instance methods are required
  • For small result sets where overhead is negligible

Known False Negatives

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

Query in Variable

Why: Query chains stored in variables are not fully traced.

// ❌ NOT DETECTED - Query stored in variable
let query = User.find({ active: true });
if (needsVirtuals) {
  // Intentionally not using lean
} else {
  query = query.lean();
}
const users = await query;

Mitigation: Use explicit lean() in all execution paths or disable rule selectively.

Abstracted Query Methods

Why: Custom query wrappers are not recognized.

// ❌ NOT DETECTED - Custom query method
async function findActiveUsers() {
  return User.find({ active: true }); // Missing lean
}
const users = await findActiveUsers();

Mitigation: Apply rule to all modules. Add lean() in wrapper functions.

Intentional Save After Query

Why: The rule cannot determine if document modification is intended.

// ❌ FALSE POSITIVE RISK - Document will be saved
const user = await User.findById(id); // Flagged, but needs to be full doc
user.lastLogin = new Date();
await user.save();

Mitigation: Disable rule for files with write operations. Add eslint-disable comments.

Aggregation Pipeline

Why: Aggregation already returns plain objects; lean() is not applicable.

// ❌ NOT DETECTED (correctly) - Aggregation returns plain objects
const stats = await User.aggregate([
  { $group: { _id: null, count: { $sum: 1 } } },
]);

Mitigation: Not applicable - aggregation is already "lean".

References

On this page