eslint-plugin-node-security 4.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.
Files changed (102) hide show
  1. package/CHANGELOG.md +83 -0
  2. package/README.md +50 -0
  3. package/package.json +79 -0
  4. package/src/index.d.ts +10 -0
  5. package/src/index.js +118 -0
  6. package/src/index.js.map +1 -0
  7. package/src/rules/detect-child-process/index.d.ts +30 -0
  8. package/src/rules/detect-child-process/index.js +535 -0
  9. package/src/rules/detect-child-process/index.js.map +1 -0
  10. package/src/rules/detect-eval-with-expression/index.d.ts +28 -0
  11. package/src/rules/detect-eval-with-expression/index.js +398 -0
  12. package/src/rules/detect-eval-with-expression/index.js.map +1 -0
  13. package/src/rules/detect-non-literal-fs-filename/index.d.ts +26 -0
  14. package/src/rules/detect-non-literal-fs-filename/index.js +460 -0
  15. package/src/rules/detect-non-literal-fs-filename/index.js.map +1 -0
  16. package/src/rules/detect-suspicious-dependencies/index.d.ts +12 -0
  17. package/src/rules/detect-suspicious-dependencies/index.js +77 -0
  18. package/src/rules/detect-suspicious-dependencies/index.js.map +1 -0
  19. package/src/rules/lock-file/index.d.ts +13 -0
  20. package/src/rules/lock-file/index.js +94 -0
  21. package/src/rules/lock-file/index.js.map +1 -0
  22. package/src/rules/no-arbitrary-file-access/index.d.ts +12 -0
  23. package/src/rules/no-arbitrary-file-access/index.js +201 -0
  24. package/src/rules/no-arbitrary-file-access/index.js.map +1 -0
  25. package/src/rules/no-buffer-overread/index.d.ts +39 -0
  26. package/src/rules/no-buffer-overread/index.js +612 -0
  27. package/src/rules/no-buffer-overread/index.js.map +1 -0
  28. package/src/rules/no-cryptojs/index.d.ts +24 -0
  29. package/src/rules/no-cryptojs/index.js +104 -0
  30. package/src/rules/no-cryptojs/index.js.map +1 -0
  31. package/src/rules/no-cryptojs-weak-random/index.d.ts +24 -0
  32. package/src/rules/no-cryptojs-weak-random/index.js +112 -0
  33. package/src/rules/no-cryptojs-weak-random/index.js.map +1 -0
  34. package/src/rules/no-data-in-temp-storage/index.d.ts +14 -0
  35. package/src/rules/no-data-in-temp-storage/index.js +99 -0
  36. package/src/rules/no-data-in-temp-storage/index.js.map +1 -0
  37. package/src/rules/no-deprecated-cipher-method/index.d.ts +23 -0
  38. package/src/rules/no-deprecated-cipher-method/index.js +118 -0
  39. package/src/rules/no-deprecated-cipher-method/index.js.map +1 -0
  40. package/src/rules/no-dynamic-dependency-loading/index.d.ts +12 -0
  41. package/src/rules/no-dynamic-dependency-loading/index.js +55 -0
  42. package/src/rules/no-dynamic-dependency-loading/index.js.map +1 -0
  43. package/src/rules/no-dynamic-require/index.d.ts +21 -0
  44. package/src/rules/no-dynamic-require/index.js +122 -0
  45. package/src/rules/no-dynamic-require/index.js.map +1 -0
  46. package/src/rules/no-ecb-mode/index.d.ts +23 -0
  47. package/src/rules/no-ecb-mode/index.js +113 -0
  48. package/src/rules/no-ecb-mode/index.js.map +1 -0
  49. package/src/rules/no-insecure-key-derivation/index.d.ts +24 -0
  50. package/src/rules/no-insecure-key-derivation/index.js +116 -0
  51. package/src/rules/no-insecure-key-derivation/index.js.map +1 -0
  52. package/src/rules/no-insecure-rsa-padding/index.d.ts +24 -0
  53. package/src/rules/no-insecure-rsa-padding/index.js +110 -0
  54. package/src/rules/no-insecure-rsa-padding/index.js.map +1 -0
  55. package/src/rules/no-pii-in-logs/index.d.ts +12 -0
  56. package/src/rules/no-pii-in-logs/index.js +74 -0
  57. package/src/rules/no-pii-in-logs/index.js.map +1 -0
  58. package/src/rules/no-self-signed-certs/index.d.ts +23 -0
  59. package/src/rules/no-self-signed-certs/index.js +116 -0
  60. package/src/rules/no-self-signed-certs/index.js.map +1 -0
  61. package/src/rules/no-sha1-hash/index.d.ts +24 -0
  62. package/src/rules/no-sha1-hash/index.js +128 -0
  63. package/src/rules/no-sha1-hash/index.js.map +1 -0
  64. package/src/rules/no-static-iv/index.d.ts +23 -0
  65. package/src/rules/no-static-iv/index.js +147 -0
  66. package/src/rules/no-static-iv/index.js.map +1 -0
  67. package/src/rules/no-timing-unsafe-compare/index.d.ts +23 -0
  68. package/src/rules/no-timing-unsafe-compare/index.js +114 -0
  69. package/src/rules/no-timing-unsafe-compare/index.js.map +1 -0
  70. package/src/rules/no-toctou-vulnerability/index.d.ts +26 -0
  71. package/src/rules/no-toctou-vulnerability/index.js +214 -0
  72. package/src/rules/no-toctou-vulnerability/index.js.map +1 -0
  73. package/src/rules/no-unsafe-dynamic-require/index.d.ts +19 -0
  74. package/src/rules/no-unsafe-dynamic-require/index.js +112 -0
  75. package/src/rules/no-unsafe-dynamic-require/index.js.map +1 -0
  76. package/src/rules/no-weak-cipher-algorithm/index.d.ts +25 -0
  77. package/src/rules/no-weak-cipher-algorithm/index.js +190 -0
  78. package/src/rules/no-weak-cipher-algorithm/index.js.map +1 -0
  79. package/src/rules/no-weak-hash-algorithm/index.d.ts +25 -0
  80. package/src/rules/no-weak-hash-algorithm/index.js +218 -0
  81. package/src/rules/no-weak-hash-algorithm/index.js.map +1 -0
  82. package/src/rules/no-zip-slip/index.d.ts +35 -0
  83. package/src/rules/no-zip-slip/index.js +451 -0
  84. package/src/rules/no-zip-slip/index.js.map +1 -0
  85. package/src/rules/prefer-native-crypto/index.d.ts +23 -0
  86. package/src/rules/prefer-native-crypto/index.js +124 -0
  87. package/src/rules/prefer-native-crypto/index.js.map +1 -0
  88. package/src/rules/require-dependency-integrity/index.d.ts +12 -0
  89. package/src/rules/require-dependency-integrity/index.js +70 -0
  90. package/src/rules/require-dependency-integrity/index.js.map +1 -0
  91. package/src/rules/require-secure-credential-storage/index.d.ts +12 -0
  92. package/src/rules/require-secure-credential-storage/index.js +54 -0
  93. package/src/rules/require-secure-credential-storage/index.js.map +1 -0
  94. package/src/rules/require-secure-deletion/index.d.ts +12 -0
  95. package/src/rules/require-secure-deletion/index.js +46 -0
  96. package/src/rules/require-secure-deletion/index.js.map +1 -0
  97. package/src/rules/require-storage-encryption/index.d.ts +12 -0
  98. package/src/rules/require-storage-encryption/index.js +54 -0
  99. package/src/rules/require-storage-encryption/index.js.map +1 -0
  100. package/src/types/index.d.ts +24 -0
  101. package/src/types/index.js +8 -0
  102. package/src/types/index.js.map +1 -0
