eslint-plugin-secure-coding 2.3.4 → 2.4.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.
Files changed (33) hide show
  1. package/CHANGELOG.md +51 -1
  2. package/README.md +3 -2
  3. package/package.json +2 -9
  4. package/src/index.d.ts +1 -1
  5. package/src/index.js +0 -49
  6. package/src/types/index.d.ts +4 -29
  7. package/src/types/index.js +3 -4
  8. package/src/rules/database-injection/index.d.ts +0 -13
  9. package/src/rules/database-injection/index.js +0 -406
  10. package/src/rules/no-credentials-in-storage-api/index.d.ts +0 -6
  11. package/src/rules/no-credentials-in-storage-api/index.js +0 -54
  12. package/src/rules/no-document-cookie/index.d.ts +0 -5
  13. package/src/rules/no-document-cookie/index.js +0 -89
  14. package/src/rules/no-insecure-cookie-settings/index.d.ts +0 -9
  15. package/src/rules/no-insecure-cookie-settings/index.js +0 -306
  16. package/src/rules/no-insecure-jwt/index.d.ts +0 -10
  17. package/src/rules/no-insecure-jwt/index.js +0 -380
  18. package/src/rules/no-insufficient-postmessage-validation/index.d.ts +0 -14
  19. package/src/rules/no-insufficient-postmessage-validation/index.js +0 -392
  20. package/src/rules/no-insufficient-random/index.d.ts +0 -9
  21. package/src/rules/no-insufficient-random/index.js +0 -208
  22. package/src/rules/no-postmessage-origin-wildcard/index.d.ts +0 -8
  23. package/src/rules/no-postmessage-origin-wildcard/index.js +0 -56
  24. package/src/rules/no-sql-injection/index.d.ts +0 -10
  25. package/src/rules/no-sql-injection/index.js +0 -335
  26. package/src/rules/no-timing-attack/index.d.ts +0 -10
  27. package/src/rules/no-timing-attack/index.js +0 -447
  28. package/src/rules/no-unencrypted-local-storage/index.d.ts +0 -8
  29. package/src/rules/no-unencrypted-local-storage/index.js +0 -61
  30. package/src/rules/no-unsanitized-html/index.d.ts +0 -9
  31. package/src/rules/no-unsanitized-html/index.js +0 -335
  32. package/src/rules/no-weak-crypto/index.d.ts +0 -11
  33. package/src/rules/no-weak-crypto/index.js +0 -351
