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.
Files changed (155) hide show
  1. package/AGENTS.md +196 -0
  2. package/CHANGELOG.md +105 -0
  3. package/LICENSE +23 -0
  4. package/README.md +377 -0
  5. package/package.json +80 -0
  6. package/src/index.d.ts +32 -0
  7. package/src/index.js +345 -0
  8. package/src/index.js.map +1 -0
  9. package/src/rules/security/database-injection.d.ts +13 -0
  10. package/src/rules/security/database-injection.js +407 -0
  11. package/src/rules/security/database-injection.js.map +1 -0
  12. package/src/rules/security/detect-child-process.d.ts +11 -0
  13. package/src/rules/security/detect-child-process.js +460 -0
  14. package/src/rules/security/detect-child-process.js.map +1 -0
  15. package/src/rules/security/detect-eval-with-expression.d.ts +9 -0
  16. package/src/rules/security/detect-eval-with-expression.js +393 -0
  17. package/src/rules/security/detect-eval-with-expression.js.map +1 -0
  18. package/src/rules/security/detect-non-literal-fs-filename.d.ts +7 -0
  19. package/src/rules/security/detect-non-literal-fs-filename.js +322 -0
  20. package/src/rules/security/detect-non-literal-fs-filename.js.map +1 -0
  21. package/src/rules/security/detect-non-literal-regexp.d.ts +9 -0
  22. package/src/rules/security/detect-non-literal-regexp.js +387 -0
  23. package/src/rules/security/detect-non-literal-regexp.js.map +1 -0
  24. package/src/rules/security/detect-object-injection.d.ts +11 -0
  25. package/src/rules/security/detect-object-injection.js +411 -0
  26. package/src/rules/security/detect-object-injection.js.map +1 -0
  27. package/src/rules/security/no-buffer-overread.d.ts +14 -0
  28. package/src/rules/security/no-buffer-overread.js +519 -0
  29. package/src/rules/security/no-buffer-overread.js.map +1 -0
  30. package/src/rules/security/no-clickjacking.d.ts +10 -0
  31. package/src/rules/security/no-clickjacking.js +381 -0
  32. package/src/rules/security/no-clickjacking.js.map +1 -0
  33. package/src/rules/security/no-directive-injection.d.ts +12 -0
  34. package/src/rules/security/no-directive-injection.js +446 -0
  35. package/src/rules/security/no-directive-injection.js.map +1 -0
  36. package/src/rules/security/no-document-cookie.d.ts +5 -0
  37. package/src/rules/security/no-document-cookie.js +90 -0
  38. package/src/rules/security/no-document-cookie.js.map +1 -0
  39. package/src/rules/security/no-electron-security-issues.d.ts +10 -0
  40. package/src/rules/security/no-electron-security-issues.js +421 -0
  41. package/src/rules/security/no-electron-security-issues.js.map +1 -0
  42. package/src/rules/security/no-exposed-sensitive-data.d.ts +11 -0
  43. package/src/rules/security/no-exposed-sensitive-data.js +341 -0
  44. package/src/rules/security/no-exposed-sensitive-data.js.map +1 -0
  45. package/src/rules/security/no-format-string-injection.d.ts +17 -0
  46. package/src/rules/security/no-format-string-injection.js +653 -0
  47. package/src/rules/security/no-format-string-injection.js.map +1 -0
  48. package/src/rules/security/no-graphql-injection.d.ts +12 -0
  49. package/src/rules/security/no-graphql-injection.js +410 -0
  50. package/src/rules/security/no-graphql-injection.js.map +1 -0
  51. package/src/rules/security/no-hardcoded-credentials.d.ts +26 -0
  52. package/src/rules/security/no-hardcoded-credentials.js +377 -0
  53. package/src/rules/security/no-hardcoded-credentials.js.map +1 -0
  54. package/src/rules/security/no-improper-sanitization.d.ts +12 -0
  55. package/src/rules/security/no-improper-sanitization.js +408 -0
  56. package/src/rules/security/no-improper-sanitization.js.map +1 -0
  57. package/src/rules/security/no-improper-type-validation.d.ts +10 -0
  58. package/src/rules/security/no-improper-type-validation.js +420 -0
  59. package/src/rules/security/no-improper-type-validation.js.map +1 -0
  60. package/src/rules/security/no-insecure-comparison.d.ts +7 -0
  61. package/src/rules/security/no-insecure-comparison.js +125 -0
  62. package/src/rules/security/no-insecure-comparison.js.map +1 -0
  63. package/src/rules/security/no-insecure-cookie-settings.d.ts +9 -0
  64. package/src/rules/security/no-insecure-cookie-settings.js +305 -0
  65. package/src/rules/security/no-insecure-cookie-settings.js.map +1 -0
  66. package/src/rules/security/no-insecure-jwt.d.ts +10 -0
  67. package/src/rules/security/no-insecure-jwt.js +338 -0
  68. package/src/rules/security/no-insecure-jwt.js.map +1 -0
  69. package/src/rules/security/no-insecure-redirects.d.ts +7 -0
  70. package/src/rules/security/no-insecure-redirects.js +215 -0
  71. package/src/rules/security/no-insecure-redirects.js.map +1 -0
  72. package/src/rules/security/no-insufficient-postmessage-validation.d.ts +14 -0
  73. package/src/rules/security/no-insufficient-postmessage-validation.js +390 -0
  74. package/src/rules/security/no-insufficient-postmessage-validation.js.map +1 -0
  75. package/src/rules/security/no-insufficient-random.d.ts +9 -0
  76. package/src/rules/security/no-insufficient-random.js +207 -0
  77. package/src/rules/security/no-insufficient-random.js.map +1 -0
  78. package/src/rules/security/no-ldap-injection.d.ts +10 -0
  79. package/src/rules/security/no-ldap-injection.js +449 -0
  80. package/src/rules/security/no-ldap-injection.js.map +1 -0
  81. package/src/rules/security/no-missing-authentication.d.ts +13 -0
  82. package/src/rules/security/no-missing-authentication.js +322 -0
  83. package/src/rules/security/no-missing-authentication.js.map +1 -0
  84. package/src/rules/security/no-missing-cors-check.d.ts +9 -0
  85. package/src/rules/security/no-missing-cors-check.js +449 -0
  86. package/src/rules/security/no-missing-cors-check.js.map +1 -0
  87. package/src/rules/security/no-missing-csrf-protection.d.ts +11 -0
  88. package/src/rules/security/no-missing-csrf-protection.js +183 -0
  89. package/src/rules/security/no-missing-csrf-protection.js.map +1 -0
  90. package/src/rules/security/no-missing-security-headers.d.ts +7 -0
  91. package/src/rules/security/no-missing-security-headers.js +217 -0
  92. package/src/rules/security/no-missing-security-headers.js.map +1 -0
  93. package/src/rules/security/no-privilege-escalation.d.ts +13 -0
  94. package/src/rules/security/no-privilege-escalation.js +321 -0
  95. package/src/rules/security/no-privilege-escalation.js.map +1 -0
  96. package/src/rules/security/no-redos-vulnerable-regex.d.ts +7 -0
  97. package/src/rules/security/no-redos-vulnerable-regex.js +307 -0
  98. package/src/rules/security/no-redos-vulnerable-regex.js.map +1 -0
  99. package/src/rules/security/no-sensitive-data-exposure.d.ts +11 -0
  100. package/src/rules/security/no-sensitive-data-exposure.js +251 -0
  101. package/src/rules/security/no-sensitive-data-exposure.js.map +1 -0
  102. package/src/rules/security/no-sql-injection.d.ts +10 -0
  103. package/src/rules/security/no-sql-injection.js +332 -0
  104. package/src/rules/security/no-sql-injection.js.map +1 -0
  105. package/src/rules/security/no-timing-attack.d.ts +10 -0
  106. package/src/rules/security/no-timing-attack.js +358 -0
  107. package/src/rules/security/no-timing-attack.js.map +1 -0
  108. package/src/rules/security/no-toctou-vulnerability.d.ts +7 -0
  109. package/src/rules/security/no-toctou-vulnerability.js +165 -0
  110. package/src/rules/security/no-toctou-vulnerability.js.map +1 -0
  111. package/src/rules/security/no-unchecked-loop-condition.d.ts +12 -0
  112. package/src/rules/security/no-unchecked-loop-condition.js +635 -0
  113. package/src/rules/security/no-unchecked-loop-condition.js.map +1 -0
  114. package/src/rules/security/no-unencrypted-transmission.d.ts +11 -0
  115. package/src/rules/security/no-unencrypted-transmission.js +237 -0
  116. package/src/rules/security/no-unencrypted-transmission.js.map +1 -0
  117. package/src/rules/security/no-unescaped-url-parameter.d.ts +9 -0
  118. package/src/rules/security/no-unescaped-url-parameter.js +266 -0
  119. package/src/rules/security/no-unescaped-url-parameter.js.map +1 -0
  120. package/src/rules/security/no-unlimited-resource-allocation.d.ts +12 -0
  121. package/src/rules/security/no-unlimited-resource-allocation.js +659 -0
  122. package/src/rules/security/no-unlimited-resource-allocation.js.map +1 -0
  123. package/src/rules/security/no-unsafe-deserialization.d.ts +10 -0
  124. package/src/rules/security/no-unsafe-deserialization.js +501 -0
  125. package/src/rules/security/no-unsafe-deserialization.js.map +1 -0
  126. package/src/rules/security/no-unsafe-dynamic-require.d.ts +5 -0
  127. package/src/rules/security/no-unsafe-dynamic-require.js +107 -0
  128. package/src/rules/security/no-unsafe-dynamic-require.js.map +1 -0
  129. package/src/rules/security/no-unsafe-regex-construction.d.ts +9 -0
  130. package/src/rules/security/no-unsafe-regex-construction.js +292 -0
  131. package/src/rules/security/no-unsafe-regex-construction.js.map +1 -0
  132. package/src/rules/security/no-unsanitized-html.d.ts +9 -0
  133. package/src/rules/security/no-unsanitized-html.js +347 -0
  134. package/src/rules/security/no-unsanitized-html.js.map +1 -0
  135. package/src/rules/security/no-unvalidated-user-input.d.ts +9 -0
  136. package/src/rules/security/no-unvalidated-user-input.js +418 -0
  137. package/src/rules/security/no-unvalidated-user-input.js.map +1 -0
  138. package/src/rules/security/no-weak-crypto.d.ts +11 -0
  139. package/src/rules/security/no-weak-crypto.js +350 -0
  140. package/src/rules/security/no-weak-crypto.js.map +1 -0
  141. package/src/rules/security/no-weak-password-recovery.d.ts +12 -0
  142. package/src/rules/security/no-weak-password-recovery.js +401 -0
  143. package/src/rules/security/no-weak-password-recovery.js.map +1 -0
  144. package/src/rules/security/no-xpath-injection.d.ts +10 -0
  145. package/src/rules/security/no-xpath-injection.js +487 -0
  146. package/src/rules/security/no-xpath-injection.js.map +1 -0
  147. package/src/rules/security/no-xxe-injection.d.ts +7 -0
  148. package/src/rules/security/no-xxe-injection.js +270 -0
  149. package/src/rules/security/no-xxe-injection.js.map +1 -0
  150. package/src/rules/security/no-zip-slip.d.ts +9 -0
  151. package/src/rules/security/no-zip-slip.js +446 -0
  152. package/src/rules/security/no-zip-slip.js.map +1 -0
  153. package/src/types/index.d.ts +131 -0
  154. package/src/types/index.js +18 -0
  155. package/src/types/index.js.map +1 -0
