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
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.noUnsafeQuery = void 0;
|
|
4
|
+
const eslint_devkit_1 = require("@interlace/eslint-devkit");
|
|
5
|
+
// MongoDB/Mongoose query methods
|
|
6
|
+
const QUERY_METHODS = [
|
|
7
|
+
'find',
|
|
8
|
+
'findOne',
|
|
9
|
+
'findById',
|
|
10
|
+
'findOneAndUpdate',
|
|
11
|
+
'findOneAndDelete',
|
|
12
|
+
'findOneAndReplace',
|
|
13
|
+
'findByIdAndUpdate',
|
|
14
|
+
'findByIdAndDelete',
|
|
15
|
+
'updateOne',
|
|
16
|
+
'updateMany',
|
|
17
|
+
'deleteOne',
|
|
18
|
+
'deleteMany',
|
|
19
|
+
'replaceOne',
|
|
20
|
+
'countDocuments',
|
|
21
|
+
'aggregate',
|
|
22
|
+
];
|
|
23
|
+
// Patterns that indicate user input
|
|
24
|
+
const USER_INPUT_PATTERNS = [
|
|
25
|
+
'req.body',
|
|
26
|
+
'req.query',
|
|
27
|
+
'req.params',
|
|
28
|
+
'request.body',
|
|
29
|
+
'request.query',
|
|
30
|
+
'request.params',
|
|
31
|
+
'ctx.request.body',
|
|
32
|
+
'ctx.query',
|
|
33
|
+
'ctx.params',
|
|
34
|
+
];
|
|
35
|
+
/**
|
|
36
|
+
* Check if an expression contains potential user input
|
|
37
|
+
*/
|
|
38
|
+
function containsUserInput(node) {
|
|
39
|
+
const code = getNodeSource(node);
|
|
40
|
+
return USER_INPUT_PATTERNS.some((pattern) => code.includes(pattern));
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Get source code representation of a node (simplified)
|
|
44
|
+
*/
|
|
45
|
+
function getNodeSource(node) {
|
|
46
|
+
if (node.type === eslint_devkit_1.AST_NODE_TYPES.Identifier) {
|
|
47
|
+
return node.name;
|
|
48
|
+
}
|
|
49
|
+
if (node.type === eslint_devkit_1.AST_NODE_TYPES.MemberExpression) {
|
|
50
|
+
const obj = getNodeSource(node.object);
|
|
51
|
+
const prop = node.property.type === eslint_devkit_1.AST_NODE_TYPES.Identifier
|
|
52
|
+
? node.property.name
|
|
53
|
+
: '[computed]';
|
|
54
|
+
return `${obj}.${prop}`;
|
|
55
|
+
}
|
|
56
|
+
if (node.type === eslint_devkit_1.AST_NODE_TYPES.Literal) {
|
|
57
|
+
return String(node.value);
|
|
58
|
+
}
|
|
59
|
+
return '[expression]';
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Check if a property value is potentially unsafe
|
|
63
|
+
*/
|
|
64
|
+
function isUnsafePropertyValue(node) {
|
|
65
|
+
// Direct identifier (variable) - potentially unsafe if from user input
|
|
66
|
+
if (node.type === eslint_devkit_1.AST_NODE_TYPES.Identifier) {
|
|
67
|
+
return true;
|
|
68
|
+
}
|
|
69
|
+
// Member expression like req.body.username
|
|
70
|
+
if (node.type === eslint_devkit_1.AST_NODE_TYPES.MemberExpression) {
|
|
71
|
+
return containsUserInput(node);
|
|
72
|
+
}
|
|
73
|
+
// Template literal - always unsafe for queries
|
|
74
|
+
if (node.type === eslint_devkit_1.AST_NODE_TYPES.TemplateLiteral) {
|
|
75
|
+
return node.expressions.length > 0;
|
|
76
|
+
}
|
|
77
|
+
// Binary expression (string concatenation)
|
|
78
|
+
if (node.type === eslint_devkit_1.AST_NODE_TYPES.BinaryExpression && node.operator === '+') {
|
|
79
|
+
return true;
|
|
80
|
+
}
|
|
81
|
+
return false;
|
|
82
|
+
}
|
|
83
|
+
exports.noUnsafeQuery = (0, eslint_devkit_1.createRule)({
|
|
84
|
+
name: 'no-unsafe-query',
|
|
85
|
+
meta: {
|
|
86
|
+
type: 'problem',
|
|
87
|
+
docs: {
|
|
88
|
+
description: 'Prevent NoSQL injection via direct use of user input in MongoDB queries',
|
|
89
|
+
},
|
|
90
|
+
hasSuggestions: true,
|
|
91
|
+
messages: {
|
|
92
|
+
unsafeQuery: (0, eslint_devkit_1.formatLLMMessage)({
|
|
93
|
+
icon: eslint_devkit_1.MessageIcons.SECURITY,
|
|
94
|
+
issueName: 'NoSQL Injection via Unsafe Query',
|
|
95
|
+
cwe: 'CWE-943',
|
|
96
|
+
owasp: 'A03:2021',
|
|
97
|
+
cvss: 9.8,
|
|
98
|
+
description: 'User input "{{input}}" is used directly in MongoDB query. Attackers can inject operators like { $ne: null } to bypass authentication.',
|
|
99
|
+
severity: 'CRITICAL',
|
|
100
|
+
fix: 'Wrap user input with explicit $eq operator: { field: { $eq: sanitize(value) } }',
|
|
101
|
+
documentationLink: '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',
|
|
102
|
+
}),
|
|
103
|
+
suggestionUseEq: (0, eslint_devkit_1.formatLLMMessage)({
|
|
104
|
+
icon: eslint_devkit_1.MessageIcons.INFO,
|
|
105
|
+
issueName: 'Use $eq Operator',
|
|
106
|
+
description: 'Wrap the value with { $eq: value } to prevent operator injection',
|
|
107
|
+
severity: 'LOW',
|
|
108
|
+
fix: 'Replace direct value with { $eq: sanitizedValue }',
|
|
109
|
+
documentationLink: 'https://www.mongodb.com/docs/manual/reference/operator/query/eq/',
|
|
110
|
+
}),
|
|
111
|
+
},
|
|
112
|
+
schema: [
|
|
113
|
+
{
|
|
114
|
+
type: 'object',
|
|
115
|
+
properties: {
|
|
116
|
+
allowInTests: { type: 'boolean', default: true },
|
|
117
|
+
additionalMethods: {
|
|
118
|
+
type: 'array',
|
|
119
|
+
items: { type: 'string' },
|
|
120
|
+
default: [],
|
|
121
|
+
},
|
|
122
|
+
},
|
|
123
|
+
additionalProperties: false,
|
|
124
|
+
},
|
|
125
|
+
],
|
|
126
|
+
},
|
|
127
|
+
defaultOptions: [{ allowInTests: true, additionalMethods: [] }],
|
|
128
|
+
create(context, [options = {}]) {
|
|
129
|
+
const { allowInTests = true, additionalMethods = [] } = options;
|
|
130
|
+
const filename = context.filename || context.getFilename();
|
|
131
|
+
const isTestFile = /\.(test|spec)\.(ts|tsx|js|jsx)$/.test(filename);
|
|
132
|
+
if (allowInTests && isTestFile) {
|
|
133
|
+
return {};
|
|
134
|
+
}
|
|
135
|
+
const allMethods = [...QUERY_METHODS, ...additionalMethods];
|
|
136
|
+
return {
|
|
137
|
+
CallExpression(node) {
|
|
138
|
+
// Check if this is a MongoDB query method call
|
|
139
|
+
if (node.callee.type !== eslint_devkit_1.AST_NODE_TYPES.MemberExpression) {
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
const methodName = node.callee.property.type === eslint_devkit_1.AST_NODE_TYPES.Identifier
|
|
143
|
+
? node.callee.property.name
|
|
144
|
+
: null;
|
|
145
|
+
if (!methodName || !allMethods.includes(methodName)) {
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
// Check first argument (the query object)
|
|
149
|
+
const queryArg = node.arguments[0];
|
|
150
|
+
if (!queryArg || queryArg.type !== eslint_devkit_1.AST_NODE_TYPES.ObjectExpression) {
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
// Check each property in the query object
|
|
154
|
+
for (const prop of queryArg.properties) {
|
|
155
|
+
if (prop.type !== eslint_devkit_1.AST_NODE_TYPES.Property) {
|
|
156
|
+
continue;
|
|
157
|
+
}
|
|
158
|
+
const value = prop.value;
|
|
159
|
+
// Check if the value is potentially unsafe
|
|
160
|
+
if (isUnsafePropertyValue(value)) {
|
|
161
|
+
const inputSource = getNodeSource(value);
|
|
162
|
+
// Only report if it looks like user input or is a potentially tainted variable
|
|
163
|
+
if (containsUserInput(value) || value.type === eslint_devkit_1.AST_NODE_TYPES.Identifier) {
|
|
164
|
+
context.report({
|
|
165
|
+
node: prop,
|
|
166
|
+
messageId: 'unsafeQuery',
|
|
167
|
+
data: {
|
|
168
|
+
input: inputSource,
|
|
169
|
+
},
|
|
170
|
+
suggest: [
|
|
171
|
+
{
|
|
172
|
+
messageId: 'suggestionUseEq',
|
|
173
|
+
fix(fixer) {
|
|
174
|
+
const sourceCode = context.sourceCode || context.getSourceCode();
|
|
175
|
+
const valueText = sourceCode.getText(value);
|
|
176
|
+
return fixer.replaceText(value, `{ $eq: ${valueText} }`);
|
|
177
|
+
},
|
|
178
|
+
},
|
|
179
|
+
],
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
},
|
|
185
|
+
};
|
|
186
|
+
},
|
|
187
|
+
});
|
|
188
|
+
exports.default = exports.noUnsafeQuery;
|
|
189
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../../packages/eslint-plugin-mongodb-security/src/rules/no-unsafe-query/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.noUnsafeRegexQuery = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* ESLint Rule: no-unsafe-regex-query
|
|
6
|
+
* Detects ReDoS and injection via $regex operator
|
|
7
|
+
* CWE-400: Resource Exhaustion
|
|
8
|
+
*/
|
|
9
|
+
const eslint_devkit_1 = require("@interlace/eslint-devkit");
|
|
10
|
+
exports.noUnsafeRegexQuery = (0, eslint_devkit_1.createRule)({
|
|
11
|
+
name: 'no-unsafe-regex-query',
|
|
12
|
+
meta: {
|
|
13
|
+
type: 'problem',
|
|
14
|
+
docs: { description: 'Prevent ReDoS attacks via $regex with user input' },
|
|
15
|
+
hasSuggestions: true,
|
|
16
|
+
messages: {
|
|
17
|
+
unsafeRegex: (0, eslint_devkit_1.formatLLMMessage)({
|
|
18
|
+
icon: eslint_devkit_1.MessageIcons.SECURITY,
|
|
19
|
+
issueName: 'ReDoS via $regex',
|
|
20
|
+
cwe: 'CWE-400',
|
|
21
|
+
owasp: 'A03:2021',
|
|
22
|
+
cvss: 7.5,
|
|
23
|
+
description: 'User input in $regex can cause ReDoS or information disclosure',
|
|
24
|
+
severity: 'HIGH',
|
|
25
|
+
fix: 'Escape special regex characters and anchor patterns',
|
|
26
|
+
documentationLink: 'https://owasp.org/www-community/attacks/Regular_expression_Denial_of_Service_-_ReDoS',
|
|
27
|
+
}),
|
|
28
|
+
},
|
|
29
|
+
schema: [{ type: 'object', properties: { allowInTests: { type: 'boolean', default: true } }, additionalProperties: false }],
|
|
30
|
+
},
|
|
31
|
+
defaultOptions: [{ allowInTests: true }],
|
|
32
|
+
create() { return {}; },
|
|
33
|
+
});
|
|
34
|
+
exports.default = exports.noUnsafeRegexQuery;
|
|
35
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../../packages/eslint-plugin-mongodb-security/src/rules/no-unsafe-regex-query/index.ts"],"names":[],"mappings":";;;AAAA;;;;GAIG;AACH,4DAAsF;AAMzE,QAAA,kBAAkB,GAAG,IAAA,0BAAU,EAA0B;IACpE,IAAI,EAAE,uBAAuB;IAC7B,IAAI,EAAE;QACJ,IAAI,EAAE,SAAS;QACf,IAAI,EAAE,EAAE,WAAW,EAAE,kDAAkD,EAAE;QACzE,cAAc,EAAE,IAAI;QACpB,QAAQ,EAAE;YACR,WAAW,EAAE,IAAA,gCAAgB,EAAC;gBAC5B,IAAI,EAAE,4BAAY,CAAC,QAAQ;gBAC3B,SAAS,EAAE,kBAAkB;gBAC7B,GAAG,EAAE,SAAS;gBACd,KAAK,EAAE,UAAU;gBACjB,IAAI,EAAE,GAAG;gBACT,WAAW,EAAE,gEAAgE;gBAC7E,QAAQ,EAAE,MAAM;gBAChB,GAAG,EAAE,qDAAqD;gBAC1D,iBAAiB,EAAE,sFAAsF;aAC1G,CAAC;SACH;QACD,MAAM,EAAE,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,UAAU,EAAE,EAAE,YAAY,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE,EAAE,oBAAoB,EAAE,KAAK,EAAE,CAAC;KAC5H;IACD,cAAc,EAAE,CAAC,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC;IACxC,MAAM,KAAK,OAAO,EAAE,CAAC,CAAC,CAAC;CACxB,CAAC,CAAC;AAEH,kBAAe,0BAAkB,CAAC"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.noUnsafeWhere = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* ESLint Rule: no-unsafe-where
|
|
6
|
+
* Detects dangerous $where operator usage (CVE-2025-23061, CVE-2024-53900)
|
|
7
|
+
* CWE-943: NoSQL Injection
|
|
8
|
+
*
|
|
9
|
+
* @see https://nvd.nist.gov/vuln/detail/CVE-2025-23061
|
|
10
|
+
*/
|
|
11
|
+
const eslint_devkit_1 = require("@interlace/eslint-devkit");
|
|
12
|
+
exports.noUnsafeWhere = (0, eslint_devkit_1.createRule)({
|
|
13
|
+
name: 'no-unsafe-where',
|
|
14
|
+
meta: {
|
|
15
|
+
type: 'problem',
|
|
16
|
+
docs: {
|
|
17
|
+
description: 'Prevent $where operator RCE attacks (CVE-2025-23061)',
|
|
18
|
+
},
|
|
19
|
+
hasSuggestions: true,
|
|
20
|
+
messages: {
|
|
21
|
+
unsafeWhere: (0, eslint_devkit_1.formatLLMMessage)({
|
|
22
|
+
icon: eslint_devkit_1.MessageIcons.SECURITY,
|
|
23
|
+
issueName: '$where Operator RCE',
|
|
24
|
+
cwe: 'CWE-943',
|
|
25
|
+
owasp: 'A01:2021',
|
|
26
|
+
cvss: 9.0,
|
|
27
|
+
description: 'The $where operator executes JavaScript and enables Remote Code Execution',
|
|
28
|
+
severity: 'CRITICAL',
|
|
29
|
+
fix: 'Remove $where and use standard query operators like $eq, $in, $regex',
|
|
30
|
+
documentationLink: 'https://nvd.nist.gov/vuln/detail/CVE-2025-23061',
|
|
31
|
+
}),
|
|
32
|
+
},
|
|
33
|
+
schema: [
|
|
34
|
+
{
|
|
35
|
+
type: 'object',
|
|
36
|
+
properties: {
|
|
37
|
+
allowInTests: { type: 'boolean', default: true },
|
|
38
|
+
},
|
|
39
|
+
additionalProperties: false,
|
|
40
|
+
},
|
|
41
|
+
],
|
|
42
|
+
},
|
|
43
|
+
defaultOptions: [{ allowInTests: true }],
|
|
44
|
+
create() {
|
|
45
|
+
// TODO: Implement rule logic
|
|
46
|
+
return {};
|
|
47
|
+
},
|
|
48
|
+
});
|
|
49
|
+
exports.default = exports.noUnsafeWhere;
|
|
50
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../../packages/eslint-plugin-mongodb-security/src/rules/no-unsafe-where/index.ts"],"names":[],"mappings":";;;AAAA;;;;;;GAMG;AACH,4DAIkC;AAUrB,QAAA,aAAa,GAAG,IAAA,0BAAU,EAA0B;IAC/D,IAAI,EAAE,iBAAiB;IACvB,IAAI,EAAE;QACJ,IAAI,EAAE,SAAS;QACf,IAAI,EAAE;YACJ,WAAW,EAAE,sDAAsD;SACpE;QACD,cAAc,EAAE,IAAI;QACpB,QAAQ,EAAE;YACR,WAAW,EAAE,IAAA,gCAAgB,EAAC;gBAC5B,IAAI,EAAE,4BAAY,CAAC,QAAQ;gBAC3B,SAAS,EAAE,qBAAqB;gBAChC,GAAG,EAAE,SAAS;gBACd,KAAK,EAAE,UAAU;gBACjB,IAAI,EAAE,GAAG;gBACT,WAAW,EAAE,2EAA2E;gBACxF,QAAQ,EAAE,UAAU;gBACpB,GAAG,EAAE,sEAAsE;gBAC3E,iBAAiB,EAAE,iDAAiD;aACrE,CAAC;SACH;QACD,MAAM,EAAE;YACN;gBACE,IAAI,EAAE,QAAQ;gBACd,UAAU,EAAE;oBACV,YAAY,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,IAAI,EAAE;iBACjD;gBACD,oBAAoB,EAAE,KAAK;aAC5B;SACF;KACF;IACD,cAAc,EAAE,CAAC,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC;IACxC,MAAM;QACJ,6BAA6B;QAC7B,OAAO,EAAE,CAAC;IACZ,CAAC;CACF,CAAC,CAAC;AAEH,kBAAe,qBAAa,CAAC"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.requireAuthMechanism = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* ESLint Rule: require-auth-mechanism
|
|
6
|
+
* Requires explicit authentication mechanism
|
|
7
|
+
* CWE-287: Improper Authentication
|
|
8
|
+
*/
|
|
9
|
+
const eslint_devkit_1 = require("@interlace/eslint-devkit");
|
|
10
|
+
exports.requireAuthMechanism = (0, eslint_devkit_1.createRule)({
|
|
11
|
+
name: 'require-auth-mechanism',
|
|
12
|
+
meta: {
|
|
13
|
+
type: 'suggestion',
|
|
14
|
+
docs: { description: 'Require explicit authentication mechanism (SCRAM-SHA-256)' },
|
|
15
|
+
hasSuggestions: true,
|
|
16
|
+
messages: {
|
|
17
|
+
requireAuthMechanism: (0, eslint_devkit_1.formatLLMMessage)({
|
|
18
|
+
icon: eslint_devkit_1.MessageIcons.INFO,
|
|
19
|
+
issueName: 'Implicit Auth Mechanism',
|
|
20
|
+
cwe: 'CWE-287',
|
|
21
|
+
owasp: 'A07:2021',
|
|
22
|
+
cvss: 6.5,
|
|
23
|
+
description: 'MongoDB connection uses default authentication mechanism',
|
|
24
|
+
severity: 'MEDIUM',
|
|
25
|
+
fix: 'Add { authMechanism: "SCRAM-SHA-256" } to connection options',
|
|
26
|
+
documentationLink: 'https://www.mongodb.com/docs/manual/core/authentication/',
|
|
27
|
+
}),
|
|
28
|
+
},
|
|
29
|
+
schema: [{ type: 'object', properties: { allowInTests: { type: 'boolean', default: true } }, additionalProperties: false }],
|
|
30
|
+
},
|
|
31
|
+
defaultOptions: [{ allowInTests: true }],
|
|
32
|
+
create() { return {}; },
|
|
33
|
+
});
|
|
34
|
+
exports.default = exports.requireAuthMechanism;
|
|
35
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../../packages/eslint-plugin-mongodb-security/src/rules/require-auth-mechanism/index.ts"],"names":[],"mappings":";;;AAAA;;;;GAIG;AACH,4DAAsF;AAMzE,QAAA,oBAAoB,GAAG,IAAA,0BAAU,EAA0B;IACtE,IAAI,EAAE,wBAAwB;IAC9B,IAAI,EAAE;QACJ,IAAI,EAAE,YAAY;QAClB,IAAI,EAAE,EAAE,WAAW,EAAE,2DAA2D,EAAE;QAClF,cAAc,EAAE,IAAI;QACpB,QAAQ,EAAE;YACR,oBAAoB,EAAE,IAAA,gCAAgB,EAAC;gBACrC,IAAI,EAAE,4BAAY,CAAC,IAAI;gBACvB,SAAS,EAAE,yBAAyB;gBACpC,GAAG,EAAE,SAAS;gBACd,KAAK,EAAE,UAAU;gBACjB,IAAI,EAAE,GAAG;gBACT,WAAW,EAAE,0DAA0D;gBACvE,QAAQ,EAAE,QAAQ;gBAClB,GAAG,EAAE,8DAA8D;gBACnE,iBAAiB,EAAE,0DAA0D;aAC9E,CAAC;SACH;QACD,MAAM,EAAE,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,UAAU,EAAE,EAAE,YAAY,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE,EAAE,oBAAoB,EAAE,KAAK,EAAE,CAAC;KAC5H;IACD,cAAc,EAAE,CAAC,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC;IACxC,MAAM,KAAK,OAAO,EAAE,CAAC,CAAC,CAAC;CACxB,CAAC,CAAC;AAEH,kBAAe,4BAAoB,CAAC"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.requireLeanQueries = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* ESLint Rule: require-lean-queries
|
|
6
|
+
* Suggests .lean() for read-only queries
|
|
7
|
+
* CWE-400: Resource Exhaustion
|
|
8
|
+
*/
|
|
9
|
+
const eslint_devkit_1 = require("@interlace/eslint-devkit");
|
|
10
|
+
exports.requireLeanQueries = (0, eslint_devkit_1.createRule)({
|
|
11
|
+
name: 'require-lean-queries',
|
|
12
|
+
meta: {
|
|
13
|
+
type: 'suggestion',
|
|
14
|
+
docs: { description: 'Suggest .lean() for read-only Mongoose queries' },
|
|
15
|
+
hasSuggestions: true,
|
|
16
|
+
messages: {
|
|
17
|
+
useLean: (0, eslint_devkit_1.formatLLMMessage)({
|
|
18
|
+
icon: eslint_devkit_1.MessageIcons.INFO,
|
|
19
|
+
issueName: 'Consider Using .lean()',
|
|
20
|
+
cwe: 'CWE-400',
|
|
21
|
+
owasp: 'A04:2021',
|
|
22
|
+
cvss: 4.3,
|
|
23
|
+
description: 'Full Mongoose documents use more memory than plain objects',
|
|
24
|
+
severity: 'LOW',
|
|
25
|
+
fix: 'Add .lean() for read-only queries to improve performance',
|
|
26
|
+
documentationLink: 'https://mongoosejs.com/docs/tutorials/lean.html',
|
|
27
|
+
}),
|
|
28
|
+
},
|
|
29
|
+
schema: [{ type: 'object', properties: { allowInTests: { type: 'boolean', default: true } }, additionalProperties: false }],
|
|
30
|
+
},
|
|
31
|
+
defaultOptions: [{ allowInTests: true }],
|
|
32
|
+
create() { return {}; },
|
|
33
|
+
});
|
|
34
|
+
exports.default = exports.requireLeanQueries;
|
|
35
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../../packages/eslint-plugin-mongodb-security/src/rules/require-lean-queries/index.ts"],"names":[],"mappings":";;;AAAA;;;;GAIG;AACH,4DAAsF;AAMzE,QAAA,kBAAkB,GAAG,IAAA,0BAAU,EAA0B;IACpE,IAAI,EAAE,sBAAsB;IAC5B,IAAI,EAAE;QACJ,IAAI,EAAE,YAAY;QAClB,IAAI,EAAE,EAAE,WAAW,EAAE,gDAAgD,EAAE;QACvE,cAAc,EAAE,IAAI;QACpB,QAAQ,EAAE;YACR,OAAO,EAAE,IAAA,gCAAgB,EAAC;gBACxB,IAAI,EAAE,4BAAY,CAAC,IAAI;gBACvB,SAAS,EAAE,wBAAwB;gBACnC,GAAG,EAAE,SAAS;gBACd,KAAK,EAAE,UAAU;gBACjB,IAAI,EAAE,GAAG;gBACT,WAAW,EAAE,4DAA4D;gBACzE,QAAQ,EAAE,KAAK;gBACf,GAAG,EAAE,0DAA0D;gBAC/D,iBAAiB,EAAE,iDAAiD;aACrE,CAAC;SACH;QACD,MAAM,EAAE,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,UAAU,EAAE,EAAE,YAAY,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE,EAAE,oBAAoB,EAAE,KAAK,EAAE,CAAC;KAC5H;IACD,cAAc,EAAE,CAAC,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC;IACxC,MAAM,KAAK,OAAO,EAAE,CAAC,CAAC,CAAC;CACxB,CAAC,CAAC;AAEH,kBAAe,0BAAkB,CAAC"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.requireProjection = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* ESLint Rule: require-projection
|
|
6
|
+
* Requires field projection on queries
|
|
7
|
+
* CWE-200: Information Exposure
|
|
8
|
+
*/
|
|
9
|
+
const eslint_devkit_1 = require("@interlace/eslint-devkit");
|
|
10
|
+
exports.requireProjection = (0, eslint_devkit_1.createRule)({
|
|
11
|
+
name: 'require-projection',
|
|
12
|
+
meta: {
|
|
13
|
+
type: 'suggestion',
|
|
14
|
+
docs: { description: 'Require field projection on MongoDB queries' },
|
|
15
|
+
hasSuggestions: true,
|
|
16
|
+
messages: {
|
|
17
|
+
requireProjection: (0, eslint_devkit_1.formatLLMMessage)({
|
|
18
|
+
icon: eslint_devkit_1.MessageIcons.INFO,
|
|
19
|
+
issueName: 'Missing Projection',
|
|
20
|
+
cwe: 'CWE-200',
|
|
21
|
+
owasp: 'A01:2021',
|
|
22
|
+
cvss: 3.7,
|
|
23
|
+
description: 'Query returns all fields without projection',
|
|
24
|
+
severity: 'LOW',
|
|
25
|
+
fix: 'Add projection to select only required fields',
|
|
26
|
+
documentationLink: 'https://www.mongodb.com/docs/manual/tutorial/project-fields-from-query-results/',
|
|
27
|
+
}),
|
|
28
|
+
},
|
|
29
|
+
schema: [{ type: 'object', properties: { allowInTests: { type: 'boolean', default: true } }, additionalProperties: false }],
|
|
30
|
+
},
|
|
31
|
+
defaultOptions: [{ allowInTests: true }],
|
|
32
|
+
create() { return {}; },
|
|
33
|
+
});
|
|
34
|
+
exports.default = exports.requireProjection;
|
|
35
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../../packages/eslint-plugin-mongodb-security/src/rules/require-projection/index.ts"],"names":[],"mappings":";;;AAAA;;;;GAIG;AACH,4DAAsF;AAMzE,QAAA,iBAAiB,GAAG,IAAA,0BAAU,EAA0B;IACnE,IAAI,EAAE,oBAAoB;IAC1B,IAAI,EAAE;QACJ,IAAI,EAAE,YAAY;QAClB,IAAI,EAAE,EAAE,WAAW,EAAE,6CAA6C,EAAE;QACpE,cAAc,EAAE,IAAI;QACpB,QAAQ,EAAE;YACR,iBAAiB,EAAE,IAAA,gCAAgB,EAAC;gBAClC,IAAI,EAAE,4BAAY,CAAC,IAAI;gBACvB,SAAS,EAAE,oBAAoB;gBAC/B,GAAG,EAAE,SAAS;gBACd,KAAK,EAAE,UAAU;gBACjB,IAAI,EAAE,GAAG;gBACT,WAAW,EAAE,6CAA6C;gBAC1D,QAAQ,EAAE,KAAK;gBACf,GAAG,EAAE,+CAA+C;gBACpD,iBAAiB,EAAE,iFAAiF;aACrG,CAAC;SACH;QACD,MAAM,EAAE,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,UAAU,EAAE,EAAE,YAAY,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE,EAAE,oBAAoB,EAAE,KAAK,EAAE,CAAC;KAC5H;IACD,cAAc,EAAE,CAAC,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC;IACxC,MAAM,KAAK,OAAO,EAAE,CAAC,CAAC,CAAC;CACxB,CAAC,CAAC;AAEH,kBAAe,yBAAiB,CAAC"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.requireSchemaValidation = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* ESLint Rule: require-schema-validation
|
|
6
|
+
* Requires Mongoose schema validation
|
|
7
|
+
* CWE-20: Improper Input Validation
|
|
8
|
+
*/
|
|
9
|
+
const eslint_devkit_1 = require("@interlace/eslint-devkit");
|
|
10
|
+
exports.requireSchemaValidation = (0, eslint_devkit_1.createRule)({
|
|
11
|
+
name: 'require-schema-validation',
|
|
12
|
+
meta: {
|
|
13
|
+
type: 'suggestion',
|
|
14
|
+
docs: { description: 'Require validation on Mongoose schema fields' },
|
|
15
|
+
hasSuggestions: true,
|
|
16
|
+
messages: {
|
|
17
|
+
requireSchemaValidation: (0, eslint_devkit_1.formatLLMMessage)({
|
|
18
|
+
icon: eslint_devkit_1.MessageIcons.INFO,
|
|
19
|
+
issueName: 'Missing Schema Validation',
|
|
20
|
+
cwe: 'CWE-20',
|
|
21
|
+
owasp: 'A04:2021',
|
|
22
|
+
cvss: 6.1,
|
|
23
|
+
description: 'Mongoose schema field lacks validation',
|
|
24
|
+
severity: 'MEDIUM',
|
|
25
|
+
fix: 'Add required, validate, or enum options to schema field',
|
|
26
|
+
documentationLink: 'https://mongoosejs.com/docs/validation.html',
|
|
27
|
+
}),
|
|
28
|
+
},
|
|
29
|
+
schema: [{ type: 'object', properties: { allowInTests: { type: 'boolean', default: true } }, additionalProperties: false }],
|
|
30
|
+
},
|
|
31
|
+
defaultOptions: [{ allowInTests: true }],
|
|
32
|
+
create() { return {}; },
|
|
33
|
+
});
|
|
34
|
+
exports.default = exports.requireSchemaValidation;
|
|
35
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../../packages/eslint-plugin-mongodb-security/src/rules/require-schema-validation/index.ts"],"names":[],"mappings":";;;AAAA;;;;GAIG;AACH,4DAAsF;AAMzE,QAAA,uBAAuB,GAAG,IAAA,0BAAU,EAA0B;IACzE,IAAI,EAAE,2BAA2B;IACjC,IAAI,EAAE;QACJ,IAAI,EAAE,YAAY;QAClB,IAAI,EAAE,EAAE,WAAW,EAAE,8CAA8C,EAAE;QACrE,cAAc,EAAE,IAAI;QACpB,QAAQ,EAAE;YACR,uBAAuB,EAAE,IAAA,gCAAgB,EAAC;gBACxC,IAAI,EAAE,4BAAY,CAAC,IAAI;gBACvB,SAAS,EAAE,2BAA2B;gBACtC,GAAG,EAAE,QAAQ;gBACb,KAAK,EAAE,UAAU;gBACjB,IAAI,EAAE,GAAG;gBACT,WAAW,EAAE,wCAAwC;gBACrD,QAAQ,EAAE,QAAQ;gBAClB,GAAG,EAAE,yDAAyD;gBAC9D,iBAAiB,EAAE,6CAA6C;aACjE,CAAC;SACH;QACD,MAAM,EAAE,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,UAAU,EAAE,EAAE,YAAY,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE,EAAE,oBAAoB,EAAE,KAAK,EAAE,CAAC;KAC5H;IACD,cAAc,EAAE,CAAC,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC;IACxC,MAAM,KAAK,OAAO,EAAE,CAAC,CAAC,CAAC;CACxB,CAAC,CAAC;AAEH,kBAAe,+BAAuB,CAAC"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.requireTlsConnection = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* ESLint Rule: require-tls-connection
|
|
6
|
+
* Requires TLS for MongoDB connections
|
|
7
|
+
* CWE-295: Improper Certificate Validation
|
|
8
|
+
*/
|
|
9
|
+
const eslint_devkit_1 = require("@interlace/eslint-devkit");
|
|
10
|
+
exports.requireTlsConnection = (0, eslint_devkit_1.createRule)({
|
|
11
|
+
name: 'require-tls-connection',
|
|
12
|
+
meta: {
|
|
13
|
+
type: 'problem',
|
|
14
|
+
docs: { description: 'Require TLS for MongoDB connections in production' },
|
|
15
|
+
hasSuggestions: true,
|
|
16
|
+
messages: {
|
|
17
|
+
requireTls: (0, eslint_devkit_1.formatLLMMessage)({
|
|
18
|
+
icon: eslint_devkit_1.MessageIcons.SECURITY,
|
|
19
|
+
issueName: 'Missing TLS Connection',
|
|
20
|
+
cwe: 'CWE-295',
|
|
21
|
+
owasp: 'A02:2021',
|
|
22
|
+
cvss: 7.4,
|
|
23
|
+
description: 'MongoDB connection is not using TLS encryption',
|
|
24
|
+
severity: 'HIGH',
|
|
25
|
+
fix: 'Add { tls: true } to connection options',
|
|
26
|
+
documentationLink: 'https://www.mongodb.com/docs/manual/tutorial/configure-ssl/',
|
|
27
|
+
}),
|
|
28
|
+
},
|
|
29
|
+
schema: [{ type: 'object', properties: { allowInTests: { type: 'boolean', default: true } }, additionalProperties: false }],
|
|
30
|
+
},
|
|
31
|
+
defaultOptions: [{ allowInTests: true }],
|
|
32
|
+
create() { return {}; },
|
|
33
|
+
});
|
|
34
|
+
exports.default = exports.requireTlsConnection;
|
|
35
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../../packages/eslint-plugin-mongodb-security/src/rules/require-tls-connection/index.ts"],"names":[],"mappings":";;;AAAA;;;;GAIG;AACH,4DAAsF;AAMzE,QAAA,oBAAoB,GAAG,IAAA,0BAAU,EAA0B;IACtE,IAAI,EAAE,wBAAwB;IAC9B,IAAI,EAAE;QACJ,IAAI,EAAE,SAAS;QACf,IAAI,EAAE,EAAE,WAAW,EAAE,mDAAmD,EAAE;QAC1E,cAAc,EAAE,IAAI;QACpB,QAAQ,EAAE;YACR,UAAU,EAAE,IAAA,gCAAgB,EAAC;gBAC3B,IAAI,EAAE,4BAAY,CAAC,QAAQ;gBAC3B,SAAS,EAAE,wBAAwB;gBACnC,GAAG,EAAE,SAAS;gBACd,KAAK,EAAE,UAAU;gBACjB,IAAI,EAAE,GAAG;gBACT,WAAW,EAAE,gDAAgD;gBAC7D,QAAQ,EAAE,MAAM;gBAChB,GAAG,EAAE,yCAAyC;gBAC9C,iBAAiB,EAAE,6DAA6D;aACjF,CAAC;SACH;QACD,MAAM,EAAE,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,UAAU,EAAE,EAAE,YAAY,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE,EAAE,oBAAoB,EAAE,KAAK,EAAE,CAAC;KAC5H;IACD,cAAc,EAAE,CAAC,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC;IACxC,MAAM,KAAK,OAAO,EAAE,CAAC,CAAC,CAAC;CACxB,CAAC,CAAC;AAEH,kBAAe,4BAAoB,CAAC"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* eslint-plugin-mongodb-security Type Exports
|
|
3
|
+
*
|
|
4
|
+
* Barrel file that exports all MongoDB security rule Options types.
|
|
5
|
+
*
|
|
6
|
+
* Usage:
|
|
7
|
+
* ```typescript
|
|
8
|
+
* import type { NoUnsafeQueryOptions } from 'eslint-plugin-mongodb-security/types';
|
|
9
|
+
* ```
|
|
10
|
+
*/
|
|
11
|
+
import type { Options as NoUnsafeQueryOptions } from '../rules/no-unsafe-query';
|
|
12
|
+
import type { Options as NoOperatorInjectionOptions } from '../rules/no-operator-injection';
|
|
13
|
+
import type { Options as NoUnsafeWhereOptions } from '../rules/no-unsafe-where';
|
|
14
|
+
import type { Options as NoUnsafeRegexQueryOptions } from '../rules/no-unsafe-regex-query';
|
|
15
|
+
import type { Options as NoHardcodedConnectionStringOptions } from '../rules/no-hardcoded-connection-string';
|
|
16
|
+
import type { Options as NoHardcodedCredentialsOptions } from '../rules/no-hardcoded-credentials';
|
|
17
|
+
import type { Options as RequireTlsConnectionOptions } from '../rules/require-tls-connection';
|
|
18
|
+
import type { Options as RequireAuthMechanismOptions } from '../rules/require-auth-mechanism';
|
|
19
|
+
import type { Options as RequireSchemaValidationOptions } from '../rules/require-schema-validation';
|
|
20
|
+
import type { Options as NoSelectSensitiveFieldsOptions } from '../rules/no-select-sensitive-fields';
|
|
21
|
+
import type { Options as NoBypassMiddlewareOptions } from '../rules/no-bypass-middleware';
|
|
22
|
+
import type { Options as NoUnsafePopulateOptions } from '../rules/no-unsafe-populate';
|
|
23
|
+
import type { Options as NoUnboundedFindOptions } from '../rules/no-unbounded-find';
|
|
24
|
+
import type { Options as RequireProjectionOptions } from '../rules/require-projection';
|
|
25
|
+
import type { Options as RequireLeanQueriesOptions } from '../rules/require-lean-queries';
|
|
26
|
+
import type { Options as NoDebugModeProductionOptions } from '../rules/no-debug-mode-production';
|
|
27
|
+
export type { NoUnsafeQueryOptions, NoOperatorInjectionOptions, NoUnsafeWhereOptions, NoUnsafeRegexQueryOptions, NoHardcodedConnectionStringOptions, NoHardcodedCredentialsOptions, RequireTlsConnectionOptions, RequireAuthMechanismOptions, RequireSchemaValidationOptions, NoSelectSensitiveFieldsOptions, NoBypassMiddlewareOptions, NoUnsafePopulateOptions, NoUnboundedFindOptions, RequireProjectionOptions, RequireLeanQueriesOptions, NoDebugModeProductionOptions, };
|
|
28
|
+
/**
|
|
29
|
+
* Combined type for all MongoDB security rule options
|
|
30
|
+
*/
|
|
31
|
+
export type AllMongoDBSecurityRulesOptions = {
|
|
32
|
+
'no-unsafe-query'?: NoUnsafeQueryOptions;
|
|
33
|
+
'no-operator-injection'?: NoOperatorInjectionOptions;
|
|
34
|
+
'no-unsafe-where'?: NoUnsafeWhereOptions;
|
|
35
|
+
'no-unsafe-regex-query'?: NoUnsafeRegexQueryOptions;
|
|
36
|
+
'no-hardcoded-connection-string'?: NoHardcodedConnectionStringOptions;
|
|
37
|
+
'no-hardcoded-credentials'?: NoHardcodedCredentialsOptions;
|
|
38
|
+
'require-tls-connection'?: RequireTlsConnectionOptions;
|
|
39
|
+
'require-auth-mechanism'?: RequireAuthMechanismOptions;
|
|
40
|
+
'require-schema-validation'?: RequireSchemaValidationOptions;
|
|
41
|
+
'no-select-sensitive-fields'?: NoSelectSensitiveFieldsOptions;
|
|
42
|
+
'no-bypass-middleware'?: NoBypassMiddlewareOptions;
|
|
43
|
+
'no-unsafe-populate'?: NoUnsafePopulateOptions;
|
|
44
|
+
'no-unbounded-find'?: NoUnboundedFindOptions;
|
|
45
|
+
'require-projection'?: RequireProjectionOptions;
|
|
46
|
+
'require-lean-queries'?: RequireLeanQueriesOptions;
|
|
47
|
+
'no-debug-mode-production'?: NoDebugModeProductionOptions;
|
|
48
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* eslint-plugin-mongodb-security Type Exports
|
|
4
|
+
*
|
|
5
|
+
* Barrel file that exports all MongoDB security rule Options types.
|
|
6
|
+
*
|
|
7
|
+
* Usage:
|
|
8
|
+
* ```typescript
|
|
9
|
+
* import type { NoUnsafeQueryOptions } from 'eslint-plugin-mongodb-security/types';
|
|
10
|
+
* ```
|
|
11
|
+
*/
|
|
12
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../packages/eslint-plugin-mongodb-security/src/types/index.ts"],"names":[],"mappings":";AAAA;;;;;;;;;GASG"}
|