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
| Aspect | Details |
|---|---|
| CWE Reference | CWE-400 (Resource Exhaustion) |
| OWASP | A04:2021 - Insecure Design |
| Severity | Low (CVSS: 4.3) |
| Category | Performance |
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
| Component | Purpose | Example |
|---|---|---|
| Risk Standards | Security benchmarks | CWE-400 OWASP:A06 CVSS:7.5 |
| Issue Description | Specific vulnerability | Uncontrolled Resource Consumption (ReDoS) detected |
| Severity & Compliance | Impact assessment | HIGH |
| Fix Instruction | Actionable remediation | Follow the remediation steps below |
| Technical Truth | Official reference | OWASP 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".