@@ -1,351 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.noWeakCrypto = void 0;
4
- const eslint_devkit_1 = require("@interlace/eslint-devkit");
5
- const eslint_devkit_2 = require("@interlace/eslint-devkit");
6
- const WEAK_CRYPTO_PATTERNS = [
7
- {
8
- pattern: /\bmd5\b/i,
9
- name: 'MD5',
10
- category: 'hash',
11
- alternatives: ['SHA-256', 'SHA-512', 'SHA-3'],
12
- example: {
13
- bad: 'crypto.createHash("md5").update(data)',
14
- good: 'crypto.createHash("sha256").update(data)'
15
- },
16
- effort: '5 minutes'
17
- },
18
- {
19
- pattern: /\bsha1\b/i,
20
- name: 'SHA-1',
21
- category: 'hash',
22
- alternatives: ['SHA-256', 'SHA-512', 'SHA-3'],
23
- example: {
24
- bad: 'crypto.createHash("sha1").update(data)',
25
- good: 'crypto.createHash("sha256").update(data)'
26
- },
27
- effort: '5 minutes'
28
- },
29
- {
30
- pattern: /\bdes\b/i,
31
- name: 'DES',
32
- category: 'encryption',
33
- alternatives: ['AES-256', 'ChaCha20-Poly1305'],
34
- example: {
35
- bad: 'crypto.createCipher("des", key)',
36
- good: 'crypto.createCipheriv("aes-256-gcm", key, iv)'
37
- },
38
- effort: '15 minutes'
39
- },
40
- {
41
- pattern: /\b3des\b|\btripledes\b/i,
42
- name: '3DES',
43
- category: 'encryption',
44
- alternatives: ['AES-256', 'ChaCha20-Poly1305'],
45
- example: {
46
- bad: 'crypto.createCipher("des-ede3", key)',
47
- good: 'crypto.createCipheriv("aes-256-gcm", key, iv)'
48
- },
49
- effort: '15 minutes'
50
- },
51
- {
52
- pattern: /\brc4\b/i,
53
- name: 'RC4',
54
- category: 'encryption',
55
- alternatives: ['AES-256', 'ChaCha20-Poly1305'],
56
- example: {
57
- bad: 'crypto.createCipher("rc4", key)',
58
- good: 'crypto.createCipheriv("aes-256-gcm", key, iv)'
59
- },
60
- effort: '15 minutes'
61
- }
62
- ];
63
- /**
64
- * Check if a string contains a weak crypto algorithm
65
- */
66
- function containsWeakCrypto(value, additionalPatterns) {
67
- // Check standard patterns
68
- for (const pattern of WEAK_CRYPTO_PATTERNS) {
69
- if (pattern.pattern.test(value)) {
70
- return pattern;
71
- }
72
- }
73
- // Check additional patterns
74
- for (const additionalPattern of additionalPatterns) {
75
- const regex = new RegExp(`\\b${additionalPattern}\\b`, 'i');
76
- if (regex.test(value)) {
77
- return {
78
- pattern: regex,
79
- name: additionalPattern,
80
- category: 'hash',
81
- alternatives: ['SHA-256', 'SHA-512'],
82
- example: {
83
- bad: `crypto.createHash("${additionalPattern}").update(data)`,
84
- good: 'crypto.createHash("sha256").update(data)'
85
- },
86
- effort: '10 minutes'
87
- };
88
- }
89
- }
90
- return null;
91
- }
92
- /**
93
- * Generate refactoring suggestions based on the weak crypto pattern
94
- */
95
- function generateRefactoringSteps(pattern, context) {
96
- const suggestions = [];
97
- if (pattern.category === 'hash') {
98
- suggestions.push({
99
- messageId: 'useSha256',
100
- fix: `Use SHA-256: crypto.createHash("sha256").update(${context})`
101
- });
102
- }
103
- else if (pattern.category === 'encryption') {
104
- suggestions.push({
105
- messageId: 'useAes256',
106
- fix: `Use AES-256-GCM: crypto.createCipheriv("aes-256-gcm", key, iv)`
107
- });
108
- }
109
- if (pattern.category === 'password') {
110
- suggestions.push({
111
- messageId: 'useBcrypt',
112
- fix: 'Use bcrypt: bcrypt.hash(password, 10)'
113
- });
114
- suggestions.push({
115
- messageId: 'useScrypt',
116
- fix: 'Use scrypt: crypto.scrypt(password, salt, 64)'
117
- });
118
- suggestions.push({
119
- messageId: 'useArgon2',
120
- fix: 'Use Argon2: argon2.hash(password)'
121
- });
122
- }
123
- return suggestions;
124
- }
125
- exports.noWeakCrypto = (0, eslint_devkit_2.createRule)({
126
- name: 'no-weak-crypto',
127
- meta: {
128
- type: 'problem',
129
- deprecated: true,
130
- replacedBy: ['@see eslint-plugin-crypto for 24 crypto security rules'],
131
- docs: {
132
- description: 'Detects use of weak cryptography algorithms (MD5, SHA1, DES)',
133
- },
134
- hasSuggestions: true,
135
- messages: {
136
- weakCrypto: (0, eslint_devkit_1.formatLLMMessage)({
137
- icon: eslint_devkit_1.MessageIcons.SECURITY,
138
- issueName: 'Weak cryptography',
139
- cwe: 'CWE-327',
140
- description: 'Use of weak cryptography algorithm: {{algorithm}}',
141
- severity: 'CRITICAL',
142
- fix: '{{safeAlternative}}',
143
- documentationLink: 'https://owasp.org/www-community/vulnerabilities/Weak_Cryptography',
144
- }),
145
- useSha256: (0, eslint_devkit_1.formatLLMMessage)({
146
- icon: eslint_devkit_1.MessageIcons.INFO,
147
- issueName: 'Use SHA-256',
148
- description: 'Use SHA-256 for hashing',
149
- severity: 'LOW',
150
- fix: 'crypto.createHash("sha256").update(data)',
151
- documentationLink: 'https://nodejs.org/api/crypto.html#cryptocreatehashmethod-options',
152
- }),
153
- useBcrypt: (0, eslint_devkit_1.formatLLMMessage)({
154
- icon: eslint_devkit_1.MessageIcons.INFO,
155
- issueName: 'Use bcrypt',
156
- description: 'Use bcrypt for password hashing',
157
- severity: 'LOW',
158
- fix: 'bcrypt.hash(password, 10)',
159
- documentationLink: 'https://github.com/kelektiv/node.bcrypt.js',
160
- }),
161
- useScrypt: (0, eslint_devkit_1.formatLLMMessage)({
162
- icon: eslint_devkit_1.MessageIcons.INFO,
163
- issueName: 'Use scrypt',
164
- description: 'Use scrypt for password hashing',
165
- severity: 'LOW',
166
- fix: 'crypto.scrypt(password, salt, 64)',
167
- documentationLink: 'https://nodejs.org/api/crypto.html#cryptoscryptpassword-salt-keylen-options-callback',
168
- }),
169
- useArgon2: (0, eslint_devkit_1.formatLLMMessage)({
170
- icon: eslint_devkit_1.MessageIcons.INFO,
171
- issueName: 'Use Argon2',
172
- description: 'Use Argon2 for password hashing',
173
- severity: 'LOW',
174
- fix: 'argon2.hash(password)',
175
- documentationLink: 'https://github.com/ranisalt/node-argon2',
176
- }),
177
- useAes256: (0, eslint_devkit_1.formatLLMMessage)({
178
- icon: eslint_devkit_1.MessageIcons.INFO,
179
- issueName: 'Use AES-256-GCM',
180
- description: 'Use AES-256-GCM for encryption',
181
- severity: 'LOW',
182
- fix: 'Use crypto.createCipheriv("aes-256-gcm", key, iv)',
183
- documentationLink: 'https://nodejs.org/api/crypto.html#cryptocreatecipherivalgorithm-key-iv-options',
184
- }),
185
- strategyAuto: (0, eslint_devkit_1.formatLLMMessage)({
186
- icon: eslint_devkit_1.MessageIcons.INFO,
187
- issueName: 'Auto-fix Strategy',
188
- description: 'Automatically suggest the best replacement',
189
- severity: 'LOW',
190
- fix: 'Apply automatic fix suggestion',
191
- documentationLink: 'https://owasp.org/www-community/vulnerabilities/Weak_Cryptography',
192
- }),
193
- strategyUpgrade: (0, eslint_devkit_1.formatLLMMessage)({
194
- icon: eslint_devkit_1.MessageIcons.INFO,
195
- issueName: 'Upgrade Strategy',
196
- description: 'Upgrade to a stronger algorithm',
197
- severity: 'LOW',
198
- fix: 'Replace weak algorithm with stronger alternative',
199
- documentationLink: 'https://owasp.org/www-community/vulnerabilities/Weak_Cryptography',
200
- }),
201
- strategyMigrate: (0, eslint_devkit_1.formatLLMMessage)({
202
- icon: eslint_devkit_1.MessageIcons.INFO,
203
- issueName: 'Migration Strategy',
204
- description: 'Plan migration to stronger cryptography',
205
- severity: 'LOW',
206
- fix: 'Create migration plan for cryptographic upgrade',
207
- documentationLink: 'https://owasp.org/www-community/vulnerabilities/Weak_Cryptography',
208
- }),
209
- strategyPolicy: (0, eslint_devkit_1.formatLLMMessage)({
210
- icon: eslint_devkit_1.MessageIcons.INFO,
211
- issueName: 'Policy Strategy',
212
- description: 'Apply organizational security policy',
213
- severity: 'LOW',
214
- fix: 'crypto.createCipheriv("aes-256-gcm", key, iv)',
215
- documentationLink: 'https://nodejs.org/api/crypto.html#cryptocreatecipherivalgorithm-key-iv-options',
216
- }),
217
- },
218
- schema: [
219
- {
220
- type: 'object',
221
- properties: {
222
- allowInTests: {
223
- type: 'boolean',
224
- default: false,
225
- description: 'Allow weak crypto in test files',
226
- },
227
- additionalWeakAlgorithms: {
228
- type: 'array',
229
- items: { type: 'string' },
230
- default: [],
231
- description: 'Additional weak algorithms to detect',
232
- },
233
- trustedLibraries: {
234
- type: 'array',
235
- items: { type: 'string' },
236
- default: ['crypto', 'crypto-js'],
237
- description: 'Trusted crypto libraries',
238
- },
239
- },
240
- additionalProperties: false,
241
- },
242
- ],
243
- },
244
- defaultOptions: [
245
- {
246
- allowInTests: false,
247
- additionalWeakAlgorithms: [],
248
- trustedLibraries: ['crypto', 'crypto-js'],
249
- },
250
- ],
251
- create(context, [options = {}]) {
252
- const { allowInTests = false, additionalWeakAlgorithms = [], trustedLibraries = ['crypto', 'crypto-js'], } = options;
253
- const filename = context.getFilename();
254
- const isTestFile = allowInTests && /\.(test|spec)\.(ts|tsx|js|jsx)$/.test(filename);
255
- /**
256
- * Check if a call expression uses weak crypto
257
- */
258
- function checkCallExpression(node) {
259
- if (isTestFile) {
260
- return;
261
- }
262
- // Check for crypto.createHash, crypto.createCipher, etc.
263
- if (node.callee.type === 'MemberExpression') {
264
- // Check if it's a crypto method call (e.g., crypto.createHash, crypto.createCipher)
265
- if (node.callee.object.type === 'Identifier' &&
266
- node.callee.property.type === 'Identifier') {
267
- const objectName = node.callee.object.name;
268
- const methodName = node.callee.property.name;
269
- // Check if it's a crypto method from a trusted library
270
- const isCryptoMethod = (methodName === 'createHash' ||
271
- methodName === 'createCipher' ||
272
- methodName === 'createCipheriv') &&
273
- (trustedLibraries.includes(objectName) || objectName === 'crypto');
274
- if (isCryptoMethod) {
275
- // Check arguments for weak algorithms
276
- for (const arg of node.arguments) {
277
- if (arg.type === 'Literal' && typeof arg.value === 'string') {
278
- const weakPattern = containsWeakCrypto(arg.value, additionalWeakAlgorithms);
279
- if (weakPattern) {
280
- const safeAlternative = weakPattern.alternatives[0];
281
- const refactoringSteps = generateRefactoringSteps(weakPattern, 'data');
282
- context.report({
283
- node: arg,
284
- messageId: 'weakCrypto',
285
- data: {
286
- algorithm: weakPattern.name,
287
- safeAlternative: `Use ${safeAlternative}: ${weakPattern.example.good}`,
288
- },
289
- suggest: refactoringSteps.map(step => ({
290
- messageId: step.messageId,
291
- fix: (fixer) => {
292
- // Replace the weak algorithm with a safe one
293
- if (weakPattern.category === 'hash') {
294
- return fixer.replaceText(arg, `"sha256"`);
295
- }
296
- else if (weakPattern.category === 'encryption') {
297
- return fixer.replaceText(arg, `"aes-256-gcm"`);
298
- }
299
- return null;
300
- },
301
- })),
302
- });
303
- }
304
- }
305
- }
306
- }
307
- }
308
- }
309
- // Check for standalone crypto function calls (e.g., createHash, createCipher)
310
- if (node.callee.type === 'Identifier') {
311
- const calleeName = node.callee.name;
312
- // Check for common crypto library patterns
313
- if (calleeName === 'createHash' || calleeName === 'createCipher' || calleeName === 'createCipheriv') {
314
- for (const arg of node.arguments) {
315
- if (arg.type === 'Literal' && typeof arg.value === 'string') {
316
- const weakPattern = containsWeakCrypto(arg.value, additionalWeakAlgorithms);
317
- if (weakPattern) {
318
- const safeAlternative = weakPattern.alternatives[0];
319
- context.report({
320
- node: arg,
321
- messageId: 'weakCrypto',
322
- data: {
323
- algorithm: weakPattern.name,
324
- safeAlternative: `Use ${safeAlternative}: ${weakPattern.example.good}`,
325
- },
326
- suggest: [
327
- {
328
- messageId: weakPattern.category === 'hash' ? 'useSha256' : 'useAes256',
329
- fix: (fixer) => {
330
- if (weakPattern.category === 'hash') {
331
- return fixer.replaceText(arg, `"sha256"`);
332
- }
333
- else if (weakPattern.category === 'encryption') {
334
- return fixer.replaceText(arg, `"aes-256-gcm"`);
335
- }
336
- return null;
337
- },
338
- },
339
- ],
340
- });
341
- }
342
- }
343
- }
344
- }
345
- }
346
- }
347
- return {
348
- CallExpression: checkCallExpression,
349
- };
350
- },
351
- });