eslint-plugin-secure-coding 1.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 +196 -0
- package/CHANGELOG.md +105 -0
- package/LICENSE +23 -0
- package/README.md +377 -0
- package/package.json +80 -0
- package/src/index.d.ts +32 -0
- package/src/index.js +345 -0
- package/src/index.js.map +1 -0
- package/src/rules/security/database-injection.d.ts +13 -0
- package/src/rules/security/database-injection.js +407 -0
- package/src/rules/security/database-injection.js.map +1 -0
- package/src/rules/security/detect-child-process.d.ts +11 -0
- package/src/rules/security/detect-child-process.js +460 -0
- package/src/rules/security/detect-child-process.js.map +1 -0
- package/src/rules/security/detect-eval-with-expression.d.ts +9 -0
- package/src/rules/security/detect-eval-with-expression.js +393 -0
- package/src/rules/security/detect-eval-with-expression.js.map +1 -0
- package/src/rules/security/detect-non-literal-fs-filename.d.ts +7 -0
- package/src/rules/security/detect-non-literal-fs-filename.js +322 -0
- package/src/rules/security/detect-non-literal-fs-filename.js.map +1 -0
- package/src/rules/security/detect-non-literal-regexp.d.ts +9 -0
- package/src/rules/security/detect-non-literal-regexp.js +387 -0
- package/src/rules/security/detect-non-literal-regexp.js.map +1 -0
- package/src/rules/security/detect-object-injection.d.ts +11 -0
- package/src/rules/security/detect-object-injection.js +411 -0
- package/src/rules/security/detect-object-injection.js.map +1 -0
- package/src/rules/security/no-buffer-overread.d.ts +14 -0
- package/src/rules/security/no-buffer-overread.js +519 -0
- package/src/rules/security/no-buffer-overread.js.map +1 -0
- package/src/rules/security/no-clickjacking.d.ts +10 -0
- package/src/rules/security/no-clickjacking.js +381 -0
- package/src/rules/security/no-clickjacking.js.map +1 -0
- package/src/rules/security/no-directive-injection.d.ts +12 -0
- package/src/rules/security/no-directive-injection.js +446 -0
- package/src/rules/security/no-directive-injection.js.map +1 -0
- package/src/rules/security/no-document-cookie.d.ts +5 -0
- package/src/rules/security/no-document-cookie.js +90 -0
- package/src/rules/security/no-document-cookie.js.map +1 -0
- package/src/rules/security/no-electron-security-issues.d.ts +10 -0
- package/src/rules/security/no-electron-security-issues.js +421 -0
- package/src/rules/security/no-electron-security-issues.js.map +1 -0
- package/src/rules/security/no-exposed-sensitive-data.d.ts +11 -0
- package/src/rules/security/no-exposed-sensitive-data.js +341 -0
- package/src/rules/security/no-exposed-sensitive-data.js.map +1 -0
- package/src/rules/security/no-format-string-injection.d.ts +17 -0
- package/src/rules/security/no-format-string-injection.js +653 -0
- package/src/rules/security/no-format-string-injection.js.map +1 -0
- package/src/rules/security/no-graphql-injection.d.ts +12 -0
- package/src/rules/security/no-graphql-injection.js +410 -0
- package/src/rules/security/no-graphql-injection.js.map +1 -0
- package/src/rules/security/no-hardcoded-credentials.d.ts +26 -0
- package/src/rules/security/no-hardcoded-credentials.js +377 -0
- package/src/rules/security/no-hardcoded-credentials.js.map +1 -0
- package/src/rules/security/no-improper-sanitization.d.ts +12 -0
- package/src/rules/security/no-improper-sanitization.js +408 -0
- package/src/rules/security/no-improper-sanitization.js.map +1 -0
- package/src/rules/security/no-improper-type-validation.d.ts +10 -0
- package/src/rules/security/no-improper-type-validation.js +420 -0
- package/src/rules/security/no-improper-type-validation.js.map +1 -0
- package/src/rules/security/no-insecure-comparison.d.ts +7 -0
- package/src/rules/security/no-insecure-comparison.js +125 -0
- package/src/rules/security/no-insecure-comparison.js.map +1 -0
- package/src/rules/security/no-insecure-cookie-settings.d.ts +9 -0
- package/src/rules/security/no-insecure-cookie-settings.js +305 -0
- package/src/rules/security/no-insecure-cookie-settings.js.map +1 -0
- package/src/rules/security/no-insecure-jwt.d.ts +10 -0
- package/src/rules/security/no-insecure-jwt.js +338 -0
- package/src/rules/security/no-insecure-jwt.js.map +1 -0
- package/src/rules/security/no-insecure-redirects.d.ts +7 -0
- package/src/rules/security/no-insecure-redirects.js +215 -0
- package/src/rules/security/no-insecure-redirects.js.map +1 -0
- package/src/rules/security/no-insufficient-postmessage-validation.d.ts +14 -0
- package/src/rules/security/no-insufficient-postmessage-validation.js +390 -0
- package/src/rules/security/no-insufficient-postmessage-validation.js.map +1 -0
- package/src/rules/security/no-insufficient-random.d.ts +9 -0
- package/src/rules/security/no-insufficient-random.js +207 -0
- package/src/rules/security/no-insufficient-random.js.map +1 -0
- package/src/rules/security/no-ldap-injection.d.ts +10 -0
- package/src/rules/security/no-ldap-injection.js +449 -0
- package/src/rules/security/no-ldap-injection.js.map +1 -0
- package/src/rules/security/no-missing-authentication.d.ts +13 -0
- package/src/rules/security/no-missing-authentication.js +322 -0
- package/src/rules/security/no-missing-authentication.js.map +1 -0
- package/src/rules/security/no-missing-cors-check.d.ts +9 -0
- package/src/rules/security/no-missing-cors-check.js +449 -0
- package/src/rules/security/no-missing-cors-check.js.map +1 -0
- package/src/rules/security/no-missing-csrf-protection.d.ts +11 -0
- package/src/rules/security/no-missing-csrf-protection.js +183 -0
- package/src/rules/security/no-missing-csrf-protection.js.map +1 -0
- package/src/rules/security/no-missing-security-headers.d.ts +7 -0
- package/src/rules/security/no-missing-security-headers.js +217 -0
- package/src/rules/security/no-missing-security-headers.js.map +1 -0
- package/src/rules/security/no-privilege-escalation.d.ts +13 -0
- package/src/rules/security/no-privilege-escalation.js +321 -0
- package/src/rules/security/no-privilege-escalation.js.map +1 -0
- package/src/rules/security/no-redos-vulnerable-regex.d.ts +7 -0
- package/src/rules/security/no-redos-vulnerable-regex.js +307 -0
- package/src/rules/security/no-redos-vulnerable-regex.js.map +1 -0
- package/src/rules/security/no-sensitive-data-exposure.d.ts +11 -0
- package/src/rules/security/no-sensitive-data-exposure.js +251 -0
- package/src/rules/security/no-sensitive-data-exposure.js.map +1 -0
- package/src/rules/security/no-sql-injection.d.ts +10 -0
- package/src/rules/security/no-sql-injection.js +332 -0
- package/src/rules/security/no-sql-injection.js.map +1 -0
- package/src/rules/security/no-timing-attack.d.ts +10 -0
- package/src/rules/security/no-timing-attack.js +358 -0
- package/src/rules/security/no-timing-attack.js.map +1 -0
- package/src/rules/security/no-toctou-vulnerability.d.ts +7 -0
- package/src/rules/security/no-toctou-vulnerability.js +165 -0
- package/src/rules/security/no-toctou-vulnerability.js.map +1 -0
- package/src/rules/security/no-unchecked-loop-condition.d.ts +12 -0
- package/src/rules/security/no-unchecked-loop-condition.js +635 -0
- package/src/rules/security/no-unchecked-loop-condition.js.map +1 -0
- package/src/rules/security/no-unencrypted-transmission.d.ts +11 -0
- package/src/rules/security/no-unencrypted-transmission.js +237 -0
- package/src/rules/security/no-unencrypted-transmission.js.map +1 -0
- package/src/rules/security/no-unescaped-url-parameter.d.ts +9 -0
- package/src/rules/security/no-unescaped-url-parameter.js +266 -0
- package/src/rules/security/no-unescaped-url-parameter.js.map +1 -0
- package/src/rules/security/no-unlimited-resource-allocation.d.ts +12 -0
- package/src/rules/security/no-unlimited-resource-allocation.js +659 -0
- package/src/rules/security/no-unlimited-resource-allocation.js.map +1 -0
- package/src/rules/security/no-unsafe-deserialization.d.ts +10 -0
- package/src/rules/security/no-unsafe-deserialization.js +501 -0
- package/src/rules/security/no-unsafe-deserialization.js.map +1 -0
- package/src/rules/security/no-unsafe-dynamic-require.d.ts +5 -0
- package/src/rules/security/no-unsafe-dynamic-require.js +107 -0
- package/src/rules/security/no-unsafe-dynamic-require.js.map +1 -0
- package/src/rules/security/no-unsafe-regex-construction.d.ts +9 -0
- package/src/rules/security/no-unsafe-regex-construction.js +292 -0
- package/src/rules/security/no-unsafe-regex-construction.js.map +1 -0
- package/src/rules/security/no-unsanitized-html.d.ts +9 -0
- package/src/rules/security/no-unsanitized-html.js +347 -0
- package/src/rules/security/no-unsanitized-html.js.map +1 -0
- package/src/rules/security/no-unvalidated-user-input.d.ts +9 -0
- package/src/rules/security/no-unvalidated-user-input.js +418 -0
- package/src/rules/security/no-unvalidated-user-input.js.map +1 -0
- package/src/rules/security/no-weak-crypto.d.ts +11 -0
- package/src/rules/security/no-weak-crypto.js +350 -0
- package/src/rules/security/no-weak-crypto.js.map +1 -0
- package/src/rules/security/no-weak-password-recovery.d.ts +12 -0
- package/src/rules/security/no-weak-password-recovery.js +401 -0
- package/src/rules/security/no-weak-password-recovery.js.map +1 -0
- package/src/rules/security/no-xpath-injection.d.ts +10 -0
- package/src/rules/security/no-xpath-injection.js +487 -0
- package/src/rules/security/no-xpath-injection.js.map +1 -0
- package/src/rules/security/no-xxe-injection.d.ts +7 -0
- package/src/rules/security/no-xxe-injection.js +270 -0
- package/src/rules/security/no-xxe-injection.js.map +1 -0
- package/src/rules/security/no-zip-slip.d.ts +9 -0
- package/src/rules/security/no-zip-slip.js +446 -0
- package/src/rules/security/no-zip-slip.js.map +1 -0
- package/src/types/index.d.ts +131 -0
- package/src/types/index.js +18 -0
- package/src/types/index.js.map +1 -0
|
@@ -0,0 +1,418 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.noUnvalidatedUserInput = void 0;
|
|
4
|
+
const eslint_devkit_1 = require("@interlace/eslint-devkit");
|
|
5
|
+
const eslint_devkit_2 = require("@interlace/eslint-devkit");
|
|
6
|
+
/**
|
|
7
|
+
* Patterns that indicate unvalidated user input
|
|
8
|
+
*/
|
|
9
|
+
const UNVALIDATED_INPUT_PATTERNS = [
|
|
10
|
+
// Express/Node.js patterns
|
|
11
|
+
{ pattern: /\breq\.body\b/, name: 'req.body', context: 'Express request body' },
|
|
12
|
+
{ pattern: /\breq\.query\b/, name: 'req.query', context: 'Express query parameters' },
|
|
13
|
+
{ pattern: /\breq\.params\b/, name: 'req.params', context: 'Express route parameters' },
|
|
14
|
+
{ pattern: /\breq\.headers\b/, name: 'req.headers', context: 'Express headers' },
|
|
15
|
+
{ pattern: /\breq\.cookies\b/, name: 'req.cookies', context: 'Express cookies' },
|
|
16
|
+
// Fastify patterns
|
|
17
|
+
{ pattern: /\brequest\.body\b/, name: 'request.body', context: 'Fastify request body' },
|
|
18
|
+
{ pattern: /\brequest\.query\b/, name: 'request.query', context: 'Fastify query parameters' },
|
|
19
|
+
{ pattern: /\brequest\.params\b/, name: 'request.params', context: 'Fastify route parameters' },
|
|
20
|
+
// Next.js patterns
|
|
21
|
+
{ pattern: /\bsearchParams\b/, name: 'searchParams', context: 'Next.js search params' },
|
|
22
|
+
// Generic patterns
|
|
23
|
+
{ pattern: /\buserInput\b/, name: 'userInput', context: 'Generic user input' },
|
|
24
|
+
{ pattern: /\binput\b/, name: 'input', context: 'Generic input variable' },
|
|
25
|
+
];
|
|
26
|
+
/**
|
|
27
|
+
* Check if a node is inside a validation function call
|
|
28
|
+
*/
|
|
29
|
+
function isInsideValidationCall(node, sourceCode, trustedLibraries) {
|
|
30
|
+
let current = node;
|
|
31
|
+
while (current) {
|
|
32
|
+
// Check if current is an argument to a CallExpression
|
|
33
|
+
if (current.parent && current.parent.type === 'CallExpression') {
|
|
34
|
+
const callExpr = current.parent;
|
|
35
|
+
// Verify that current is actually an argument of this call
|
|
36
|
+
const isArgument = callExpr.arguments.some((arg) => arg === current);
|
|
37
|
+
if (!isArgument) {
|
|
38
|
+
// Not an argument, continue traversing
|
|
39
|
+
if ('parent' in current && current.parent) {
|
|
40
|
+
current = current.parent;
|
|
41
|
+
continue;
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
break;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
const callee = callExpr.callee;
|
|
48
|
+
// Check if it's a validation library call (e.g., schema.parse(), schema.validate())
|
|
49
|
+
if (callee.type === 'MemberExpression') {
|
|
50
|
+
const property = callee.property;
|
|
51
|
+
if (property.type === 'Identifier') {
|
|
52
|
+
const methodName = property.name.toLowerCase();
|
|
53
|
+
// Check for validation methods (including async variants)
|
|
54
|
+
// Note: safeParse is one word, not two
|
|
55
|
+
if (['parse', 'validate', 'safeparse', 'parseasync', 'validateasync', 'safe_parse'].includes(methodName)) {
|
|
56
|
+
return true;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
// Check if the object is a validation library
|
|
60
|
+
const object = callee.object;
|
|
61
|
+
if (object.type === 'Identifier') {
|
|
62
|
+
const objectName = object.name.toLowerCase();
|
|
63
|
+
if (trustedLibraries.some(lib => objectName.includes(lib.toLowerCase()))) {
|
|
64
|
+
return true;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
// Check if it's a direct validation function call (e.g., validate(), plainToClass())
|
|
69
|
+
if (callee.type === 'Identifier') {
|
|
70
|
+
const calleeName = callee.name.toLowerCase();
|
|
71
|
+
if (['validate', 'plaintoclass', 'transform'].includes(calleeName)) {
|
|
72
|
+
return true;
|
|
73
|
+
}
|
|
74
|
+
if (trustedLibraries.some(lib => calleeName.includes(lib.toLowerCase()))) {
|
|
75
|
+
return true;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
// Traverse up the AST
|
|
80
|
+
if ('parent' in current && current.parent) {
|
|
81
|
+
current = current.parent;
|
|
82
|
+
}
|
|
83
|
+
else {
|
|
84
|
+
break;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
return false;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Check if a string matches any ignore pattern
|
|
91
|
+
*/
|
|
92
|
+
function matchesIgnorePattern(text, ignorePatterns) {
|
|
93
|
+
return ignorePatterns.some(pattern => {
|
|
94
|
+
try {
|
|
95
|
+
const regex = new RegExp(pattern, 'i');
|
|
96
|
+
return regex.test(text);
|
|
97
|
+
}
|
|
98
|
+
catch {
|
|
99
|
+
// Invalid regex - treat as literal string match
|
|
100
|
+
return text.toLowerCase().includes(pattern.toLowerCase());
|
|
101
|
+
}
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
exports.noUnvalidatedUserInput = (0, eslint_devkit_2.createRule)({
|
|
105
|
+
name: 'no-unvalidated-user-input',
|
|
106
|
+
meta: {
|
|
107
|
+
type: 'problem',
|
|
108
|
+
docs: {
|
|
109
|
+
description: 'Detects unvalidated user input usage (req.body, req.query, etc.)',
|
|
110
|
+
},
|
|
111
|
+
hasSuggestions: true,
|
|
112
|
+
messages: {
|
|
113
|
+
unvalidatedInput: (0, eslint_devkit_1.formatLLMMessage)({
|
|
114
|
+
icon: eslint_devkit_1.MessageIcons.SECURITY,
|
|
115
|
+
issueName: 'Unvalidated User Input',
|
|
116
|
+
cwe: 'CWE-20',
|
|
117
|
+
description: 'Unvalidated user input detected: {{inputSource}}',
|
|
118
|
+
severity: 'HIGH',
|
|
119
|
+
fix: 'Use validation library: {{validationExample}}',
|
|
120
|
+
documentationLink: 'https://cwe.mitre.org/data/definitions/20.html',
|
|
121
|
+
}),
|
|
122
|
+
useValidationLibrary: (0, eslint_devkit_1.formatLLMMessage)({
|
|
123
|
+
icon: eslint_devkit_1.MessageIcons.INFO,
|
|
124
|
+
issueName: 'Use Validation Library',
|
|
125
|
+
description: 'Use validation library',
|
|
126
|
+
severity: 'LOW',
|
|
127
|
+
fix: 'Use Zod, Joi, Yup, or class-validator',
|
|
128
|
+
documentationLink: 'https://zod.dev/',
|
|
129
|
+
}),
|
|
130
|
+
useZod: (0, eslint_devkit_1.formatLLMMessage)({
|
|
131
|
+
icon: eslint_devkit_1.MessageIcons.INFO,
|
|
132
|
+
issueName: 'Use Zod',
|
|
133
|
+
description: 'Use Zod for validation',
|
|
134
|
+
severity: 'LOW',
|
|
135
|
+
fix: 'const data = z.object({ name: z.string() }).parse(req.body)',
|
|
136
|
+
documentationLink: 'https://zod.dev/',
|
|
137
|
+
}),
|
|
138
|
+
useJoi: (0, eslint_devkit_1.formatLLMMessage)({
|
|
139
|
+
icon: eslint_devkit_1.MessageIcons.INFO,
|
|
140
|
+
issueName: 'Use Joi',
|
|
141
|
+
description: 'Use Joi for validation',
|
|
142
|
+
severity: 'LOW',
|
|
143
|
+
fix: 'Joi.object({ name: Joi.string() }).validate(req.body)',
|
|
144
|
+
documentationLink: 'https://joi.dev/',
|
|
145
|
+
}),
|
|
146
|
+
},
|
|
147
|
+
schema: [
|
|
148
|
+
{
|
|
149
|
+
type: 'object',
|
|
150
|
+
properties: {
|
|
151
|
+
allowInTests: {
|
|
152
|
+
type: 'boolean',
|
|
153
|
+
default: false,
|
|
154
|
+
description: 'Allow unvalidated input in test files',
|
|
155
|
+
},
|
|
156
|
+
trustedLibraries: {
|
|
157
|
+
type: 'array',
|
|
158
|
+
items: { type: 'string' },
|
|
159
|
+
default: ['zod', 'joi', 'yup', 'class-validator'],
|
|
160
|
+
description: 'Trusted validation libraries',
|
|
161
|
+
},
|
|
162
|
+
ignorePatterns: {
|
|
163
|
+
type: 'array',
|
|
164
|
+
items: { type: 'string' },
|
|
165
|
+
default: [],
|
|
166
|
+
description: 'Additional safe patterns to ignore',
|
|
167
|
+
},
|
|
168
|
+
},
|
|
169
|
+
additionalProperties: false,
|
|
170
|
+
},
|
|
171
|
+
],
|
|
172
|
+
},
|
|
173
|
+
defaultOptions: [
|
|
174
|
+
{
|
|
175
|
+
allowInTests: false,
|
|
176
|
+
trustedLibraries: ['zod', 'joi', 'yup', 'class-validator'],
|
|
177
|
+
ignorePatterns: [],
|
|
178
|
+
},
|
|
179
|
+
],
|
|
180
|
+
create(context, [options = {}]) {
|
|
181
|
+
const { allowInTests = false, trustedLibraries = ['zod', 'joi', 'yup', 'class-validator'], ignorePatterns = [], } = options;
|
|
182
|
+
const filename = context.getFilename();
|
|
183
|
+
const isTestFile = allowInTests && /\.(test|spec)\.(ts|tsx|js|jsx)$/.test(filename);
|
|
184
|
+
const sourceCode = context.sourceCode || context.sourceCode;
|
|
185
|
+
function checkMemberExpression(node) {
|
|
186
|
+
if (isTestFile) {
|
|
187
|
+
return;
|
|
188
|
+
}
|
|
189
|
+
const text = sourceCode.getText(node);
|
|
190
|
+
// Check if the variable name (if in assignment) matches ignore pattern
|
|
191
|
+
// For cases like: const safeInput = req.body;
|
|
192
|
+
if (node.parent && node.parent.type === 'VariableDeclarator' && node.parent.id.type === 'Identifier') {
|
|
193
|
+
const varName = node.parent.id.name;
|
|
194
|
+
if (matchesIgnorePattern(varName, ignorePatterns)) {
|
|
195
|
+
return;
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
// Check if it matches any ignore pattern
|
|
199
|
+
if (matchesIgnorePattern(text, ignorePatterns)) {
|
|
200
|
+
return;
|
|
201
|
+
}
|
|
202
|
+
// Check if it matches unvalidated input patterns
|
|
203
|
+
// For nested member expressions like req.body.name, check the base (req.body)
|
|
204
|
+
let baseText = text;
|
|
205
|
+
if (node.object.type === 'MemberExpression') {
|
|
206
|
+
baseText = sourceCode.getText(node.object);
|
|
207
|
+
}
|
|
208
|
+
const matchedPattern = UNVALIDATED_INPUT_PATTERNS.find(p => p.pattern.test(text) || p.pattern.test(baseText));
|
|
209
|
+
if (matchedPattern) {
|
|
210
|
+
// Skip if this is a nested member expression and the parent also matches
|
|
211
|
+
// This prevents double reporting for cases like req.query.id
|
|
212
|
+
// We only want to report on the outermost matching expression
|
|
213
|
+
if (node.object.type === 'MemberExpression') {
|
|
214
|
+
const parentText = sourceCode.getText(node.object);
|
|
215
|
+
const parentMatches = UNVALIDATED_INPUT_PATTERNS.some(p => p.pattern.test(parentText));
|
|
216
|
+
if (parentMatches) {
|
|
217
|
+
// Parent also matches, skip this nested one - it will be reported when we visit the parent
|
|
218
|
+
return;
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
// Skip if this is in a destructuring assignment - checkObjectPattern will handle it
|
|
222
|
+
// This prevents double reporting for cases like: const { email } = req.body;
|
|
223
|
+
if (node.parent && node.parent.type === 'VariableDeclarator' && node.parent.id.type === 'ObjectPattern') {
|
|
224
|
+
return; // checkObjectPattern will report on the init instead
|
|
225
|
+
}
|
|
226
|
+
// Check if it's inside a validation call
|
|
227
|
+
if (isInsideValidationCall(node, sourceCode, trustedLibraries)) {
|
|
228
|
+
return;
|
|
229
|
+
}
|
|
230
|
+
// Determine validation example based on context
|
|
231
|
+
let validationExample = 'const schema = z.object({ field: z.string() }); const data = schema.parse(req.body);';
|
|
232
|
+
if (text.includes('query')) {
|
|
233
|
+
validationExample = 'const schema = z.object({ id: z.string() }); const data = schema.parse(req.query);';
|
|
234
|
+
}
|
|
235
|
+
else if (text.includes('params')) {
|
|
236
|
+
validationExample = 'const schema = z.object({ id: z.string() }); const data = schema.parse(req.params);';
|
|
237
|
+
}
|
|
238
|
+
// Build suggestions - provide same code as output for test framework recognition
|
|
239
|
+
const suggestions = [
|
|
240
|
+
{
|
|
241
|
+
messageId: 'useZod',
|
|
242
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
243
|
+
fix: (_fixer) => {
|
|
244
|
+
// This is a suggestion, not an auto-fix, so we return null
|
|
245
|
+
return null;
|
|
246
|
+
},
|
|
247
|
+
},
|
|
248
|
+
{
|
|
249
|
+
messageId: 'useJoi',
|
|
250
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
251
|
+
fix: (_fixer) => {
|
|
252
|
+
return null;
|
|
253
|
+
},
|
|
254
|
+
},
|
|
255
|
+
];
|
|
256
|
+
context.report({
|
|
257
|
+
node,
|
|
258
|
+
messageId: 'unvalidatedInput',
|
|
259
|
+
data: {
|
|
260
|
+
inputSource: matchedPattern.name,
|
|
261
|
+
validationExample,
|
|
262
|
+
},
|
|
263
|
+
suggest: suggestions,
|
|
264
|
+
});
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
function checkIdentifier(node) {
|
|
268
|
+
if (isTestFile) {
|
|
269
|
+
return;
|
|
270
|
+
}
|
|
271
|
+
const text = node.name;
|
|
272
|
+
// Check if it matches any ignore pattern
|
|
273
|
+
if (matchesIgnorePattern(text, ignorePatterns)) {
|
|
274
|
+
return;
|
|
275
|
+
}
|
|
276
|
+
// Skip if this identifier is assigned from a user input source (MemberExpression)
|
|
277
|
+
// For cases like: const userInput = req.body;
|
|
278
|
+
// We should only report on req.body, not on userInput
|
|
279
|
+
// But don't skip if the init is the same identifier (e.g., const data = input;)
|
|
280
|
+
if (node.parent && node.parent.type === 'VariableDeclarator' && node.parent.init) {
|
|
281
|
+
const init = node.parent.init;
|
|
282
|
+
// Only skip if init is a MemberExpression (like req.body) that will be caught by checkMemberExpression
|
|
283
|
+
// Don't skip if init is the same identifier (like input) - we want to report on it
|
|
284
|
+
if (init.type === 'MemberExpression') {
|
|
285
|
+
const initText = sourceCode.getText(init);
|
|
286
|
+
// Check if init matches any user input pattern
|
|
287
|
+
const initMatchesPattern = UNVALIDATED_INPUT_PATTERNS.some(p => p.pattern.test(initText));
|
|
288
|
+
if (initMatchesPattern) {
|
|
289
|
+
return; // Skip - the init (e.g., req.body) will be reported by checkMemberExpression
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
// Check for generic input patterns (userInput, input)
|
|
294
|
+
const matchedPattern = UNVALIDATED_INPUT_PATTERNS.find(p => (p.name === 'userInput' || p.name === 'input') && p.pattern.test(text));
|
|
295
|
+
if (matchedPattern) {
|
|
296
|
+
// Check if it's inside a validation call
|
|
297
|
+
if (isInsideValidationCall(node, sourceCode, trustedLibraries)) {
|
|
298
|
+
return;
|
|
299
|
+
}
|
|
300
|
+
context.report({
|
|
301
|
+
node,
|
|
302
|
+
messageId: 'unvalidatedInput',
|
|
303
|
+
data: {
|
|
304
|
+
inputSource: matchedPattern.name,
|
|
305
|
+
validationExample: 'const schema = z.object({ field: z.string() }); const data = schema.parse(input);',
|
|
306
|
+
},
|
|
307
|
+
suggest: [
|
|
308
|
+
{
|
|
309
|
+
messageId: 'useZod',
|
|
310
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
311
|
+
fix: (_fixer) => null,
|
|
312
|
+
},
|
|
313
|
+
{
|
|
314
|
+
messageId: 'useJoi',
|
|
315
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
316
|
+
fix: (_fixer) => null,
|
|
317
|
+
},
|
|
318
|
+
],
|
|
319
|
+
});
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
function checkObjectPattern(node) {
|
|
323
|
+
if (isTestFile) {
|
|
324
|
+
return;
|
|
325
|
+
}
|
|
326
|
+
// Check destructuring patterns like: const { page, limit } = req.query;
|
|
327
|
+
if (node.parent && node.parent.type === 'VariableDeclarator' && node.parent.init) {
|
|
328
|
+
const init = node.parent.init;
|
|
329
|
+
const initText = sourceCode.getText(init);
|
|
330
|
+
// If init is a CallExpression, check if it's a validation call
|
|
331
|
+
// If so, the input is being validated, so skip
|
|
332
|
+
if (init.type === 'CallExpression') {
|
|
333
|
+
const callee = init.callee;
|
|
334
|
+
if (callee.type === 'MemberExpression' && callee.property.type === 'Identifier') {
|
|
335
|
+
const methodName = callee.property.name.toLowerCase();
|
|
336
|
+
if (['parse', 'validate', 'safeparse', 'parseasync', 'validateasync', 'safe_parse'].includes(methodName)) {
|
|
337
|
+
return; // It's a validation call, skip
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
if (callee.type === 'Identifier') {
|
|
341
|
+
const calleeName = callee.name.toLowerCase();
|
|
342
|
+
if (['validate', 'plaintoclass', 'transform'].includes(calleeName)) {
|
|
343
|
+
return; // It's a validation call, skip
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
// Check if the right side matches unvalidated input patterns
|
|
348
|
+
const matchedPattern = UNVALIDATED_INPUT_PATTERNS.find(p => p.pattern.test(initText));
|
|
349
|
+
if (matchedPattern) {
|
|
350
|
+
// For CallExpressions, check the arguments to see if they're validated
|
|
351
|
+
// The init itself being a validation call was already checked above
|
|
352
|
+
if (init.type === 'CallExpression') {
|
|
353
|
+
// Check each argument to see if it's validated
|
|
354
|
+
// If init is a validation call (like schema.validate(req.body)),
|
|
355
|
+
// then req.body is validated, so skip
|
|
356
|
+
const callee = init.callee;
|
|
357
|
+
const isValidationCall = (callee.type === 'MemberExpression' && callee.property.type === 'Identifier' &&
|
|
358
|
+
['parse', 'validate', 'safeparse', 'parseasync', 'validateasync', 'safe_parse'].includes(callee.property.name.toLowerCase())) ||
|
|
359
|
+
(callee.type === 'Identifier' &&
|
|
360
|
+
['validate', 'plaintoclass', 'transform'].includes(callee.name.toLowerCase()));
|
|
361
|
+
if (isValidationCall) {
|
|
362
|
+
return; // The init is a validation call, so the input is validated
|
|
363
|
+
}
|
|
364
|
+
// If init is not a validation call, check if arguments are validated
|
|
365
|
+
const hasValidatedArg = init.arguments.some((arg) => {
|
|
366
|
+
if (arg.type === 'MemberExpression' || arg.type === 'Identifier') {
|
|
367
|
+
return isInsideValidationCall(arg, sourceCode, trustedLibraries);
|
|
368
|
+
}
|
|
369
|
+
return false;
|
|
370
|
+
});
|
|
371
|
+
if (hasValidatedArg) {
|
|
372
|
+
return; // At least one argument is validated
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
else {
|
|
376
|
+
// For non-call expressions, check if init itself is inside a validation call
|
|
377
|
+
if (isInsideValidationCall(init, sourceCode, trustedLibraries)) {
|
|
378
|
+
return;
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
// Check if variable name matches ignore pattern
|
|
382
|
+
if (node.parent.id.type === 'ObjectPattern') {
|
|
383
|
+
const varText = sourceCode.getText(node.parent.id);
|
|
384
|
+
if (matchesIgnorePattern(varText, ignorePatterns)) {
|
|
385
|
+
return;
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
context.report({
|
|
389
|
+
node: init,
|
|
390
|
+
messageId: 'unvalidatedInput',
|
|
391
|
+
data: {
|
|
392
|
+
inputSource: matchedPattern.name,
|
|
393
|
+
validationExample: 'const schema = z.object({ page: z.string(), limit: z.string() }); const { page, limit } = schema.parse(req.query);',
|
|
394
|
+
},
|
|
395
|
+
suggest: [
|
|
396
|
+
{
|
|
397
|
+
messageId: 'useZod',
|
|
398
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
399
|
+
fix: (_fixer) => null,
|
|
400
|
+
},
|
|
401
|
+
{
|
|
402
|
+
messageId: 'useJoi',
|
|
403
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
404
|
+
fix: (_fixer) => null,
|
|
405
|
+
},
|
|
406
|
+
],
|
|
407
|
+
});
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
return {
|
|
412
|
+
MemberExpression: checkMemberExpression,
|
|
413
|
+
Identifier: checkIdentifier,
|
|
414
|
+
ObjectPattern: checkObjectPattern,
|
|
415
|
+
};
|
|
416
|
+
},
|
|
417
|
+
});
|
|
418
|
+
//# sourceMappingURL=no-unvalidated-user-input.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"no-unvalidated-user-input.js","sourceRoot":"","sources":["../../../../../../packages/eslint-plugin-secure-coding/src/rules/security/no-unvalidated-user-input.ts"],"names":[],"mappings":";;;AASA,4DAA0E;AAC1E,4DAAsD;AAiBtD;;GAEG;AACH,MAAM,0BAA0B,GAAG;IACjC,2BAA2B;IAC3B,EAAE,OAAO,EAAE,eAAe,EAAE,IAAI,EAAE,UAAU,EAAE,OAAO,EAAE,sBAAsB,EAAE;IAC/E,EAAE,OAAO,EAAE,gBAAgB,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,0BAA0B,EAAE;IACrF,EAAE,OAAO,EAAE,iBAAiB,EAAE,IAAI,EAAE,YAAY,EAAE,OAAO,EAAE,0BAA0B,EAAE;IACvF,EAAE,OAAO,EAAE,kBAAkB,EAAE,IAAI,EAAE,aAAa,EAAE,OAAO,EAAE,iBAAiB,EAAE;IAChF,EAAE,OAAO,EAAE,kBAAkB,EAAE,IAAI,EAAE,aAAa,EAAE,OAAO,EAAE,iBAAiB,EAAE;IAEhF,mBAAmB;IACnB,EAAE,OAAO,EAAE,mBAAmB,EAAE,IAAI,EAAE,cAAc,EAAE,OAAO,EAAE,sBAAsB,EAAE;IACvF,EAAE,OAAO,EAAE,oBAAoB,EAAE,IAAI,EAAE,eAAe,EAAE,OAAO,EAAE,0BAA0B,EAAE;IAC7F,EAAE,OAAO,EAAE,qBAAqB,EAAE,IAAI,EAAE,gBAAgB,EAAE,OAAO,EAAE,0BAA0B,EAAE;IAE/F,mBAAmB;IACnB,EAAE,OAAO,EAAE,kBAAkB,EAAE,IAAI,EAAE,cAAc,EAAE,OAAO,EAAE,uBAAuB,EAAE;IAEvF,mBAAmB;IACnB,EAAE,OAAO,EAAE,eAAe,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,oBAAoB,EAAE;IAC9E,EAAE,OAAO,EAAE,WAAW,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,wBAAwB,EAAE;CAC3E,CAAC;AAEF;;GAEG;AACH,SAAS,sBAAsB,CAC7B,IAAmB,EACnB,UAA+B,EAC/B,gBAA0B;IAE1B,IAAI,OAAO,GAAyB,IAAI,CAAC;IAEzC,OAAO,OAAO,EAAE,CAAC;QACf,sDAAsD;QACtD,IAAI,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC,MAAM,CAAC,IAAI,KAAK,gBAAgB,EAAE,CAAC;YAC/D,MAAM,QAAQ,GAAG,OAAO,CAAC,MAAiC,CAAC;YAE3D,2DAA2D;YAC3D,MAAM,UAAU,GAAG,QAAQ,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,GAAoC,EAAE,EAAE,CAAC,GAAG,KAAK,OAAO,CAAC,CAAC;YACtG,IAAI,CAAC,UAAU,EAAE,CAAC;gBAChB,uCAAuC;gBACvC,IAAI,QAAQ,IAAI,OAAO,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;oBAC1C,OAAO,GAAG,OAAO,CAAC,MAAuB,CAAC;oBAC1C,SAAS;gBACX,CAAC;qBAAM,CAAC;oBACN,MAAM;gBACR,CAAC;YACH,CAAC;YAED,MAAM,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAC;YAE/B,oFAAoF;YACpF,IAAI,MAAM,CAAC,IAAI,KAAK,kBAAkB,EAAE,CAAC;gBACvC,MAAM,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC;gBACjC,IAAI,QAAQ,CAAC,IAAI,KAAK,YAAY,EAAE,CAAC;oBACnC,MAAM,UAAU,GAAG,QAAQ,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;oBAC/C,0DAA0D;oBAC1D,uCAAuC;oBACvC,IAAI,CAAC,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,YAAY,EAAE,eAAe,EAAE,YAAY,CAAC,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC;wBACzG,OAAO,IAAI,CAAC;oBACd,CAAC;gBACH,CAAC;gBAED,8CAA8C;gBAC9C,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC;gBAC7B,IAAI,MAAM,CAAC,IAAI,KAAK,YAAY,EAAE,CAAC;oBACjC,MAAM,UAAU,GAAG,MAAM,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;oBAC7C,IAAI,gBAAgB,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC,CAAC,EAAE,CAAC;wBACzE,OAAO,IAAI,CAAC;oBACd,CAAC;gBACH,CAAC;YACH,CAAC;YAED,qFAAqF;YACrF,IAAI,MAAM,CAAC,IAAI,KAAK,YAAY,EAAE,CAAC;gBACjC,MAAM,UAAU,GAAG,MAAM,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;gBAC7C,IAAI,CAAC,UAAU,EAAE,cAAc,EAAE,WAAW,CAAC,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC;oBACnE,OAAO,IAAI,CAAC;gBACd,CAAC;gBACD,IAAI,gBAAgB,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC,CAAC,EAAE,CAAC;oBACzE,OAAO,IAAI,CAAC;gBACd,CAAC;YACH,CAAC;QACH,CAAC;QAED,sBAAsB;QACtB,IAAI,QAAQ,IAAI,OAAO,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;YAC1C,OAAO,GAAG,OAAO,CAAC,MAAuB,CAAC;QAC5C,CAAC;aAAM,CAAC;YACN,MAAM;QACR,CAAC;IACH,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;GAEG;AACH,SAAS,oBAAoB,CAAC,IAAY,EAAE,cAAwB;IAClE,OAAO,cAAc,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE;QACnC,IAAI,CAAC;YACH,MAAM,KAAK,GAAG,IAAI,MAAM,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;YACvC,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC1B,CAAC;QAAC,MAAM,CAAC;YACP,gDAAgD;YAChD,OAAO,IAAI,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC;QAC5D,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC;AAEY,QAAA,sBAAsB,GAAG,IAAA,0BAAU,EAA0B;IACxE,IAAI,EAAE,2BAA2B;IACjC,IAAI,EAAE;QACJ,IAAI,EAAE,SAAS;QACf,IAAI,EAAE;YACJ,WAAW,EAAE,kEAAkE;SAChF;QACD,cAAc,EAAE,IAAI;QACpB,QAAQ,EAAE;YACR,gBAAgB,EAAE,IAAA,gCAAgB,EAAC;gBACjC,IAAI,EAAE,4BAAY,CAAC,QAAQ;gBAC3B,SAAS,EAAE,wBAAwB;gBACnC,GAAG,EAAE,QAAQ;gBACb,WAAW,EAAE,kDAAkD;gBAC/D,QAAQ,EAAE,MAAM;gBAChB,GAAG,EAAE,+CAA+C;gBACpD,iBAAiB,EAAE,gDAAgD;aACpE,CAAC;YACF,oBAAoB,EAAE,IAAA,gCAAgB,EAAC;gBACrC,IAAI,EAAE,4BAAY,CAAC,IAAI;gBACvB,SAAS,EAAE,wBAAwB;gBACnC,WAAW,EAAE,wBAAwB;gBACrC,QAAQ,EAAE,KAAK;gBACf,GAAG,EAAE,uCAAuC;gBAC5C,iBAAiB,EAAE,kBAAkB;aACtC,CAAC;YACF,MAAM,EAAE,IAAA,gCAAgB,EAAC;gBACvB,IAAI,EAAE,4BAAY,CAAC,IAAI;gBACvB,SAAS,EAAE,SAAS;gBACpB,WAAW,EAAE,wBAAwB;gBACrC,QAAQ,EAAE,KAAK;gBACf,GAAG,EAAE,6DAA6D;gBAClE,iBAAiB,EAAE,kBAAkB;aACtC,CAAC;YACF,MAAM,EAAE,IAAA,gCAAgB,EAAC;gBACvB,IAAI,EAAE,4BAAY,CAAC,IAAI;gBACvB,SAAS,EAAE,SAAS;gBACpB,WAAW,EAAE,wBAAwB;gBACrC,QAAQ,EAAE,KAAK;gBACf,GAAG,EAAE,uDAAuD;gBAC5D,iBAAiB,EAAE,kBAAkB;aACtC,CAAC;SACH;QACD,MAAM,EAAE;YACN;gBACE,IAAI,EAAE,QAAQ;gBACd,UAAU,EAAE;oBACV,YAAY,EAAE;wBACZ,IAAI,EAAE,SAAS;wBACf,OAAO,EAAE,KAAK;wBACd,WAAW,EAAE,uCAAuC;qBACrD;oBACD,gBAAgB,EAAE;wBAChB,IAAI,EAAE,OAAO;wBACb,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;wBACzB,OAAO,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,iBAAiB,CAAC;wBACjD,WAAW,EAAE,8BAA8B;qBAC5C;oBACD,cAAc,EAAE;wBACd,IAAI,EAAE,OAAO;wBACb,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;wBACzB,OAAO,EAAE,EAAE;wBACX,WAAW,EAAE,oCAAoC;qBAClD;iBACF;gBACD,oBAAoB,EAAE,KAAK;aAC5B;SACF;KACF;IACD,cAAc,EAAE;QACd;YACE,YAAY,EAAE,KAAK;YACnB,gBAAgB,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,iBAAiB,CAAC;YAC1D,cAAc,EAAE,EAAE;SACnB;KACF;IACD,MAAM,CACJ,OAAsD,EACtD,CAAC,OAAO,GAAG,EAAE,CAAC;QAEd,MAAM,EACJ,YAAY,GAAG,KAAK,EACpB,gBAAgB,GAAG,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,iBAAiB,CAAC,EAC3D,cAAc,GAAG,EAAE,GACpB,GAAG,OAAkB,CAAC;QAEvB,MAAM,QAAQ,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;QACvC,MAAM,UAAU,GAAG,YAAY,IAAI,iCAAiC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACpF,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,IAAI,OAAO,CAAC,UAAU,CAAC;QAE5D,SAAS,qBAAqB,CAAC,IAA+B;YAC5D,IAAI,UAAU,EAAE,CAAC;gBACf,OAAO;YACT,CAAC;YAED,MAAM,IAAI,GAAG,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;YAEtC,uEAAuE;YACvE,8CAA8C;YAC9C,IAAI,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,MAAM,CAAC,IAAI,KAAK,oBAAoB,IAAI,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,KAAK,YAAY,EAAE,CAAC;gBACrG,MAAM,OAAO,GAAG,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,CAAC;gBACpC,IAAI,oBAAoB,CAAC,OAAO,EAAE,cAAc,CAAC,EAAE,CAAC;oBAClD,OAAO;gBACT,CAAC;YACH,CAAC;YAED,yCAAyC;YACzC,IAAI,oBAAoB,CAAC,IAAI,EAAE,cAAc,CAAC,EAAE,CAAC;gBAC/C,OAAO;YACT,CAAC;YAED,iDAAiD;YACjD,8EAA8E;YAC9E,IAAI,QAAQ,GAAG,IAAI,CAAC;YACpB,IAAI,IAAI,CAAC,MAAM,CAAC,IAAI,KAAK,kBAAkB,EAAE,CAAC;gBAC5C,QAAQ,GAAG,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YAC7C,CAAC;YAED,MAAM,cAAc,GAAG,0BAA0B,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CACzD,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CACjD,CAAC;YAEF,IAAI,cAAc,EAAE,CAAC;gBACnB,yEAAyE;gBACzE,6DAA6D;gBAC7D,8DAA8D;gBAC9D,IAAI,IAAI,CAAC,MAAM,CAAC,IAAI,KAAK,kBAAkB,EAAE,CAAC;oBAC5C,MAAM,UAAU,GAAG,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;oBACnD,MAAM,aAAa,GAAG,0BAA0B,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC;oBACvF,IAAI,aAAa,EAAE,CAAC;wBAClB,2FAA2F;wBAC3F,OAAO;oBACT,CAAC;gBACH,CAAC;gBAED,oFAAoF;gBACpF,6EAA6E;gBAC7E,IAAI,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,MAAM,CAAC,IAAI,KAAK,oBAAoB,IAAI,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,KAAK,eAAe,EAAE,CAAC;oBACxG,OAAO,CAAC,qDAAqD;gBAC/D,CAAC;gBAED,yCAAyC;gBACzC,IAAI,sBAAsB,CAAC,IAAI,EAAE,UAAU,EAAE,gBAAgB,CAAC,EAAE,CAAC;oBAC/D,OAAO;gBACT,CAAC;gBAED,gDAAgD;gBAChD,IAAI,iBAAiB,GAAG,sFAAsF,CAAC;gBAC/G,IAAI,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;oBAC3B,iBAAiB,GAAG,oFAAoF,CAAC;gBAC3G,CAAC;qBAAM,IAAI,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;oBACnC,iBAAiB,GAAG,qFAAqF,CAAC;gBAC5G,CAAC;gBAED,iFAAiF;gBACjF,MAAM,WAAW,GAAsD;oBACrE;wBACE,SAAS,EAAE,QAAQ;wBACnB,6DAA6D;wBAC7D,GAAG,EAAE,CAAC,MAA0B,EAAE,EAAE;4BAClC,2DAA2D;4BAC3D,OAAO,IAAI,CAAC;wBACd,CAAC;qBACF;oBACD;wBACE,SAAS,EAAE,QAAQ;wBACnB,6DAA6D;wBAC7D,GAAG,EAAE,CAAC,MAA0B,EAAE,EAAE;4BAClC,OAAO,IAAI,CAAC;wBACd,CAAC;qBACF;iBACF,CAAC;gBAEF,OAAO,CAAC,MAAM,CAAC;oBACb,IAAI;oBACJ,SAAS,EAAE,kBAAkB;oBAC7B,IAAI,EAAE;wBACJ,WAAW,EAAE,cAAc,CAAC,IAAI;wBAChC,iBAAiB;qBAClB;oBACD,OAAO,EAAE,WAAW;iBACrB,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QAED,SAAS,eAAe,CAAC,IAAyB;YAChD,IAAI,UAAU,EAAE,CAAC;gBACf,OAAO;YACT,CAAC;YAED,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC;YAEvB,yCAAyC;YACzC,IAAI,oBAAoB,CAAC,IAAI,EAAE,cAAc,CAAC,EAAE,CAAC;gBAC/C,OAAO;YACT,CAAC;YAED,kFAAkF;YAClF,8CAA8C;YAC9C,sDAAsD;YACtD,gFAAgF;YAChF,IAAI,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,MAAM,CAAC,IAAI,KAAK,oBAAoB,IAAI,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;gBACjF,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC;gBAC9B,uGAAuG;gBACvG,mFAAmF;gBACnF,IAAI,IAAI,CAAC,IAAI,KAAK,kBAAkB,EAAE,CAAC;oBACrC,MAAM,QAAQ,GAAG,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;oBAC1C,+CAA+C;oBAC/C,MAAM,kBAAkB,GAAG,0BAA0B,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC;oBAC1F,IAAI,kBAAkB,EAAE,CAAC;wBACvB,OAAO,CAAC,6EAA6E;oBACvF,CAAC;gBACH,CAAC;YACH,CAAC;YAED,sDAAsD;YACtD,MAAM,cAAc,GAAG,0BAA0B,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CACzD,CAAC,CAAC,CAAC,IAAI,KAAK,WAAW,IAAI,CAAC,CAAC,IAAI,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CACvE,CAAC;YAEF,IAAI,cAAc,EAAE,CAAC;gBACnB,yCAAyC;gBACzC,IAAI,sBAAsB,CAAC,IAAI,EAAE,UAAU,EAAE,gBAAgB,CAAC,EAAE,CAAC;oBAC/D,OAAO;gBACT,CAAC;gBAED,OAAO,CAAC,MAAM,CAAC;oBACb,IAAI;oBACJ,SAAS,EAAE,kBAAkB;oBAC7B,IAAI,EAAE;wBACJ,WAAW,EAAE,cAAc,CAAC,IAAI;wBAChC,iBAAiB,EAAE,mFAAmF;qBACvG;oBACD,OAAO,EAAE;wBACP;4BACE,SAAS,EAAE,QAAQ;4BACnB,6DAA6D;4BAC7D,GAAG,EAAE,CAAC,MAA0B,EAAE,EAAE,CAAC,IAAI;yBAC1C;wBACD;4BACE,SAAS,EAAE,QAAQ;4BACnB,6DAA6D;4BAC7D,GAAG,EAAE,CAAC,MAA0B,EAAE,EAAE,CAAC,IAAI;yBAC1C;qBACF;iBACF,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QAED,SAAS,kBAAkB,CAAC,IAA4B;YACtD,IAAI,UAAU,EAAE,CAAC;gBACf,OAAO;YACT,CAAC;YAED,wEAAwE;YACxE,IAAI,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,MAAM,CAAC,IAAI,KAAK,oBAAoB,IAAI,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;gBACjF,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC;gBAC9B,MAAM,QAAQ,GAAG,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;gBAE1C,+DAA+D;gBAC/D,+CAA+C;gBAC/C,IAAI,IAAI,CAAC,IAAI,KAAK,gBAAgB,EAAE,CAAC;oBACnC,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;oBAC3B,IAAI,MAAM,CAAC,IAAI,KAAK,kBAAkB,IAAI,MAAM,CAAC,QAAQ,CAAC,IAAI,KAAK,YAAY,EAAE,CAAC;wBAChF,MAAM,UAAU,GAAG,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;wBACtD,IAAI,CAAC,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,YAAY,EAAE,eAAe,EAAE,YAAY,CAAC,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC;4BACzG,OAAO,CAAC,+BAA+B;wBACzC,CAAC;oBACH,CAAC;oBACD,IAAI,MAAM,CAAC,IAAI,KAAK,YAAY,EAAE,CAAC;wBACjC,MAAM,UAAU,GAAG,MAAM,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;wBAC7C,IAAI,CAAC,UAAU,EAAE,cAAc,EAAE,WAAW,CAAC,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC;4BACnE,OAAO,CAAC,+BAA+B;wBACzC,CAAC;oBACH,CAAC;gBACH,CAAC;gBAED,6DAA6D;gBAC7D,MAAM,cAAc,GAAG,0BAA0B,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC;gBAEtF,IAAI,cAAc,EAAE,CAAC;oBACnB,uEAAuE;oBACvE,oEAAoE;oBACpE,IAAI,IAAI,CAAC,IAAI,KAAK,gBAAgB,EAAE,CAAC;wBACnC,+CAA+C;wBAC/C,iEAAiE;wBACjE,sCAAsC;wBACtC,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;wBAC3B,MAAM,gBAAgB,GACpB,CAAC,MAAM,CAAC,IAAI,KAAK,kBAAkB,IAAI,MAAM,CAAC,QAAQ,CAAC,IAAI,KAAK,YAAY;4BAC3E,CAAC,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,YAAY,EAAE,eAAe,EAAE,YAAY,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC;4BAC9H,CAAC,MAAM,CAAC,IAAI,KAAK,YAAY;gCAC5B,CAAC,UAAU,EAAE,cAAc,EAAE,WAAW,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC;wBAElF,IAAI,gBAAgB,EAAE,CAAC;4BACrB,OAAO,CAAC,2DAA2D;wBACrE,CAAC;wBAED,qEAAqE;wBACrE,MAAM,eAAe,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,GAAoC,EAAE,EAAE;4BACnF,IAAI,GAAG,CAAC,IAAI,KAAK,kBAAkB,IAAI,GAAG,CAAC,IAAI,KAAK,YAAY,EAAE,CAAC;gCACjE,OAAO,sBAAsB,CAAC,GAAG,EAAE,UAAU,EAAE,gBAAgB,CAAC,CAAC;4BACnE,CAAC;4BACD,OAAO,KAAK,CAAC;wBACf,CAAC,CAAC,CAAC;wBACH,IAAI,eAAe,EAAE,CAAC;4BACpB,OAAO,CAAC,qCAAqC;wBAC/C,CAAC;oBACH,CAAC;yBAAM,CAAC;wBACN,6EAA6E;wBAC7E,IAAI,sBAAsB,CAAC,IAAI,EAAE,UAAU,EAAE,gBAAgB,CAAC,EAAE,CAAC;4BAC/D,OAAO;wBACT,CAAC;oBACH,CAAC;oBAED,gDAAgD;oBAChD,IAAI,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,KAAK,eAAe,EAAE,CAAC;wBAC5C,MAAM,OAAO,GAAG,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;wBACnD,IAAI,oBAAoB,CAAC,OAAO,EAAE,cAAc,CAAC,EAAE,CAAC;4BAClD,OAAO;wBACT,CAAC;oBACH,CAAC;oBAED,OAAO,CAAC,MAAM,CAAC;wBACb,IAAI,EAAE,IAAI;wBACV,SAAS,EAAE,kBAAkB;wBAC7B,IAAI,EAAE;4BACJ,WAAW,EAAE,cAAc,CAAC,IAAI;4BAChC,iBAAiB,EAAE,oHAAoH;yBACxI;wBACD,OAAO,EAAE;4BACP;gCACE,SAAS,EAAE,QAAQ;gCACnB,6DAA6D;gCAC7D,GAAG,EAAE,CAAC,MAA0B,EAAE,EAAE,CAAC,IAAI;6BAC1C;4BACD;gCACE,SAAS,EAAE,QAAQ;gCACnB,6DAA6D;gCAC7D,GAAG,EAAE,CAAC,MAA0B,EAAE,EAAE,CAAC,IAAI;6BAC1C;yBACF;qBACF,CAAC,CAAC;gBACL,CAAC;YACH,CAAC;QACH,CAAC;QAED,OAAO;YACL,gBAAgB,EAAE,qBAAqB;YACvC,UAAU,EAAE,eAAe;YAC3B,aAAa,EAAE,kBAAkB;SAClC,CAAC;IACJ,CAAC;CACF,CAAC,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export interface Options {
|
|
2
|
+
/** Allow weak crypto in test files. Default: false */
|
|
3
|
+
allowInTests?: boolean;
|
|
4
|
+
/** Additional weak algorithms to detect. Default: [] */
|
|
5
|
+
additionalWeakAlgorithms?: string[];
|
|
6
|
+
/** Trusted crypto libraries. Default: ['crypto', 'crypto-js'] */
|
|
7
|
+
trustedLibraries?: string[];
|
|
8
|
+
/** Strategy for fixing weak crypto: 'upgrade', 'migrate', 'policy', 'auto' */
|
|
9
|
+
strategy?: 'upgrade' | 'migrate' | 'policy' | 'auto';
|
|
10
|
+
}
|
|
11
|
+
export declare const noWeakCrypto: ESLintUtils.RuleModule<MessageIds, Options, unknown, ESLintUtils.RuleListener>;
|