eslint-plugin-mongodb-security 8.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +181 -0
- package/CHANGELOG.md +36 -0
- package/LICENSE +21 -0
- package/README.md +238 -0
- package/package.json +91 -0
- package/src/index.d.ts +32 -0
- package/src/index.js +148 -0
- package/src/index.js.map +1 -0
- package/src/rules/no-bypass-middleware/index.d.ts +5 -0
- package/src/rules/no-bypass-middleware/index.js +35 -0
- package/src/rules/no-bypass-middleware/index.js.map +1 -0
- package/src/rules/no-debug-mode-production/index.d.ts +5 -0
- package/src/rules/no-debug-mode-production/index.js +35 -0
- package/src/rules/no-debug-mode-production/index.js.map +1 -0
- package/src/rules/no-hardcoded-connection-string/index.d.ts +5 -0
- package/src/rules/no-hardcoded-connection-string/index.js +34 -0
- package/src/rules/no-hardcoded-connection-string/index.js.map +1 -0
- package/src/rules/no-hardcoded-credentials/index.d.ts +5 -0
- package/src/rules/no-hardcoded-credentials/index.js +34 -0
- package/src/rules/no-hardcoded-credentials/index.js.map +1 -0
- package/src/rules/no-operator-injection/index.d.ts +5 -0
- package/src/rules/no-operator-injection/index.js +50 -0
- package/src/rules/no-operator-injection/index.js.map +1 -0
- package/src/rules/no-select-sensitive-fields/index.d.ts +6 -0
- package/src/rules/no-select-sensitive-fields/index.js +35 -0
- package/src/rules/no-select-sensitive-fields/index.js.map +1 -0
- package/src/rules/no-unbounded-find/index.d.ts +5 -0
- package/src/rules/no-unbounded-find/index.js +35 -0
- package/src/rules/no-unbounded-find/index.js.map +1 -0
- package/src/rules/no-unsafe-populate/index.d.ts +5 -0
- package/src/rules/no-unsafe-populate/index.js +35 -0
- package/src/rules/no-unsafe-populate/index.js.map +1 -0
- package/src/rules/no-unsafe-query/index.d.ts +8 -0
- package/src/rules/no-unsafe-query/index.js +189 -0
- package/src/rules/no-unsafe-query/index.js.map +1 -0
- package/src/rules/no-unsafe-regex-query/index.d.ts +5 -0
- package/src/rules/no-unsafe-regex-query/index.js +35 -0
- package/src/rules/no-unsafe-regex-query/index.js.map +1 -0
- package/src/rules/no-unsafe-where/index.d.ts +5 -0
- package/src/rules/no-unsafe-where/index.js +50 -0
- package/src/rules/no-unsafe-where/index.js.map +1 -0
- package/src/rules/require-auth-mechanism/index.d.ts +5 -0
- package/src/rules/require-auth-mechanism/index.js +35 -0
- package/src/rules/require-auth-mechanism/index.js.map +1 -0
- package/src/rules/require-lean-queries/index.d.ts +5 -0
- package/src/rules/require-lean-queries/index.js +35 -0
- package/src/rules/require-lean-queries/index.js.map +1 -0
- package/src/rules/require-projection/index.d.ts +5 -0
- package/src/rules/require-projection/index.js +35 -0
- package/src/rules/require-projection/index.js.map +1 -0
- package/src/rules/require-schema-validation/index.d.ts +5 -0
- package/src/rules/require-schema-validation/index.js +35 -0
- package/src/rules/require-schema-validation/index.js.map +1 -0
- package/src/rules/require-tls-connection/index.d.ts +5 -0
- package/src/rules/require-tls-connection/index.js +35 -0
- package/src/rules/require-tls-connection/index.js.map +1 -0
- package/src/types/index.d.ts +48 -0
- package/src/types/index.js +13 -0
- package/src/types/index.js.map +1 -0
package/AGENTS.md
ADDED
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
# AI Agent Resolution Strategies
|
|
2
|
+
|
|
3
|
+
This document provides resolution strategies for AI assistants (GitHub Copilot, Cursor, Claude) to automatically fix issues reported by `eslint-plugin-mongodb-security`.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## NoSQL Injection Rules
|
|
8
|
+
|
|
9
|
+
### `no-unsafe-query`
|
|
10
|
+
|
|
11
|
+
**Detection**: String concatenation or template literals in MongoDB query objects.
|
|
12
|
+
|
|
13
|
+
**Resolution Strategy**:
|
|
14
|
+
|
|
15
|
+
1. Replace string interpolation with explicit `$eq` operator
|
|
16
|
+
2. Wrap user input with sanitization function
|
|
17
|
+
3. Use schema-validated input
|
|
18
|
+
|
|
19
|
+
```typescript
|
|
20
|
+
// Before (vulnerable)
|
|
21
|
+
db.collection('users').find({ username: userInput });
|
|
22
|
+
|
|
23
|
+
// After (safe)
|
|
24
|
+
db.collection('users').find({ username: { $eq: sanitize(userInput) } });
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
### `no-operator-injection`
|
|
30
|
+
|
|
31
|
+
**Detection**: Direct use of request body/params in MongoDB query operators.
|
|
32
|
+
|
|
33
|
+
**Resolution Strategy**:
|
|
34
|
+
|
|
35
|
+
1. Add explicit `$eq` wrapper around all user inputs
|
|
36
|
+
2. Validate input type before use in query
|
|
37
|
+
3. Use allow-list for expected values
|
|
38
|
+
|
|
39
|
+
```typescript
|
|
40
|
+
// Before (vulnerable - allows { password: { $ne: null } })
|
|
41
|
+
User.findOne({ email: req.body.email, password: req.body.password });
|
|
42
|
+
|
|
43
|
+
// After (safe)
|
|
44
|
+
User.findOne({
|
|
45
|
+
email: { $eq: String(req.body.email) },
|
|
46
|
+
password: { $eq: String(req.body.password) },
|
|
47
|
+
});
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
### `no-unsafe-where`
|
|
53
|
+
|
|
54
|
+
**Detection**: Use of `$where` operator with any dynamic input.
|
|
55
|
+
|
|
56
|
+
**Resolution Strategy**:
|
|
57
|
+
|
|
58
|
+
1. Remove `$where` entirely and replace with standard operators
|
|
59
|
+
2. Never use `$where` with user input
|
|
60
|
+
3. Use aggregation pipeline instead if complex logic needed
|
|
61
|
+
|
|
62
|
+
```typescript
|
|
63
|
+
// Before (vulnerable - CVE-2025-23061)
|
|
64
|
+
db.collection('users').find({ $where: `this.age > ${age}` });
|
|
65
|
+
|
|
66
|
+
// After (safe)
|
|
67
|
+
db.collection('users').find({ age: { $gt: Number(age) } });
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
---
|
|
71
|
+
|
|
72
|
+
### `no-unsafe-regex-query`
|
|
73
|
+
|
|
74
|
+
**Detection**: `$regex` with unescaped user input.
|
|
75
|
+
|
|
76
|
+
**Resolution Strategy**:
|
|
77
|
+
|
|
78
|
+
1. Escape special regex characters
|
|
79
|
+
2. Anchor pattern with `^` and `$` where possible
|
|
80
|
+
3. Add timeout or complexity limits
|
|
81
|
+
|
|
82
|
+
```typescript
|
|
83
|
+
// Before (vulnerable)
|
|
84
|
+
User.find({ name: { $regex: searchTerm } });
|
|
85
|
+
|
|
86
|
+
// After (safe)
|
|
87
|
+
const escaped = searchTerm.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
88
|
+
User.find({ name: { $regex: `^${escaped}`, $options: 'i' } });
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
---
|
|
92
|
+
|
|
93
|
+
## Credential Rules
|
|
94
|
+
|
|
95
|
+
### `no-hardcoded-connection-string`
|
|
96
|
+
|
|
97
|
+
**Resolution Strategy**:
|
|
98
|
+
|
|
99
|
+
1. Replace with `process.env.MONGODB_URI`
|
|
100
|
+
2. Use secret management service
|
|
101
|
+
|
|
102
|
+
```typescript
|
|
103
|
+
// Before
|
|
104
|
+
mongoose.connect('mongodb://admin:password@localhost:27017/mydb');
|
|
105
|
+
|
|
106
|
+
// After
|
|
107
|
+
mongoose.connect(process.env.MONGODB_URI!);
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
---
|
|
111
|
+
|
|
112
|
+
### `require-tls-connection`
|
|
113
|
+
|
|
114
|
+
**Resolution Strategy**:
|
|
115
|
+
|
|
116
|
+
1. Add `{ tls: true }` to connection options
|
|
117
|
+
2. Use `mongodb+srv://` protocol (TLS by default)
|
|
118
|
+
|
|
119
|
+
```typescript
|
|
120
|
+
// Before
|
|
121
|
+
mongoose.connect(uri);
|
|
122
|
+
|
|
123
|
+
// After
|
|
124
|
+
mongoose.connect(uri, { tls: true, tlsCAFile: process.env.MONGO_CA_CERT });
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
---
|
|
128
|
+
|
|
129
|
+
## Mongoose ODM Rules
|
|
130
|
+
|
|
131
|
+
### `no-select-sensitive-fields`
|
|
132
|
+
|
|
133
|
+
**Resolution Strategy**:
|
|
134
|
+
|
|
135
|
+
1. Add `.select('-password -refreshToken')` to queries
|
|
136
|
+
2. Use schema-level `select: false` option
|
|
137
|
+
|
|
138
|
+
```typescript
|
|
139
|
+
// Before
|
|
140
|
+
const user = await User.findById(id);
|
|
141
|
+
|
|
142
|
+
// After
|
|
143
|
+
const user = await User.findById(id).select('-password -refreshToken -apiKey');
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
---
|
|
147
|
+
|
|
148
|
+
### `require-lean-queries`
|
|
149
|
+
|
|
150
|
+
**Resolution Strategy**:
|
|
151
|
+
|
|
152
|
+
1. Add `.lean()` for read-only operations
|
|
153
|
+
2. Keep full documents only when using middleware/virtuals
|
|
154
|
+
|
|
155
|
+
```typescript
|
|
156
|
+
// Before
|
|
157
|
+
const users = await User.find({ active: true });
|
|
158
|
+
|
|
159
|
+
// After
|
|
160
|
+
const users = await User.find({ active: true }).lean();
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
---
|
|
164
|
+
|
|
165
|
+
## Message Format
|
|
166
|
+
|
|
167
|
+
All rules use LLM-optimized messages:
|
|
168
|
+
|
|
169
|
+
```
|
|
170
|
+
🔒 CWE-943 OWASP:A03-Injection CVSS:9.0 | NoSQL injection via user input | CRITICAL
|
|
171
|
+
Fix: Use { field: { $eq: sanitize(value) } } pattern
|
|
172
|
+
https://owasp.org/www-project-web-security-testing-guide/latest/4-Web_Application_Security_Testing/07-Input_Validation_Testing/05.6-Testing_for_NoSQL_Injection
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
---
|
|
176
|
+
|
|
177
|
+
## Related
|
|
178
|
+
|
|
179
|
+
- [OWASP NoSQL Injection Testing](https://owasp.org/www-project-web-security-testing-guide/latest/4-Web_Application_Security_Testing/07-Input_Validation_Testing/05.6-Testing_for_NoSQL_Injection)
|
|
180
|
+
- [CWE-943: NoSQL Injection](https://cwe.mitre.org/data/definitions/943.html)
|
|
181
|
+
- [CVE-2025-23061](https://nvd.nist.gov/vuln/detail/CVE-2025-23061)
|
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to `eslint-plugin-mongodb-security` will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [1.0.0] - 2026-01-XX
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- Initial release with 16 security rules
|
|
13
|
+
- **NoSQL Injection Prevention** (4 rules)
|
|
14
|
+
- `no-unsafe-query` - Prevents string concatenation in MongoDB queries
|
|
15
|
+
- `no-operator-injection` - Prevents $ne, $gt, $lt injection attacks
|
|
16
|
+
- `no-unsafe-where` - Prevents $where operator RCE (CVE-2025-23061, CVE-2024-53900)
|
|
17
|
+
- `no-unsafe-regex-query` - Prevents ReDoS via $regex
|
|
18
|
+
- **Credentials & Connection Security** (4 rules)
|
|
19
|
+
- `no-hardcoded-connection-string` - Prevents credentials in connection URIs
|
|
20
|
+
- `no-hardcoded-credentials` - Prevents hardcoded auth options
|
|
21
|
+
- `require-tls-connection` - Requires TLS for production connections
|
|
22
|
+
- `require-auth-mechanism` - Requires explicit SCRAM-SHA-256
|
|
23
|
+
- **Mongoose ODM Security** (5 rules)
|
|
24
|
+
- `require-schema-validation` - Requires Mongoose schema validators
|
|
25
|
+
- `no-select-sensitive-fields` - Prevents returning password/token fields
|
|
26
|
+
- `no-bypass-middleware` - Prevents bypassing pre/post hooks
|
|
27
|
+
- `no-unsafe-populate` - Prevents user-controlled populate()
|
|
28
|
+
- `require-lean-queries` - Suggests .lean() for read-only queries
|
|
29
|
+
- **Best Practices** (3 rules)
|
|
30
|
+
- `no-unbounded-find` - Requires limit() on find queries
|
|
31
|
+
- `require-projection` - Requires field projection
|
|
32
|
+
- `no-debug-mode-production` - Prevents debug mode in production
|
|
33
|
+
- Full support for `mongodb`, `mongoose`, `mongodb-client-encryption`, `@typegoose/typegoose`
|
|
34
|
+
- AI-optimized error messages with CWE and OWASP references
|
|
35
|
+
- Three configuration presets: `recommended`, `strict`, `mongoose`
|
|
36
|
+
- OWASP Top 10 2021 mapping (A01-A07 coverage)
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Ofri Peretz
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
# eslint-plugin-mongodb-security
|
|
2
|
+
|
|
3
|
+
> 🔐 Security-focused ESLint plugin for MongoDB & Mongoose. Detects NoSQL injection (CVE-2025-23061), operator attacks, credential exposure, and ODM-specific vulnerabilities with AI-optimized fix guidance.
|
|
4
|
+
|
|
5
|
+
[](https://www.npmjs.com/package/eslint-plugin-mongodb-security)
|
|
6
|
+
[](https://www.npmjs.com/package/eslint-plugin-mongodb-security)
|
|
7
|
+
[](https://opensource.org/licenses/MIT)
|
|
8
|
+
[](https://app.codecov.io/gh/ofri-peretz/eslint/components?components%5B0%5D=mongodb-security)
|
|
9
|
+
[](https://github.com/ofri-peretz/eslint)
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## 🎯 The One-Stop Shop for MongoDB Security Linting
|
|
14
|
+
|
|
15
|
+
**This is the comprehensive, actively-maintained ESLint plugin for MongoDB security in Node.js environments.**
|
|
16
|
+
|
|
17
|
+
> ⚠️ **Note**: Other packages like `eslint-plugin-mongodb` and `eslint-plugin-mongo` exist on npm but are outdated, unmaintained, or limited in scope. **eslint-plugin-mongodb-security** is purpose-built for modern security needs, covering the entire MongoDB ecosystem with CVE detection, OWASP mapping, and AI-optimized error messages.
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## 💡 What You Get
|
|
22
|
+
|
|
23
|
+
- **16 Security Rules** — NoSQL injection, operator attacks, credential exposure, ODM patterns
|
|
24
|
+
- **Full Ecosystem Coverage** — MongoDB driver, Mongoose ODM, Client-Side Encryption, Typegoose
|
|
25
|
+
- **2025 CVE Detection** — CVE-2025-23061, CVE-2024-53900 ($where injection in Mongoose)
|
|
26
|
+
- **OWASP Top 10 Mapped** — Every rule references CWE and OWASP categories
|
|
27
|
+
- **AI-Optimized** — Structured messages for GitHub Copilot, Cursor, Claude assistance
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## 📦 Installation
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
npm install --save-dev eslint-plugin-mongodb-security
|
|
35
|
+
# or
|
|
36
|
+
pnpm add -D eslint-plugin-mongodb-security
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## 🚀 Quick Start
|
|
40
|
+
|
|
41
|
+
### Flat Config (ESLint 9+)
|
|
42
|
+
|
|
43
|
+
```javascript
|
|
44
|
+
// eslint.config.js
|
|
45
|
+
import mongodbSecurity from 'eslint-plugin-mongodb-security';
|
|
46
|
+
|
|
47
|
+
export default [
|
|
48
|
+
mongodbSecurity.configs.recommended,
|
|
49
|
+
// or mongodbSecurity.configs.strict for maximum security
|
|
50
|
+
];
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### Custom Configuration
|
|
54
|
+
|
|
55
|
+
```javascript
|
|
56
|
+
import mongodbSecurity from 'eslint-plugin-mongodb-security';
|
|
57
|
+
|
|
58
|
+
export default [
|
|
59
|
+
{
|
|
60
|
+
plugins: { 'mongodb-security': mongodbSecurity },
|
|
61
|
+
rules: {
|
|
62
|
+
// Critical - NoSQL Injection
|
|
63
|
+
'mongodb-security/no-unsafe-query': 'error',
|
|
64
|
+
'mongodb-security/no-operator-injection': 'error',
|
|
65
|
+
'mongodb-security/no-unsafe-where': 'error',
|
|
66
|
+
|
|
67
|
+
// High - Credentials & Connection
|
|
68
|
+
'mongodb-security/no-hardcoded-connection-string': 'error',
|
|
69
|
+
'mongodb-security/require-tls-connection': 'warn',
|
|
70
|
+
|
|
71
|
+
// Medium - ODM Best Practices
|
|
72
|
+
'mongodb-security/require-schema-validation': 'warn',
|
|
73
|
+
'mongodb-security/no-select-sensitive-fields': 'warn',
|
|
74
|
+
},
|
|
75
|
+
},
|
|
76
|
+
];
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
---
|
|
80
|
+
|
|
81
|
+
## 🔐 Rules
|
|
82
|
+
|
|
83
|
+
💼 = Set in `recommended` | 🔧 = Auto-fixable | 💡 = Has suggestions
|
|
84
|
+
|
|
85
|
+
### Critical Severity (NoSQL Injection)
|
|
86
|
+
|
|
87
|
+
| Rule | CWE | OWASP | CVE | Description | 💼 | 💡 |
|
|
88
|
+
| ------------------------------------------------------------ | ------- | -------- | -------------- | ---------------------------------------- | --- | --- |
|
|
89
|
+
| [no-unsafe-query](docs/rules/no-unsafe-query.md) | CWE-943 | A03:2021 | — | Prevents string concatenation in queries | 💼 | 💡 |
|
|
90
|
+
| [no-operator-injection](docs/rules/no-operator-injection.md) | CWE-943 | A03:2021 | — | Prevents $ne, $gt, $lt injection attacks | 💼 | 💡 |
|
|
91
|
+
| [no-unsafe-where](docs/rules/no-unsafe-where.md) | CWE-943 | A01:2021 | CVE-2025-23061 | Prevents $where operator RCE | 💼 | 💡 |
|
|
92
|
+
| [no-unsafe-regex-query](docs/rules/no-unsafe-regex-query.md) | CWE-400 | A03:2021 | — | Prevents ReDoS via $regex | 💼 | 💡 |
|
|
93
|
+
|
|
94
|
+
### High Severity (Credentials & Connection)
|
|
95
|
+
|
|
96
|
+
| Rule | CWE | OWASP | Description | 💼 | 💡 |
|
|
97
|
+
| ------------------------------------------------------------------------------ | ------- | -------- | --------------------------------------- | --- | --- |
|
|
98
|
+
| [no-hardcoded-connection-string](docs/rules/no-hardcoded-connection-string.md) | CWE-798 | A07:2021 | Prevents credentials in connection URIs | 💼 | 💡 |
|
|
99
|
+
| [no-hardcoded-credentials](docs/rules/no-hardcoded-credentials.md) | CWE-798 | A07:2021 | Prevents hardcoded auth options | 💼 | 💡 |
|
|
100
|
+
| [require-tls-connection](docs/rules/require-tls-connection.md) | CWE-295 | A02:2021 | Requires TLS for production connections | 💼 | 💡 |
|
|
101
|
+
| [require-auth-mechanism](docs/rules/require-auth-mechanism.md) | CWE-287 | A07:2021 | Requires explicit SCRAM-SHA-256 | 💼 | 💡 |
|
|
102
|
+
|
|
103
|
+
### Medium Severity (Mongoose ODM)
|
|
104
|
+
|
|
105
|
+
| Rule | CWE | OWASP | Description | 💼 | 💡 |
|
|
106
|
+
| ---------------------------------------------------------------------- | ------- | -------- | ---------------------------------------- | --- | --- |
|
|
107
|
+
| [require-schema-validation](docs/rules/require-schema-validation.md) | CWE-20 | A04:2021 | Requires Mongoose schema validators | 💼 | 💡 |
|
|
108
|
+
| [no-select-sensitive-fields](docs/rules/no-select-sensitive-fields.md) | CWE-200 | A01:2021 | Prevents returning password/token fields | 💼 | 💡 |
|
|
109
|
+
| [no-bypass-middleware](docs/rules/no-bypass-middleware.md) | CWE-284 | A01:2021 | Prevents bypassing pre/post hooks | 💼 | 💡 |
|
|
110
|
+
| [no-unsafe-populate](docs/rules/no-unsafe-populate.md) | CWE-943 | A03:2021 | Prevents user-controlled populate() | 💼 | 💡 |
|
|
111
|
+
|
|
112
|
+
### Low Severity (Best Practices)
|
|
113
|
+
|
|
114
|
+
| Rule | CWE | OWASP | Description | 💼 | 💡 |
|
|
115
|
+
| ------------------------------------------------------------------ | ------- | -------- | -------------------------------------- | --- | --- |
|
|
116
|
+
| [no-unbounded-find](docs/rules/no-unbounded-find.md) | CWE-400 | A04:2021 | Requires limit() on find queries | | 💡 |
|
|
117
|
+
| [require-projection](docs/rules/require-projection.md) | CWE-200 | A01:2021 | Requires field projection | | 💡 |
|
|
118
|
+
| [require-lean-queries](docs/rules/require-lean-queries.md) | CWE-400 | A04:2021 | Suggests .lean() for read-only queries | | 💡 |
|
|
119
|
+
| [no-debug-mode-production](docs/rules/no-debug-mode-production.md) | CWE-489 | A05:2021 | Prevents debug mode in production | 💼 | 💡 |
|
|
120
|
+
|
|
121
|
+
---
|
|
122
|
+
|
|
123
|
+
## 📚 Supported Libraries
|
|
124
|
+
|
|
125
|
+
This plugin analyzes code that uses the following MongoDB/Mongoose libraries. **Both are optional peer dependencies** — you only need to have installed the ones you're using:
|
|
126
|
+
|
|
127
|
+
| Library | npm | Detection | Notes |
|
|
128
|
+
| ------------------------- | --------------------------------------------------------------- | ---------- | ---------------------------------- |
|
|
129
|
+
| mongodb |  | ✅ Full | Native MongoDB driver |
|
|
130
|
+
| mongoose |  | ✅ Full | ODM with schema validation |
|
|
131
|
+
| @nestjs/mongoose |  | ✅ Full | NestJS integration for Mongoose |
|
|
132
|
+
| mongodb-client-encryption |  | ✅ Full | Client-Side Field Level Encryption |
|
|
133
|
+
| @typegoose/typegoose |  | ✅ Partial | TypeScript decorators for Mongoose |
|
|
134
|
+
|
|
135
|
+
> **Note**: `mongodb` and `mongoose` are listed as optional peer dependencies (`peerDependenciesMeta.optional: true`). The plugin works regardless of which MongoDB library you use — rules detect patterns in your code, not the presence of specific packages.
|
|
136
|
+
>
|
|
137
|
+
> **Not covered**: `mongodb-core` (deprecated, merged into mongodb 4.x), `mongodb-memory-server` (testing utility).
|
|
138
|
+
>
|
|
139
|
+
> **NestJS users**: `@nestjs/mongoose` uses standard Mongoose under the hood — all rules apply. For comprehensive NestJS coverage, combine with [`eslint-plugin-nestjs-security`](https://npmjs.com/package/eslint-plugin-nestjs-security).
|
|
140
|
+
|
|
141
|
+
---
|
|
142
|
+
|
|
143
|
+
## 🔒 OWASP Top 10 2021 Coverage
|
|
144
|
+
|
|
145
|
+
| OWASP Category | Rules | Coverage |
|
|
146
|
+
| -------------------------------------- | ------------------------------------------------------------------------------------------------------------ | -------- |
|
|
147
|
+
| **A01:2021 Broken Access Control** | `no-unsafe-where`, `no-select-sensitive-fields`, `no-bypass-middleware` | ✅ |
|
|
148
|
+
| **A02:2021 Cryptographic Failures** | `require-tls-connection` | ✅ |
|
|
149
|
+
| **A03:2021 Injection** | `no-unsafe-query`, `no-operator-injection`, `no-unsafe-where`, `no-unsafe-regex-query`, `no-unsafe-populate` | ✅ |
|
|
150
|
+
| **A04:2021 Insecure Design** | `require-schema-validation`, `no-unbounded-find`, `require-lean-queries` | ✅ |
|
|
151
|
+
| **A05:2021 Security Misconfiguration** | `no-debug-mode-production` | ✅ |
|
|
152
|
+
| **A07:2021 Identification Failures** | `no-hardcoded-connection-string`, `no-hardcoded-credentials`, `require-auth-mechanism` | ✅ |
|
|
153
|
+
|
|
154
|
+
---
|
|
155
|
+
|
|
156
|
+
## 🛡️ Security Research Coverage
|
|
157
|
+
|
|
158
|
+
### CVE-2025-23061 & CVE-2024-53900 (Mongoose $where Injection)
|
|
159
|
+
|
|
160
|
+
The `no-unsafe-where` rule detects `$where` operator usage that allows RCE through JavaScript injection.
|
|
161
|
+
|
|
162
|
+
```javascript
|
|
163
|
+
// ❌ Vulnerable - Allows Remote Code Execution
|
|
164
|
+
User.find({ $where: `this.name === '${userInput}'` });
|
|
165
|
+
User.find().populate({ path: 'posts', match: { $where: userControlled } });
|
|
166
|
+
|
|
167
|
+
// ✅ Safe - Use query operators
|
|
168
|
+
User.find({ name: { $eq: sanitize(userInput) } });
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
### NoSQL Operator Injection
|
|
172
|
+
|
|
173
|
+
The `no-operator-injection` rule prevents authentication bypass attacks.
|
|
174
|
+
|
|
175
|
+
```javascript
|
|
176
|
+
// ❌ Vulnerable - Attacker sends { password: { $ne: null } }
|
|
177
|
+
User.findOne({ email: req.body.email, password: req.body.password });
|
|
178
|
+
|
|
179
|
+
// ✅ Safe - Explicit equality operator
|
|
180
|
+
User.findOne({ email: { $eq: email }, password: { $eq: password } });
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
---
|
|
184
|
+
|
|
185
|
+
## ⚙️ Configuration Presets
|
|
186
|
+
|
|
187
|
+
| Preset | Description | Rules |
|
|
188
|
+
| ------------- | ------------------ | -------------------------------------- |
|
|
189
|
+
| `recommended` | Balanced security | Critical=error, High=warn, Medium=warn |
|
|
190
|
+
| `strict` | Maximum security | All 16 rules=error |
|
|
191
|
+
| `mongoose` | Mongoose ODM focus | ODM-specific rules only |
|
|
192
|
+
|
|
193
|
+
---
|
|
194
|
+
|
|
195
|
+
## 🤖 AI-Optimized Messages
|
|
196
|
+
|
|
197
|
+
Every rule uses `formatLLMMessage` for structured output:
|
|
198
|
+
|
|
199
|
+
```
|
|
200
|
+
🔒 CWE-943 OWASP:A03-Injection CVSS:9.0 | NoSQL injection via $where operator | CRITICAL
|
|
201
|
+
Fix: Remove $where and use standard query operators like $eq, $in, $regex
|
|
202
|
+
https://nvd.nist.gov/vuln/detail/CVE-2025-23061
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
---
|
|
206
|
+
|
|
207
|
+
## 📖 References
|
|
208
|
+
|
|
209
|
+
- [OWASP NoSQL Injection Testing](https://owasp.org/www-project-web-security-testing-guide/latest/4-Web_Application_Security_Testing/07-Input_Validation_Testing/05.6-Testing_for_NoSQL_Injection)
|
|
210
|
+
- [CVE-2025-23061 - Mongoose populate() bypass](https://nvd.nist.gov/vuln/detail/CVE-2025-23061)
|
|
211
|
+
- [CVE-2024-53900 - Mongoose $where RCE](https://nvd.nist.gov/vuln/detail/CVE-2024-53900)
|
|
212
|
+
- [MongoDB Security Checklist](https://www.mongodb.com/docs/manual/administration/security-checklist/)
|
|
213
|
+
- [CWE-943: NoSQL Injection](https://cwe.mitre.org/data/definitions/943.html)
|
|
214
|
+
|
|
215
|
+
---
|
|
216
|
+
|
|
217
|
+
## 🔗 Related ESLint Plugins
|
|
218
|
+
|
|
219
|
+
Part of the **Interlace ESLint Ecosystem** — AI-native security plugins with LLM-optimized error messages:
|
|
220
|
+
|
|
221
|
+
| Plugin | Downloads | Description | Rules |
|
|
222
|
+
| ---------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------ | ----- |
|
|
223
|
+
| [`eslint-plugin-secure-coding`](https://www.npmjs.com/package/eslint-plugin-secure-coding) | [](https://npmjs.com/package/eslint-plugin-secure-coding) | Universal security (OWASP Top 10 Web + Mobile) | 75 |
|
|
224
|
+
| [`eslint-plugin-pg`](https://www.npmjs.com/package/eslint-plugin-pg) | [](https://npmjs.com/package/eslint-plugin-pg) | PostgreSQL/node-postgres security | 13 |
|
|
225
|
+
| [`eslint-plugin-crypto`](https://www.npmjs.com/package/eslint-plugin-crypto) | [](https://npmjs.com/package/eslint-plugin-crypto) | Cryptographic best practices | 24 |
|
|
226
|
+
| [`eslint-plugin-jwt`](https://www.npmjs.com/package/eslint-plugin-jwt) | [](https://npmjs.com/package/eslint-plugin-jwt) | JWT security (algorithm confusion, weak secrets) | 13 |
|
|
227
|
+
| [`eslint-plugin-browser-security`](https://www.npmjs.com/package/eslint-plugin-browser-security) | [](https://npmjs.com/package/eslint-plugin-browser-security) | Browser/DOM security (XSS, postMessage, CSP) | 21 |
|
|
228
|
+
| [`eslint-plugin-vercel-ai-security`](https://www.npmjs.com/package/eslint-plugin-vercel-ai-security) | [](https://npmjs.com/package/eslint-plugin-vercel-ai-security) | Vercel AI SDK security (OWASP LLM Top 10) | 19 |
|
|
229
|
+
| [`eslint-plugin-express-security`](https://www.npmjs.com/package/eslint-plugin-express-security) | [](https://npmjs.com/package/eslint-plugin-express-security) | Express.js security | 9 |
|
|
230
|
+
| [`eslint-plugin-lambda-security`](https://www.npmjs.com/package/eslint-plugin-lambda-security) | [](https://npmjs.com/package/eslint-plugin-lambda-security) | AWS Lambda/Middy security | 13 |
|
|
231
|
+
| [`eslint-plugin-nestjs-security`](https://www.npmjs.com/package/eslint-plugin-nestjs-security) | [](https://npmjs.com/package/eslint-plugin-nestjs-security) | NestJS security (guards, throttling) | 5 |
|
|
232
|
+
| [`eslint-plugin-import-next`](https://www.npmjs.com/package/eslint-plugin-import-next) | [](https://npmjs.com/package/eslint-plugin-import-next) | High-performance import linting | 55 |
|
|
233
|
+
|
|
234
|
+
---
|
|
235
|
+
|
|
236
|
+
## 📄 License
|
|
237
|
+
|
|
238
|
+
MIT © [Ofri Peretz](https://github.com/ofri-peretz)
|
package/package.json
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "eslint-plugin-mongodb-security",
|
|
3
|
+
"version": "8.0.0",
|
|
4
|
+
"description": "Security-focused ESLint plugin for MongoDB & Mongoose. Detects NoSQL injection, operator attacks, credential exposure, and ODM-specific vulnerabilities with AI-optimized fix guidance.",
|
|
5
|
+
"type": "commonjs",
|
|
6
|
+
"main": "./src/index.js",
|
|
7
|
+
"types": "./src/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./src/index.d.ts",
|
|
11
|
+
"default": "./src/index.js"
|
|
12
|
+
},
|
|
13
|
+
"./types": {
|
|
14
|
+
"types": "./src/types/index.d.ts",
|
|
15
|
+
"default": "./src/types/index.js"
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
"author": "Ofri Peretz <ofriperetzdev@gmail.com>",
|
|
19
|
+
"license": "MIT",
|
|
20
|
+
"homepage": "https://github.com/ofri-peretz/eslint/blob/main/packages/eslint-plugin-mongodb-security/README.md",
|
|
21
|
+
"repository": {
|
|
22
|
+
"type": "git",
|
|
23
|
+
"url": "git+https://github.com/ofri-peretz/eslint.git",
|
|
24
|
+
"directory": "packages/eslint-plugin-mongodb-security"
|
|
25
|
+
},
|
|
26
|
+
"bugs": {
|
|
27
|
+
"url": "https://github.com/ofri-peretz/eslint/issues"
|
|
28
|
+
},
|
|
29
|
+
"publishConfig": {
|
|
30
|
+
"access": "public"
|
|
31
|
+
},
|
|
32
|
+
"files": [
|
|
33
|
+
"src/",
|
|
34
|
+
"dist/",
|
|
35
|
+
"README.md",
|
|
36
|
+
"LICENSE",
|
|
37
|
+
"CHANGELOG.md",
|
|
38
|
+
"AGENTS.md"
|
|
39
|
+
],
|
|
40
|
+
"keywords": [
|
|
41
|
+
"eslint",
|
|
42
|
+
"eslint-plugin",
|
|
43
|
+
"eslintplugin",
|
|
44
|
+
"mongodb",
|
|
45
|
+
"mongoose",
|
|
46
|
+
"nosql",
|
|
47
|
+
"security",
|
|
48
|
+
"nosql-injection",
|
|
49
|
+
"owasp",
|
|
50
|
+
"cwe",
|
|
51
|
+
"vulnerability",
|
|
52
|
+
"injection",
|
|
53
|
+
"llm-optimized",
|
|
54
|
+
"ai-assistant",
|
|
55
|
+
"typescript",
|
|
56
|
+
"linting",
|
|
57
|
+
"code-quality",
|
|
58
|
+
"ast",
|
|
59
|
+
"static-analysis",
|
|
60
|
+
"mcp",
|
|
61
|
+
"model-context-protocol",
|
|
62
|
+
"github-copilot",
|
|
63
|
+
"cursor-ai",
|
|
64
|
+
"claude-ai"
|
|
65
|
+
],
|
|
66
|
+
"engines": {
|
|
67
|
+
"node": ">=18.0.0"
|
|
68
|
+
},
|
|
69
|
+
"peerDependencies": {
|
|
70
|
+
"mongodb": "^4.0.0 || ^5.0.0 || ^6.0.0",
|
|
71
|
+
"mongoose": "^6.0.0 || ^7.0.0 || ^8.0.0"
|
|
72
|
+
},
|
|
73
|
+
"peerDependenciesMeta": {
|
|
74
|
+
"mongodb": {
|
|
75
|
+
"optional": true
|
|
76
|
+
},
|
|
77
|
+
"mongoose": {
|
|
78
|
+
"optional": true
|
|
79
|
+
}
|
|
80
|
+
},
|
|
81
|
+
"dependencies": {
|
|
82
|
+
"@interlace/eslint-devkit": "^1.2.1",
|
|
83
|
+
"tslib": "^2.3.0"
|
|
84
|
+
},
|
|
85
|
+
"devDependencies": {
|
|
86
|
+
"@typescript-eslint/parser": "^8.46.2",
|
|
87
|
+
"@typescript-eslint/rule-tester": "^8.46.2",
|
|
88
|
+
"mongodb": "^6.12.0",
|
|
89
|
+
"mongoose": "^8.9.0"
|
|
90
|
+
}
|
|
91
|
+
}
|
package/src/index.d.ts
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* eslint-plugin-mongodb-security
|
|
3
|
+
*
|
|
4
|
+
* Security-focused ESLint plugin for MongoDB & Mongoose.
|
|
5
|
+
* Detects NoSQL injection, operator attacks, credential exposure,
|
|
6
|
+
* and ODM-specific vulnerabilities with AI-optimized fix guidance.
|
|
7
|
+
*
|
|
8
|
+
* Features:
|
|
9
|
+
* - LLM-optimized error messages with CWE references
|
|
10
|
+
* - OWASP Top 10 coverage (A01-A07)
|
|
11
|
+
* - CVE detection (CVE-2025-23061, CVE-2024-53900)
|
|
12
|
+
* - Full support for mongodb, mongoose, mongodb-client-encryption
|
|
13
|
+
*
|
|
14
|
+
* @see https://github.com/ofri-peretz/eslint/tree/main/packages/eslint-plugin-mongodb-security
|
|
15
|
+
*/
|
|
16
|
+
import { TSESLint } from '@interlace/eslint-devkit';
|
|
17
|
+
/**
|
|
18
|
+
* Collection of all MongoDB security rules
|
|
19
|
+
*/
|
|
20
|
+
export declare const rules: Record<string, TSESLint.RuleModule<string, readonly unknown[]>>;
|
|
21
|
+
/**
|
|
22
|
+
* ESLint Plugin object
|
|
23
|
+
*/
|
|
24
|
+
export declare const plugin: TSESLint.FlatConfig.Plugin;
|
|
25
|
+
/**
|
|
26
|
+
* Preset configurations
|
|
27
|
+
*/
|
|
28
|
+
export declare const configs: Record<string, TSESLint.FlatConfig.Config>;
|
|
29
|
+
/**
|
|
30
|
+
* Default export for ESLint plugin
|
|
31
|
+
*/
|
|
32
|
+
export default plugin;
|