@@ -0,0 +1,449 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.noMissingCorsCheck = void 0;
4
+ const eslint_devkit_1 = require("@interlace/eslint-devkit");
5
+ const eslint_devkit_2 = require("@interlace/eslint-devkit");
6
+ /**
7
+ * Check if a node is inside a CORS configuration
8
+ * Currently unused - kept for future use
9
+ * @coverage-note This function is intentionally unused and kept for future enhancements.
10
+ * It cannot be tested directly as it's not called by any code path.
11
+ */
12
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
13
+ function isInsideCorsConfig(node, sourceCode, trustedLibraries) {
14
+ let current = node;
15
+ while (current) {
16
+ // Check for CORS middleware usage
17
+ if (current.type === 'CallExpression') {
18
+ const callee = current.callee;
19
+ // Check if it's a CORS middleware call
20
+ if (callee.type === 'Identifier') {
21
+ const calleeName = callee.name.toLowerCase();
22
+ if (['cors', 'use', 'enable'].includes(calleeName)) {
23
+ return true;
24
+ }
25
+ }
26
+ // Check if it's a trusted library call
27
+ if (callee.type === 'MemberExpression') {
28
+ const object = callee.object;
29
+ if (object.type === 'Identifier') {
30
+ const objectName = object.name.toLowerCase();
31
+ if (trustedLibraries.some(lib => objectName.includes(lib.toLowerCase()))) {
32
+ return true;
33
+ }
34
+ }
35
+ }
36
+ }
37
+ // Check for CORS configuration object
38
+ if (current.type === 'ObjectExpression') {
39
+ const text = sourceCode.getText(current);
40
+ if (/\b(origin|credentials|allowedOrigins|allowedHeaders)\s*:/i.test(text)) {
41
+ // Check if it has proper validation (not just '*')
42
+ if (!/\borigin\s*:\s*['"]\*['"]/i.test(text)) {
43
+ return true;
44
+ }
45
+ }
46
+ }
47
+ // Traverse up the AST
48
+ if ('parent' in current && current.parent) {
49
+ current = current.parent;
50
+ }
51
+ else {
52
+ break;
53
+ }
54
+ }
55
+ return false;
56
+ }
57
+ /**
58
+ * Check if a string matches any ignore pattern
59
+ */
60
+ function matchesIgnorePattern(text, ignorePatterns) {
61
+ return ignorePatterns.some(pattern => {
62
+ try {
63
+ const regex = new RegExp(pattern, 'i');
64
+ return regex.test(text);
65
+ }
66
+ catch {
67
+ return false;
68
+ }
69
+ });
70
+ }
71
+ exports.noMissingCorsCheck = (0, eslint_devkit_2.createRule)({
72
+ name: 'no-missing-cors-check',
73
+ meta: {
74
+ type: 'problem',
75
+ docs: {
76
+ description: 'Detects missing CORS validation (wildcard CORS, missing origin check)',
77
+ },
78
+ hasSuggestions: true,
79
+ messages: {
80
+ missingCorsCheck: (0, eslint_devkit_1.formatLLMMessage)({
81
+ icon: eslint_devkit_1.MessageIcons.SECURITY,
82
+ issueName: 'Missing CORS Validation',
83
+ cwe: 'CWE-346',
84
+ description: 'Missing CORS validation detected: {{issue}}',
85
+ severity: 'HIGH',
86
+ fix: '{{safeAlternative}}',
87
+ documentationLink: 'https://cwe.mitre.org/data/definitions/346.html',
88
+ }),
89
+ useOriginValidation: (0, eslint_devkit_1.formatLLMMessage)({
90
+ icon: eslint_devkit_1.MessageIcons.INFO,
91
+ issueName: 'Validate Origin',
92
+ description: 'Validate CORS origin',
93
+ severity: 'LOW',
94
+ fix: 'cors({ origin: (origin, cb) => allowedOrigins.includes(origin) ? cb(null, true) : cb(new Error()) })',
95
+ documentationLink: 'https://github.com/expressjs/cors#configuration-options',
96
+ }),
97
+ useCorsMiddleware: (0, eslint_devkit_1.formatLLMMessage)({
98
+ icon: eslint_devkit_1.MessageIcons.INFO,
99
+ issueName: 'Use CORS Middleware',
100
+ description: 'Use CORS middleware with origin validation',
101
+ severity: 'LOW',
102
+ fix: 'app.use(cors({ origin: allowedOrigins }))',
103
+ documentationLink: 'https://github.com/expressjs/cors',
104
+ }),
105
+ },
106
+ schema: [
107
+ {
108
+ type: 'object',
109
+ properties: {
110
+ allowInTests: {
111
+ type: 'boolean',
112
+ default: false,
113
+ description: 'Allow missing CORS checks in test files',
114
+ },
115
+ trustedLibraries: {
116
+ type: 'array',
117
+ items: { type: 'string' },
118
+ default: [],
119
+ description: 'Custom CORS libraries to trust (wildcard origins in these libraries will not be reported)',
120
+ },
121
+ ignorePatterns: {
122
+ type: 'array',
123
+ items: { type: 'string' },
124
+ default: [],
125
+ description: 'Additional safe patterns to ignore',
126
+ },
127
+ },
128
+ additionalProperties: false,
129
+ },
130
+ ],
131
+ },
132
+ defaultOptions: [
133
+ {
134
+ allowInTests: false,
135
+ trustedLibraries: [], // Empty by default - users can add custom CORS libraries they trust
136
+ ignorePatterns: [],
137
+ },
138
+ ],
139
+ create(context, [options = {}]) {
140
+ const { allowInTests = false, trustedLibraries: corsTrustedLibraries = [], ignorePatterns = [], } = options;
141
+ const trustedLibraries = corsTrustedLibraries;
142
+ const filename = context.getFilename();
143
+ const isTestFile = allowInTests && /\.(test|spec)\.(ts|tsx|js|jsx)$/.test(filename);
144
+ const sourceCode = context.sourceCode || context.sourceCode;
145
+ function checkLiteral(node) {
146
+ if (isTestFile) {
147
+ return;
148
+ }
149
+ // Check for wildcard CORS origin
150
+ if (node.value === '*' && typeof node.value === 'string') {
151
+ const text = sourceCode.getText(node);
152
+ // Check if it matches any ignore pattern
153
+ if (matchesIgnorePattern(text, ignorePatterns)) {
154
+ return;
155
+ }
156
+ // Check if it's in contexts handled by other checkers
157
+ // 1. setHeader/header calls - checkMemberExpression handles these
158
+ // 2. app.use(cors({ origin: "*" })) - checkCallExpression handles these with suggestions
159
+ let shouldSkip = false;
160
+ let current = node;
161
+ while (current && current.parent) {
162
+ current = current.parent;
163
+ if (current.type === 'CallExpression') {
164
+ const callText = sourceCode.getText(current);
165
+ // Check if it's a setHeader/header call with Access-Control-Allow-Origin
166
+ // Skip these - checkMemberExpression handles them
167
+ if (/\b(setHeader|header)\s*\(/i.test(callText) && /\bAccess-Control-Allow-Origin\b/i.test(callText)) {
168
+ shouldSkip = true;
169
+ break;
170
+ }
171
+ // Check if it's app.use(cors({ origin: "*" })) - checkCallExpression handles these with suggestions
172
+ if (/\buse\s*\(/i.test(callText) && /\bcors\s*\(/i.test(callText)) {
173
+ // Check if the literal is in an object property named "origin"
174
+ if (node.parent && node.parent.type === 'Property') {
175
+ const prop = node.parent;
176
+ if (prop.key.type === 'Identifier' && prop.key.name === 'origin') {
177
+ shouldSkip = true;
178
+ break;
179
+ }
180
+ }
181
+ }
182
+ }
183
+ }
184
+ // Skip if it's in a context handled by another checker
185
+ if (shouldSkip) {
186
+ return;
187
+ }
188
+ // Check if it's in a CORS-related context
189
+ // Only report if it's actually in a CORS configuration (app.use(cors(...)), etc.)
190
+ // Not just any object with origin: "*"
191
+ let isActualCorsContext = false;
192
+ // Check if it's in app.use(cors(...)) or similar
193
+ current = node;
194
+ while (current && current.parent) {
195
+ current = current.parent;
196
+ if (current.type === 'CallExpression') {
197
+ const callText = sourceCode.getText(current);
198
+ // Check if it's a CORS middleware call
199
+ if (/\b(use|cors)\s*\(/i.test(callText) && /\bcors\s*\(/i.test(callText)) {
200
+ isActualCorsContext = true;
201
+ break;
202
+ }
203
+ }
204
+ }
205
+ // Also check if it's in an object property with name "origin" or "allowedOrigins"
206
+ // but only if it's in a CORS-related call expression
207
+ if (node.parent && node.parent.type === 'Property') {
208
+ const prop = node.parent;
209
+ if (prop.key.type === 'Identifier') {
210
+ const keyName = prop.key.name.toLowerCase();
211
+ if (keyName === 'origin' || keyName === 'allowedorigins') {
212
+ // Check if this property is in a CORS call context
213
+ let inCorsCall = false;
214
+ let checkNode = prop;
215
+ while (checkNode && checkNode.parent) {
216
+ checkNode = checkNode.parent;
217
+ if (checkNode.type === 'CallExpression') {
218
+ const callText = sourceCode.getText(checkNode);
219
+ if (/\bcors\s*\(/i.test(callText) ||
220
+ (/\buse\s*\(/i.test(callText) && /\bcors/i.test(callText))) {
221
+ inCorsCall = true;
222
+ break;
223
+ }
224
+ }
225
+ }
226
+ if (inCorsCall) {
227
+ // Always report wildcard CORS origin - it's never safe
228
+ context.report({
229
+ node,
230
+ messageId: 'missingCorsCheck',
231
+ data: {
232
+ issue: 'Wildcard CORS origin (*) allows all origins',
233
+ safeAlternative: 'Use origin validation: app.use(cors({ origin: (origin, callback) => { if (allowedOrigins.includes(origin)) callback(null, true); else callback(new Error("Not allowed")); } } }));',
234
+ },
235
+ suggest: [
236
+ {
237
+ messageId: 'useOriginValidation',
238
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
239
+ fix: (_fixer) => null,
240
+ },
241
+ ],
242
+ });
243
+ return;
244
+ }
245
+ }
246
+ }
247
+ }
248
+ // Only report if it's in an actual CORS context
249
+ if (isActualCorsContext) {
250
+ // Always report wildcard CORS origin - it's never safe
251
+ context.report({
252
+ node,
253
+ messageId: 'missingCorsCheck',
254
+ data: {
255
+ issue: 'Wildcard CORS origin (*) allows all origins',
256
+ safeAlternative: 'Use origin validation: app.use(cors({ origin: (origin, callback) => { if (allowedOrigins.includes(origin)) callback(null, true); else callback(new Error("Not allowed")); } } }));',
257
+ },
258
+ suggest: [
259
+ {
260
+ messageId: 'useOriginValidation',
261
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
262
+ fix: (_fixer) => null,
263
+ },
264
+ ],
265
+ });
266
+ }
267
+ }
268
+ }
269
+ function checkCallExpression(node) {
270
+ if (isTestFile) {
271
+ return;
272
+ }
273
+ // Check for app.use(cors({ origin: "*" })) or similar
274
+ if (node.callee.type === 'MemberExpression') {
275
+ const property = node.callee.property;
276
+ if (property.type === 'Identifier' && property.name === 'use') {
277
+ // Check if CORS is being used
278
+ const text = sourceCode.getText(node);
279
+ // Check if it matches any ignore pattern
280
+ if (matchesIgnorePattern(text, ignorePatterns)) {
281
+ return;
282
+ }
283
+ // Check if it's a CORS middleware call
284
+ // Check for cors() or trusted library calls
285
+ const firstArg = node.arguments.length > 0 ? node.arguments[0] : null;
286
+ let isCorsCall = /\bcors\s*\(/i.test(text);
287
+ if (!isCorsCall && firstArg && firstArg.type === 'CallExpression' && firstArg.callee.type === 'Identifier') {
288
+ const callee = firstArg.callee;
289
+ const calleeName = callee.name.toLowerCase();
290
+ // Check if it's the standard 'cors' library or a trusted library
291
+ isCorsCall = calleeName === 'cors' || trustedLibraries.some(lib => {
292
+ return calleeName.includes(lib.toLowerCase());
293
+ });
294
+ }
295
+ // Check if it's a trusted library - skip if explicitly trusted
296
+ let isTrustedLibrary = false;
297
+ if (firstArg && firstArg.type === 'CallExpression' && firstArg.callee.type === 'Identifier') {
298
+ const calleeName = firstArg.callee.name.toLowerCase();
299
+ isTrustedLibrary = trustedLibraries.some(lib => calleeName.includes(lib.toLowerCase()));
300
+ }
301
+ if (isTrustedLibrary) {
302
+ return; // Trusted library, skip
303
+ }
304
+ // Check if it's a CORS call
305
+ if (/\bcors\s*\(/i.test(text) || isCorsCall) {
306
+ // Check arguments for wildcard origin
307
+ // For app.use(cors({ origin: "*" })), we need to check the arguments to cors(), not app.use()
308
+ const corsCallArg = firstArg && firstArg.type === 'CallExpression' ? firstArg : null;
309
+ const argsToCheck = corsCallArg ? corsCallArg.arguments : node.arguments;
310
+ for (const arg of argsToCheck) {
311
+ if (arg.type === 'ObjectExpression') {
312
+ // Check for origin property with wildcard value
313
+ for (const prop of arg.properties) {
314
+ if (prop.type === 'Property' &&
315
+ prop.key.type === 'Identifier' &&
316
+ prop.key.name === 'origin' &&
317
+ prop.value.type === 'Literal' &&
318
+ prop.value.value === '*') {
319
+ context.report({
320
+ node: prop.value,
321
+ messageId: 'missingCorsCheck',
322
+ data: {
323
+ issue: 'Wildcard CORS origin (*) allows all origins',
324
+ safeAlternative: 'Use origin validation: app.use(cors({ origin: (origin, callback) => { if (allowedOrigins.includes(origin)) callback(null, true); else callback(new Error("Not allowed")); } } }));',
325
+ },
326
+ suggest: [
327
+ {
328
+ messageId: 'useOriginValidation',
329
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
330
+ fix: (_fixer) => null,
331
+ },
332
+ ],
333
+ });
334
+ }
335
+ }
336
+ }
337
+ else if (arg.type === 'Identifier') {
338
+ // Check if this identifier was assigned an object literal with origin: "*"
339
+ // For cases like: const config = { origin: "*" }; app.use(cors(config));
340
+ const varName = arg.name;
341
+ // Traverse the AST to find the variable declaration
342
+ let current = node;
343
+ while (current) {
344
+ if (current.type === 'Program' || current.type === 'FunctionDeclaration' || current.type === 'FunctionExpression' || current.type === 'ArrowFunctionExpression') {
345
+ // Search for variable declarations in this scope
346
+ const scopeBody = current.type === 'Program' ? current.body :
347
+ (current.type === 'FunctionDeclaration' || current.type === 'FunctionExpression' || current.type === 'ArrowFunctionExpression') ?
348
+ (current.body.type === 'BlockStatement' ? current.body.body : []) : [];
349
+ for (const stmt of scopeBody) {
350
+ if (stmt.type === 'VariableDeclaration') {
351
+ for (const declarator of stmt.declarations) {
352
+ if (declarator.id.type === 'Identifier' && declarator.id.name === varName && declarator.init) {
353
+ // Check if init is an object literal with origin: "*"
354
+ if (declarator.init.type === 'ObjectExpression') {
355
+ for (const prop of declarator.init.properties) {
356
+ if (prop.type === 'Property' &&
357
+ prop.key.type === 'Identifier' &&
358
+ prop.key.name === 'origin' &&
359
+ prop.value.type === 'Literal' &&
360
+ prop.value.value === '*') {
361
+ context.report({
362
+ node: arg,
363
+ messageId: 'missingCorsCheck',
364
+ data: {
365
+ issue: 'Wildcard CORS origin (*) allows all origins',
366
+ safeAlternative: 'Use origin validation: app.use(cors({ origin: (origin, callback) => { if (allowedOrigins.includes(origin)) callback(null, true); else callback(new Error("Not allowed")); } } }));',
367
+ },
368
+ suggest: [
369
+ {
370
+ messageId: 'useOriginValidation',
371
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
372
+ fix: (_fixer) => null,
373
+ },
374
+ ],
375
+ });
376
+ return; // Found and reported, exit
377
+ }
378
+ }
379
+ }
380
+ }
381
+ }
382
+ }
383
+ }
384
+ break; // Only check the immediate scope
385
+ }
386
+ if (current.parent) {
387
+ current = current.parent;
388
+ }
389
+ else {
390
+ break;
391
+ }
392
+ }
393
+ }
394
+ }
395
+ }
396
+ }
397
+ }
398
+ }
399
+ function checkMemberExpression(node) {
400
+ if (isTestFile) {
401
+ return;
402
+ }
403
+ // Check for Access-Control-Allow-Origin header without validation
404
+ if (node.property.type === 'Identifier') {
405
+ const propertyName = node.property.name;
406
+ if (propertyName === 'setHeader' || propertyName === 'header') {
407
+ // Check if it matches any ignore pattern
408
+ const text = sourceCode.getText(node);
409
+ if (matchesIgnorePattern(text, ignorePatterns)) {
410
+ return;
411
+ }
412
+ // Check if it's setting CORS headers
413
+ // Need to check the full call expression, not just the member expression
414
+ const parent = node.parent;
415
+ if (parent && parent.type === 'CallExpression') {
416
+ const callText = sourceCode.getText(parent);
417
+ if (/\bAccess-Control-Allow-Origin\b/i.test(callText)) {
418
+ // Check if the value is a wildcard
419
+ const args = parent.arguments;
420
+ if (args.length >= 2 && args[1].type === 'Literal' && args[1].value === '*') {
421
+ context.report({
422
+ node: args[1],
423
+ messageId: 'missingCorsCheck',
424
+ data: {
425
+ issue: 'Wildcard CORS header allows all origins',
426
+ safeAlternative: 'Validate origin before setting header: res.setHeader("Access-Control-Allow-Origin", allowedOrigins.includes(origin) ? origin : "null");',
427
+ },
428
+ suggest: [
429
+ {
430
+ messageId: 'useOriginValidation',
431
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
432
+ fix: (_fixer) => null,
433
+ },
434
+ ],
435
+ });
436
+ }
437
+ }
438
+ }
439
+ }
440
+ }
441
+ }
442
+ return {
443
+ Literal: checkLiteral,
444
+ CallExpression: checkCallExpression,
445
+ MemberExpression: checkMemberExpression,
446
+ };
447
+ },
448
+ });
449
+ //# sourceMappingURL=no-missing-cors-check.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"no-missing-cors-check.js","sourceRoot":"","sources":["../../../../../../packages/eslint-plugin-secure-coding/src/rules/security/no-missing-cors-check.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ export interface Options {
2
+ /** Allow missing CSRF protection in test files. Default: false */
3
+ allowInTests?: boolean;
4
+ /** CSRF middleware patterns to recognize. Default: ['csrf', 'csurf', 'csrfProtection', 'verifyCsrfToken'] */
5
+ csrfMiddlewarePatterns?: string[];
6
+ /** HTTP methods that require CSRF protection. Default: ['post', 'put', 'delete', 'patch'] */
7
+ protectedMethods?: string[];
8
+ /** Additional safe patterns to ignore. Default: [] */
9
+ ignorePatterns?: string[];
10
+ }
11
+ export declare const noMissingCsrfProtection: ESLintUtils.RuleModule<MessageIds, Options, unknown, ESLintUtils.RuleListener>;