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
| Aspect | Details |
|---|---|
| CWE Reference | CWE-200 (Information Exposure) |
| OWASP | A01:2021 - Broken Access Control |
| Severity | Medium (CVSS: 5.3) |
| Category | Security |
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: falseon 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 excludedMitigation: 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 fieldsMitigation: Always use .select() with .lean(). Define projection inline.