@@ -0,0 +1,218 @@
1
+ "use strict";
2
+ /**
3
+ * Copyright (c) 2025 Ofri Peretz
4
+ * Licensed under the MIT License. Use of this source code is governed by the
5
+ * MIT license that can be found in the LICENSE file.
6
+ */
7
+ Object.defineProperty(exports, "__esModule", { value: true });
8
+ exports.noWeakHashAlgorithm = void 0;
9
+ const eslint_devkit_1 = require("@interlace/eslint-devkit");
10
+ const WEAK_HASH_PATTERNS = [
11
+ {
12
+ pattern: /\bmd5\b/i,
13
+ name: 'MD5',
14
+ alternatives: ['SHA-256', 'SHA-512', 'SHA-3'],
15
+ replacement: 'sha256',
16
+ },
17
+ {
18
+ pattern: /\bmd4\b/i,
19
+ name: 'MD4',
20
+ alternatives: ['SHA-256', 'SHA-512', 'SHA-3'],
21
+ replacement: 'sha256',
22
+ },
23
+ {
24
+ pattern: /\bsha1\b/i,
25
+ name: 'SHA-1',
26
+ alternatives: ['SHA-256', 'SHA-512', 'SHA-3'],
27
+ replacement: 'sha256',
28
+ },
29
+ {
30
+ pattern: /\bripemd\b/i,
31
+ name: 'RIPEMD',
32
+ alternatives: ['SHA-256', 'SHA-512'],
33
+ replacement: 'sha256',
34
+ },
35
+ ];
36
+ /**
37
+ * Check if a string contains a weak hash algorithm
38
+ */
39
+ function findWeakHash(value, additionalPatterns) {
40
+ // Check standard patterns
41
+ for (const pattern of WEAK_HASH_PATTERNS) {
42
+ if (pattern.pattern.test(value)) {
43
+ return pattern;
44
+ }
45
+ }
46
+ // Check additional patterns
47
+ for (const additionalPattern of additionalPatterns) {
48
+ const regex = new RegExp(`\\b${additionalPattern}\\b`, 'i');
49
+ if (regex.test(value)) {
50
+ return {
51
+ pattern: regex,
52
+ name: additionalPattern.toUpperCase(),
53
+ alternatives: ['SHA-256', 'SHA-512'],
54
+ replacement: 'sha256',
55
+ };
56
+ }
57
+ }
58
+ return null;
59
+ }
60
+ exports.noWeakHashAlgorithm = (0, eslint_devkit_1.createRule)({
61
+ name: 'no-weak-hash-algorithm',
62
+ meta: {
63
+ type: 'problem',
64
+ docs: {
65
+ description: 'Disallow weak hash algorithms (MD5, SHA1, MD4)',
66
+ },
67
+ hasSuggestions: true,
68
+ messages: {
69
+ weakHashAlgorithm: (0, eslint_devkit_1.formatLLMMessage)({
70
+ icon: eslint_devkit_1.MessageIcons.SECURITY,
71
+ issueName: 'Weak hash algorithm',
72
+ cwe: 'CWE-327',
73
+ description: 'Use of weak hash algorithm: {{algorithm}}. {{algorithm}} is cryptographically broken and unsuitable for security purposes.',
74
+ severity: 'CRITICAL',
75
+ fix: 'Replace with {{replacement}}: crypto.createHash("{{replacement}}").update(data)',
76
+ documentationLink: 'https://owasp.org/www-community/vulnerabilities/Weak_Cryptography',
77
+ }),
78
+ useSha256: (0, eslint_devkit_1.formatLLMMessage)({
79
+ icon: eslint_devkit_1.MessageIcons.INFO,
80
+ issueName: 'Use SHA-256',
81
+ description: 'Replace with SHA-256 for secure hashing',
82
+ severity: 'LOW',
83
+ fix: 'crypto.createHash("sha256").update(data)',
84
+ documentationLink: 'https://nodejs.org/api/crypto.html#cryptocreatehashmethod-options',
85
+ }),
86
+ useSha512: (0, eslint_devkit_1.formatLLMMessage)({
87
+ icon: eslint_devkit_1.MessageIcons.INFO,
88
+ issueName: 'Use SHA-512',
89
+ description: 'Replace with SHA-512 for stronger hashing',
90
+ severity: 'LOW',
91
+ fix: 'crypto.createHash("sha512").update(data)',
92
+ documentationLink: 'https://nodejs.org/api/crypto.html#cryptocreatehashmethod-options',
93
+ }),
94
+ useSha3: (0, eslint_devkit_1.formatLLMMessage)({
95
+ icon: eslint_devkit_1.MessageIcons.INFO,
96
+ issueName: 'Use SHA-3',
97
+ description: 'Replace with SHA-3 for latest standard',
98
+ severity: 'LOW',
99
+ fix: 'crypto.createHash("sha3-256").update(data)',
100
+ documentationLink: 'https://nodejs.org/api/crypto.html#cryptocreatehashmethod-options',
101
+ }),
102
+ },
103
+ schema: [
104
+ {
105
+ type: 'object',
106
+ properties: {
107
+ additionalWeakAlgorithms: {
108
+ type: 'array',
109
+ items: { type: 'string' },
110
+ default: [],
111
+ description: 'Additional weak algorithms to detect',
112
+ },
113
+ allowInTests: {
114
+ type: 'boolean',
115
+ default: false,
116
+ description: 'Allow weak hashes in test files',
117
+ },
118
+ },
119
+ additionalProperties: false,
120
+ },
121
+ ],
122
+ },
123
+ defaultOptions: [
124
+ {
125
+ additionalWeakAlgorithms: [],
126
+ allowInTests: false,
127
+ },
128
+ ],
129
+ create(context, [options = {}]) {
130
+ const { additionalWeakAlgorithms = [], allowInTests = false, } = options;
131
+ const filename = context.filename;
132
+ const isTestFile = allowInTests && /\.(test|spec)\.(ts|tsx|js|jsx)$/.test(filename);
133
+ /**
134
+ * Check if a call expression uses a weak hash
135
+ */
136
+ function checkCallExpression(node) {
137
+ if (isTestFile)
138
+ return;
139
+ // Check for crypto.createHash() pattern
140
+ if (node.callee.type === eslint_devkit_1.AST_NODE_TYPES.MemberExpression &&
141
+ node.callee.property.type === eslint_devkit_1.AST_NODE_TYPES.Identifier &&
142
+ node.callee.property.name === 'createHash') {
143
+ checkHashArgument(node);
144
+ }
145
+ // Check for standalone createHash() pattern
146
+ if (node.callee.type === eslint_devkit_1.AST_NODE_TYPES.Identifier &&
147
+ node.callee.name === 'createHash') {
148
+ checkHashArgument(node);
149
+ }
150
+ // Check for crypto-hash package: sha1(), md5()
151
+ if (node.callee.type === eslint_devkit_1.AST_NODE_TYPES.Identifier) {
152
+ const funcName = node.callee.name.toLowerCase();
153
+ if (funcName === 'sha1' || funcName === 'md5' || funcName === 'md4') {
154
+ const weakPattern = findWeakHash(funcName, additionalWeakAlgorithms);
155
+ if (weakPattern) {
156
+ context.report({
157
+ node,
158
+ messageId: 'weakHashAlgorithm',
159
+ data: {
160
+ algorithm: weakPattern.name,
161
+ replacement: weakPattern.replacement,
162
+ },
163
+ suggest: [
164
+ {
165
+ messageId: 'useSha256',
166
+ fix: (fixer) => {
167
+ if (node.callee.type === eslint_devkit_1.AST_NODE_TYPES.Identifier) {
168
+ return fixer.replaceText(node.callee, 'sha256');
169
+ }
170
+ return null;
171
+ },
172
+ },
173
+ ],
174
+ });
175
+ }
176
+ }
177
+ }
178
+ }
179
+ /**
180
+ * Check the algorithm argument passed to createHash
181
+ */
182
+ function checkHashArgument(node) {
183
+ for (const arg of node.arguments) {
184
+ if (arg.type === eslint_devkit_1.AST_NODE_TYPES.Literal && typeof arg.value === 'string') {
185
+ const weakPattern = findWeakHash(arg.value, additionalWeakAlgorithms);
186
+ if (weakPattern) {
187
+ context.report({
188
+ node: arg,
189
+ messageId: 'weakHashAlgorithm',
190
+ data: {
191
+ algorithm: weakPattern.name,
192
+ replacement: weakPattern.replacement,
193
+ },
194
+ suggest: [
195
+ {
196
+ messageId: 'useSha256',
197
+ fix: (fixer) => fixer.replaceText(arg, `"sha256"`),
198
+ },
199
+ {
200
+ messageId: 'useSha512',
201
+ fix: (fixer) => fixer.replaceText(arg, `"sha512"`),
202
+ },
203
+ {
204
+ messageId: 'useSha3',
205
+ fix: (fixer) => fixer.replaceText(arg, `"sha3-256"`),
206
+ },
207
+ ],
208
+ });
209
+ }
210
+ }
211
+ }
212
+ }
213
+ return {
214
+ CallExpression: checkCallExpression,
215
+ };
216
+ },
217
+ });
218
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../../packages/eslint-plugin-node-security/src/rules/no-weak-hash-algorithm/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Copyright (c) 2025 Ofri Peretz
3
+ * Licensed under the MIT License. Use of this source code is governed by the
4
+ * MIT license that can be found in the LICENSE file.
5
+ */
6
+ /**
7
+ * ESLint Rule: no-zip-slip
8
+ * Detects zip slip/archive extraction vulnerabilities (CWE-22)
9
+ *
10
+ * Zip slip vulnerabilities occur when extracting archives without properly
11
+ * validating file paths, allowing attackers to write files outside the
12
+ * intended extraction directory using path traversal sequences like "../".
13
+ *
14
+ * False Positive Reduction:
15
+ * This rule uses security utilities to reduce false positives by detecting:
16
+ * - Safe archive extraction patterns
17
+ * - Path validation functions
18
+ * - JSDoc annotations (@safe, @validated)
19
+ * - Trusted extraction libraries
20
+ */
21
+ import type { TSESLint } from '@interlace/eslint-devkit';
22
+ type MessageIds = 'zipSlipVulnerability' | 'unsafeArchiveExtraction' | 'pathTraversalInArchive' | 'unvalidatedArchivePath' | 'dangerousArchiveDestination' | 'useSafeArchiveExtraction' | 'validateArchivePaths' | 'sanitizeArchiveNames' | 'strategyPathValidation' | 'strategySafeLibraries' | 'strategySandboxing';
23
+ export interface Options {
24
+ /** Archive extraction functions to check */
25
+ archiveFunctions?: string[];
26
+ /** Functions that safely validate archive paths */
27
+ pathValidationFunctions?: string[];
28
+ /** Safe archive extraction libraries */
29
+ safeLibraries?: string[];
30
+ }
31
+ type RuleOptions = [Options?];
32
+ export declare const noZipSlip: TSESLint.RuleModule<MessageIds, RuleOptions, unknown, TSESLint.RuleListener> & {
33
+ name: string;
34
+ };
35
+ export {};