eslint-plugin-secure-coding 2.3.3 → 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 (337) hide show
  1. package/CHANGELOG.md +51 -1
  2. package/README.md +2 -2
  3. package/package.json +1 -1
  4. package/src/index.d.ts +32 -0
  5. package/src/index.js +416 -0
  6. package/src/rules/detect-child-process/index.d.ts +11 -0
  7. package/src/rules/detect-child-process/index.js +529 -0
  8. package/src/rules/detect-eval-with-expression/index.d.ts +9 -0
  9. package/src/rules/detect-eval-with-expression/index.js +392 -0
  10. package/src/rules/detect-mixed-content/index.d.ts +8 -0
  11. package/src/rules/detect-mixed-content/index.js +44 -0
  12. package/src/rules/detect-non-literal-fs-filename/index.d.ts +7 -0
  13. package/src/rules/detect-non-literal-fs-filename/index.js +454 -0
  14. package/src/rules/detect-non-literal-regexp/index.d.ts +9 -0
  15. package/src/rules/detect-non-literal-regexp/index.js +403 -0
  16. package/src/rules/detect-object-injection/index.d.ts +11 -0
  17. package/src/rules/detect-object-injection/index.js +560 -0
  18. package/src/rules/detect-suspicious-dependencies/index.d.ts +8 -0
  19. package/src/rules/detect-suspicious-dependencies/index.js +71 -0
  20. package/src/rules/detect-weak-password-validation/index.d.ts +6 -0
  21. package/src/rules/detect-weak-password-validation/index.js +58 -0
  22. package/src/rules/no-allow-arbitrary-loads/index.d.ts +8 -0
  23. package/src/rules/no-allow-arbitrary-loads/index.js +47 -0
  24. package/src/rules/no-arbitrary-file-access/index.d.ts +13 -0
  25. package/src/rules/no-arbitrary-file-access/index.js +195 -0
  26. package/src/rules/no-buffer-overread/index.d.ts +29 -0
  27. package/src/rules/no-buffer-overread/index.js +606 -0
  28. package/src/rules/no-clickjacking/index.d.ts +10 -0
  29. package/src/rules/no-clickjacking/index.js +396 -0
  30. package/src/rules/no-client-side-auth-logic/index.d.ts +6 -0
  31. package/src/rules/no-client-side-auth-logic/index.js +69 -0
  32. package/src/rules/no-credentials-in-query-params/index.d.ts +8 -0
  33. package/src/rules/no-credentials-in-query-params/index.js +57 -0
  34. package/src/rules/no-data-in-temp-storage/index.d.ts +6 -0
  35. package/src/rules/no-data-in-temp-storage/index.js +64 -0
  36. package/src/rules/no-debug-code-in-production/index.d.ts +8 -0
  37. package/src/rules/no-debug-code-in-production/index.js +51 -0
  38. package/src/rules/no-directive-injection/index.d.ts +12 -0
  39. package/src/rules/no-directive-injection/index.js +457 -0
  40. package/src/rules/no-disabled-certificate-validation/index.d.ts +6 -0
  41. package/src/rules/no-disabled-certificate-validation/index.js +61 -0
  42. package/src/rules/no-dynamic-dependency-loading/index.d.ts +8 -0
  43. package/src/rules/no-dynamic-dependency-loading/index.js +51 -0
  44. package/src/rules/no-electron-security-issues/index.d.ts +10 -0
  45. package/src/rules/no-electron-security-issues/index.js +423 -0
  46. package/src/rules/no-exposed-debug-endpoints/index.d.ts +6 -0
  47. package/src/rules/no-exposed-debug-endpoints/index.js +62 -0
  48. package/src/rules/no-exposed-sensitive-data/index.d.ts +11 -0
  49. package/src/rules/no-exposed-sensitive-data/index.js +340 -0
  50. package/src/rules/no-format-string-injection/index.d.ts +17 -0
  51. package/src/rules/no-format-string-injection/index.js +660 -0
  52. package/src/rules/no-graphql-injection/index.d.ts +12 -0
  53. package/src/rules/no-graphql-injection/index.js +411 -0
  54. package/src/rules/no-hardcoded-credentials/index.d.ts +26 -0
  55. package/src/rules/no-hardcoded-credentials/index.js +376 -0
  56. package/src/rules/no-hardcoded-session-tokens/index.d.ts +6 -0
  57. package/src/rules/no-hardcoded-session-tokens/index.js +59 -0
  58. package/src/rules/no-http-urls/index.d.ts +12 -0
  59. package/src/rules/no-http-urls/index.js +114 -0
  60. package/src/rules/no-improper-sanitization/index.d.ts +12 -0
  61. package/src/rules/no-improper-sanitization/index.js +411 -0
  62. package/src/rules/no-improper-type-validation/index.d.ts +10 -0
  63. package/src/rules/no-improper-type-validation/index.js +475 -0
  64. package/src/rules/no-insecure-comparison/index.d.ts +7 -0
  65. package/src/rules/no-insecure-comparison/index.js +193 -0
  66. package/src/rules/no-insecure-redirects/index.d.ts +7 -0
  67. package/src/rules/no-insecure-redirects/index.js +216 -0
  68. package/src/rules/no-insecure-websocket/index.d.ts +6 -0
  69. package/src/rules/no-insecure-websocket/index.js +61 -0
  70. package/src/rules/no-ldap-injection/index.d.ts +10 -0
  71. package/src/rules/no-ldap-injection/index.js +455 -0
  72. package/src/rules/no-missing-authentication/index.d.ts +13 -0
  73. package/src/rules/no-missing-authentication/index.js +333 -0
  74. package/src/rules/no-missing-cors-check/index.d.ts +9 -0
  75. package/src/rules/no-missing-cors-check/index.js +399 -0
  76. package/src/rules/no-missing-csrf-protection/index.d.ts +11 -0
  77. package/src/rules/no-missing-csrf-protection/index.js +180 -0
  78. package/src/rules/no-missing-security-headers/index.d.ts +7 -0
  79. package/src/rules/no-missing-security-headers/index.js +218 -0
  80. package/src/rules/no-password-in-url/index.d.ts +8 -0
  81. package/src/rules/no-password-in-url/index.js +54 -0
  82. package/src/rules/no-permissive-cors/index.d.ts +8 -0
  83. package/src/rules/no-permissive-cors/index.js +65 -0
  84. package/src/rules/no-pii-in-logs/index.d.ts +8 -0
  85. package/src/rules/no-pii-in-logs/index.js +70 -0
  86. package/src/rules/no-privilege-escalation/index.d.ts +13 -0
  87. package/src/rules/no-privilege-escalation/index.js +321 -0
  88. package/src/rules/no-redos-vulnerable-regex/index.d.ts +7 -0
  89. package/src/rules/no-redos-vulnerable-regex/index.js +306 -0
  90. package/src/rules/no-sensitive-data-exposure/index.d.ts +11 -0
  91. package/src/rules/no-sensitive-data-exposure/index.js +250 -0
  92. package/src/rules/no-sensitive-data-in-analytics/index.d.ts +8 -0
  93. package/src/rules/no-sensitive-data-in-analytics/index.js +62 -0
  94. package/src/rules/no-sensitive-data-in-cache/index.d.ts +8 -0
  95. package/src/rules/no-sensitive-data-in-cache/index.js +52 -0
  96. package/src/rules/no-toctou-vulnerability/index.d.ts +7 -0
  97. package/src/rules/no-toctou-vulnerability/index.js +208 -0
  98. package/src/rules/no-tracking-without-consent/index.d.ts +6 -0
  99. package/src/rules/no-tracking-without-consent/index.js +67 -0
  100. package/src/rules/no-unchecked-loop-condition/index.d.ts +12 -0
  101. package/src/rules/no-unchecked-loop-condition/index.js +646 -0
  102. package/src/rules/no-unencrypted-transmission/index.d.ts +11 -0
  103. package/src/rules/no-unencrypted-transmission/index.js +236 -0
  104. package/src/rules/no-unescaped-url-parameter/index.d.ts +9 -0
  105. package/src/rules/no-unescaped-url-parameter/index.js +355 -0
  106. package/src/rules/no-unlimited-resource-allocation/index.d.ts +12 -0
  107. package/src/rules/no-unlimited-resource-allocation/index.js +643 -0
  108. package/src/rules/no-unsafe-deserialization/index.d.ts +10 -0
  109. package/src/rules/no-unsafe-deserialization/index.js +491 -0
  110. package/src/rules/no-unsafe-dynamic-require/index.d.ts +5 -0
  111. package/src/rules/no-unsafe-dynamic-require/index.js +106 -0
  112. package/src/rules/no-unsafe-regex-construction/index.d.ts +9 -0
  113. package/src/rules/no-unsafe-regex-construction/index.js +291 -0
  114. package/src/rules/no-unvalidated-deeplinks/index.d.ts +6 -0
  115. package/src/rules/no-unvalidated-deeplinks/index.js +62 -0
  116. package/src/rules/no-unvalidated-user-input/index.d.ts +9 -0
  117. package/src/rules/no-unvalidated-user-input/index.js +420 -0
  118. package/src/rules/no-verbose-error-messages/index.d.ts +8 -0
  119. package/src/rules/no-verbose-error-messages/index.js +68 -0
  120. package/src/rules/no-weak-password-recovery/index.d.ts +12 -0
  121. package/src/rules/no-weak-password-recovery/index.js +424 -0
  122. package/src/rules/no-xpath-injection/index.d.ts +10 -0
  123. package/src/rules/no-xpath-injection/index.js +487 -0
  124. package/src/rules/no-xxe-injection/index.d.ts +7 -0
  125. package/src/rules/no-xxe-injection/index.js +266 -0
  126. package/src/rules/no-zip-slip/index.d.ts +9 -0
  127. package/src/rules/no-zip-slip/index.js +445 -0
  128. package/src/rules/require-backend-authorization/index.d.ts +6 -0
  129. package/src/rules/require-backend-authorization/index.js +60 -0
  130. package/src/rules/require-code-minification/index.d.ts +8 -0
  131. package/src/rules/require-code-minification/index.js +47 -0
  132. package/src/rules/require-csp-headers/index.d.ts +6 -0
  133. package/src/rules/require-csp-headers/index.js +64 -0
  134. package/src/rules/require-data-minimization/index.d.ts +8 -0
  135. package/src/rules/require-data-minimization/index.js +53 -0
  136. package/src/rules/require-dependency-integrity/index.d.ts +6 -0
  137. package/src/rules/require-dependency-integrity/index.js +64 -0
  138. package/src/rules/require-https-only/index.d.ts +8 -0
  139. package/src/rules/require-https-only/index.js +62 -0
  140. package/src/rules/require-mime-type-validation/index.d.ts +6 -0
  141. package/src/rules/require-mime-type-validation/index.js +66 -0
  142. package/src/rules/require-network-timeout/index.d.ts +8 -0
  143. package/src/rules/require-network-timeout/index.js +50 -0
  144. package/src/rules/require-package-lock/index.d.ts +8 -0
  145. package/src/rules/require-package-lock/index.js +63 -0
  146. package/src/rules/require-secure-credential-storage/index.d.ts +8 -0
  147. package/src/rules/require-secure-credential-storage/index.js +50 -0
  148. package/src/rules/require-secure-defaults/index.d.ts +8 -0
  149. package/src/rules/require-secure-defaults/index.js +47 -0
  150. package/src/rules/require-secure-deletion/index.d.ts +8 -0
  151. package/src/rules/require-secure-deletion/index.js +44 -0
  152. package/src/rules/require-storage-encryption/index.d.ts +8 -0
  153. package/src/rules/require-storage-encryption/index.js +50 -0
  154. package/src/rules/require-url-validation/index.d.ts +6 -0
  155. package/src/rules/require-url-validation/index.js +72 -0
  156. package/src/types/index.d.ts +106 -0
  157. package/src/types/index.js +16 -0
  158. package/src/index.ts +0 -605
  159. package/src/rules/__tests__/integration-demo.test.ts +0 -290
  160. package/src/rules/__tests__/integration-llm.test.ts +0 -89
  161. package/src/rules/database-injection/database-injection.test.ts +0 -456
  162. package/src/rules/database-injection/index.ts +0 -488
  163. package/src/rules/detect-child-process/detect-child-process.test.ts +0 -207
  164. package/src/rules/detect-child-process/index.ts +0 -634
  165. package/src/rules/detect-eval-with-expression/detect-eval-with-expression.test.ts +0 -416
  166. package/src/rules/detect-eval-with-expression/index.ts +0 -463
  167. package/src/rules/detect-mixed-content/detect-mixed-content.test.ts +0 -28
  168. package/src/rules/detect-mixed-content/index.ts +0 -52
  169. package/src/rules/detect-non-literal-fs-filename/detect-non-literal-fs-filename.test.ts +0 -269
  170. package/src/rules/detect-non-literal-fs-filename/index.ts +0 -551
  171. package/src/rules/detect-non-literal-regexp/detect-non-literal-regexp.test.ts +0 -189
  172. package/src/rules/detect-non-literal-regexp/index.ts +0 -490
  173. package/src/rules/detect-object-injection/detect-object-injection.test.ts +0 -440
  174. package/src/rules/detect-object-injection/index.ts +0 -674
  175. package/src/rules/detect-suspicious-dependencies/detect-suspicious-dependencies.test.ts +0 -32
  176. package/src/rules/detect-suspicious-dependencies/index.ts +0 -84
  177. package/src/rules/detect-weak-password-validation/detect-weak-password-validation.test.ts +0 -31
  178. package/src/rules/detect-weak-password-validation/index.ts +0 -68
  179. package/src/rules/no-allow-arbitrary-loads/index.ts +0 -54
  180. package/src/rules/no-allow-arbitrary-loads/no-allow-arbitrary-loads.test.ts +0 -28
  181. package/src/rules/no-arbitrary-file-access/index.ts +0 -238
  182. package/src/rules/no-arbitrary-file-access/no-arbitrary-file-access.test.ts +0 -119
  183. package/src/rules/no-buffer-overread/index.ts +0 -724
  184. package/src/rules/no-buffer-overread/no-buffer-overread.test.ts +0 -313
  185. package/src/rules/no-clickjacking/index.ts +0 -481
  186. package/src/rules/no-clickjacking/no-clickjacking.test.ts +0 -253
  187. package/src/rules/no-client-side-auth-logic/index.ts +0 -81
  188. package/src/rules/no-client-side-auth-logic/no-client-side-auth-logic.test.ts +0 -33
  189. package/src/rules/no-credentials-in-query-params/index.ts +0 -69
  190. package/src/rules/no-credentials-in-query-params/no-credentials-in-query-params.test.ts +0 -33
  191. package/src/rules/no-credentials-in-storage-api/index.ts +0 -64
  192. package/src/rules/no-credentials-in-storage-api/no-credentials-in-storage-api.test.ts +0 -31
  193. package/src/rules/no-data-in-temp-storage/index.ts +0 -75
  194. package/src/rules/no-data-in-temp-storage/no-data-in-temp-storage.test.ts +0 -33
  195. package/src/rules/no-debug-code-in-production/index.ts +0 -59
  196. package/src/rules/no-debug-code-in-production/no-debug-code-in-production.test.ts +0 -26
  197. package/src/rules/no-directive-injection/index.ts +0 -551
  198. package/src/rules/no-directive-injection/no-directive-injection.test.ts +0 -305
  199. package/src/rules/no-disabled-certificate-validation/index.ts +0 -72
  200. package/src/rules/no-disabled-certificate-validation/no-disabled-certificate-validation.test.ts +0 -33
  201. package/src/rules/no-document-cookie/index.ts +0 -113
  202. package/src/rules/no-document-cookie/no-document-cookie.test.ts +0 -382
  203. package/src/rules/no-dynamic-dependency-loading/index.ts +0 -60
  204. package/src/rules/no-dynamic-dependency-loading/no-dynamic-dependency-loading.test.ts +0 -27
  205. package/src/rules/no-electron-security-issues/index.ts +0 -504
  206. package/src/rules/no-electron-security-issues/no-electron-security-issues.test.ts +0 -324
  207. package/src/rules/no-exposed-debug-endpoints/index.ts +0 -73
  208. package/src/rules/no-exposed-debug-endpoints/no-exposed-debug-endpoints.test.ts +0 -40
  209. package/src/rules/no-exposed-sensitive-data/index.ts +0 -428
  210. package/src/rules/no-exposed-sensitive-data/no-exposed-sensitive-data.test.ts +0 -75
  211. package/src/rules/no-format-string-injection/index.ts +0 -801
  212. package/src/rules/no-format-string-injection/no-format-string-injection.test.ts +0 -437
  213. package/src/rules/no-graphql-injection/index.ts +0 -508
  214. package/src/rules/no-graphql-injection/no-graphql-injection.test.ts +0 -371
  215. package/src/rules/no-hardcoded-credentials/index.ts +0 -478
  216. package/src/rules/no-hardcoded-credentials/no-hardcoded-credentials.test.ts +0 -639
  217. package/src/rules/no-hardcoded-session-tokens/index.ts +0 -69
  218. package/src/rules/no-hardcoded-session-tokens/no-hardcoded-session-tokens.test.ts +0 -42
  219. package/src/rules/no-http-urls/index.ts +0 -131
  220. package/src/rules/no-http-urls/no-http-urls.test.ts +0 -60
  221. package/src/rules/no-improper-sanitization/index.ts +0 -502
  222. package/src/rules/no-improper-sanitization/no-improper-sanitization.test.ts +0 -156
  223. package/src/rules/no-improper-type-validation/index.ts +0 -572
  224. package/src/rules/no-improper-type-validation/no-improper-type-validation.test.ts +0 -372
  225. package/src/rules/no-insecure-comparison/index.ts +0 -232
  226. package/src/rules/no-insecure-comparison/no-insecure-comparison.test.ts +0 -218
  227. package/src/rules/no-insecure-cookie-settings/index.ts +0 -391
  228. package/src/rules/no-insecure-cookie-settings/no-insecure-cookie-settings.test.ts +0 -409
  229. package/src/rules/no-insecure-jwt/index.ts +0 -467
  230. package/src/rules/no-insecure-jwt/no-insecure-jwt.test.ts +0 -259
  231. package/src/rules/no-insecure-redirects/index.ts +0 -267
  232. package/src/rules/no-insecure-redirects/no-insecure-redirects.test.ts +0 -108
  233. package/src/rules/no-insecure-websocket/index.ts +0 -72
  234. package/src/rules/no-insecure-websocket/no-insecure-websocket.test.ts +0 -42
  235. package/src/rules/no-insufficient-postmessage-validation/index.ts +0 -497
  236. package/src/rules/no-insufficient-postmessage-validation/no-insufficient-postmessage-validation.test.ts +0 -360
  237. package/src/rules/no-insufficient-random/index.ts +0 -288
  238. package/src/rules/no-insufficient-random/no-insufficient-random.test.ts +0 -246
  239. package/src/rules/no-ldap-injection/index.ts +0 -547
  240. package/src/rules/no-ldap-injection/no-ldap-injection.test.ts +0 -317
  241. package/src/rules/no-missing-authentication/index.ts +0 -408
  242. package/src/rules/no-missing-authentication/no-missing-authentication.test.ts +0 -350
  243. package/src/rules/no-missing-cors-check/index.ts +0 -453
  244. package/src/rules/no-missing-cors-check/no-missing-cors-check.test.ts +0 -392
  245. package/src/rules/no-missing-csrf-protection/index.ts +0 -229
  246. package/src/rules/no-missing-csrf-protection/no-missing-csrf-protection.test.ts +0 -222
  247. package/src/rules/no-missing-security-headers/index.ts +0 -266
  248. package/src/rules/no-missing-security-headers/no-missing-security-headers.test.ts +0 -98
  249. package/src/rules/no-password-in-url/index.ts +0 -64
  250. package/src/rules/no-password-in-url/no-password-in-url.test.ts +0 -27
  251. package/src/rules/no-permissive-cors/index.ts +0 -78
  252. package/src/rules/no-permissive-cors/no-permissive-cors.test.ts +0 -28
  253. package/src/rules/no-pii-in-logs/index.ts +0 -83
  254. package/src/rules/no-pii-in-logs/no-pii-in-logs.test.ts +0 -26
  255. package/src/rules/no-postmessage-origin-wildcard/index.ts +0 -67
  256. package/src/rules/no-postmessage-origin-wildcard/no-postmessage-origin-wildcard.test.ts +0 -27
  257. package/src/rules/no-privilege-escalation/index.ts +0 -403
  258. package/src/rules/no-privilege-escalation/no-privilege-escalation.test.ts +0 -306
  259. package/src/rules/no-redos-vulnerable-regex/index.ts +0 -379
  260. package/src/rules/no-redos-vulnerable-regex/no-redos-vulnerable-regex.test.ts +0 -83
  261. package/src/rules/no-sensitive-data-exposure/index.ts +0 -294
  262. package/src/rules/no-sensitive-data-exposure/no-sensitive-data-exposure.test.ts +0 -262
  263. package/src/rules/no-sensitive-data-in-analytics/index.ts +0 -73
  264. package/src/rules/no-sensitive-data-in-analytics/no-sensitive-data-in-analytics.test.ts +0 -42
  265. package/src/rules/no-sensitive-data-in-cache/index.ts +0 -59
  266. package/src/rules/no-sensitive-data-in-cache/no-sensitive-data-in-cache.test.ts +0 -32
  267. package/src/rules/no-sql-injection/index.ts +0 -424
  268. package/src/rules/no-sql-injection/no-sql-injection.test.ts +0 -303
  269. package/src/rules/no-timing-attack/index.ts +0 -552
  270. package/src/rules/no-timing-attack/no-timing-attack.test.ts +0 -348
  271. package/src/rules/no-toctou-vulnerability/index.ts +0 -250
  272. package/src/rules/no-toctou-vulnerability/no-toctou-vulnerability.test.ts +0 -60
  273. package/src/rules/no-tracking-without-consent/index.ts +0 -78
  274. package/src/rules/no-tracking-without-consent/no-tracking-without-consent.test.ts +0 -34
  275. package/src/rules/no-unchecked-loop-condition/index.ts +0 -781
  276. package/src/rules/no-unchecked-loop-condition/no-unchecked-loop-condition.test.ts +0 -459
  277. package/src/rules/no-unencrypted-local-storage/index.ts +0 -73
  278. package/src/rules/no-unencrypted-local-storage/no-unencrypted-local-storage.test.ts +0 -41
  279. package/src/rules/no-unencrypted-transmission/index.ts +0 -296
  280. package/src/rules/no-unencrypted-transmission/no-unencrypted-transmission.test.ts +0 -287
  281. package/src/rules/no-unescaped-url-parameter/index.ts +0 -424
  282. package/src/rules/no-unescaped-url-parameter/no-unescaped-url-parameter.test.ts +0 -263
  283. package/src/rules/no-unlimited-resource-allocation/index.ts +0 -767
  284. package/src/rules/no-unlimited-resource-allocation/no-unlimited-resource-allocation.test.ts +0 -544
  285. package/src/rules/no-unsafe-deserialization/index.ts +0 -593
  286. package/src/rules/no-unsafe-deserialization/no-unsafe-deserialization.test.ts +0 -310
  287. package/src/rules/no-unsafe-dynamic-require/index.ts +0 -125
  288. package/src/rules/no-unsafe-dynamic-require/no-unsafe-dynamic-require.test.ts +0 -151
  289. package/src/rules/no-unsafe-regex-construction/index.ts +0 -370
  290. package/src/rules/no-unsafe-regex-construction/no-unsafe-regex-construction.test.ts +0 -181
  291. package/src/rules/no-unsanitized-html/index.ts +0 -400
  292. package/src/rules/no-unsanitized-html/no-unsanitized-html.test.ts +0 -488
  293. package/src/rules/no-unvalidated-deeplinks/index.ts +0 -73
  294. package/src/rules/no-unvalidated-deeplinks/no-unvalidated-deeplinks.test.ts +0 -29
  295. package/src/rules/no-unvalidated-user-input/index.ts +0 -498
  296. package/src/rules/no-unvalidated-user-input/no-unvalidated-user-input.test.ts +0 -463
  297. package/src/rules/no-verbose-error-messages/index.ts +0 -83
  298. package/src/rules/no-verbose-error-messages/no-verbose-error-messages.test.ts +0 -34
  299. package/src/rules/no-weak-crypto/index.ts +0 -447
  300. package/src/rules/no-weak-crypto/no-weak-crypto.test.ts +0 -297
  301. package/src/rules/no-weak-password-recovery/index.ts +0 -509
  302. package/src/rules/no-weak-password-recovery/no-weak-password-recovery.test.ts +0 -184
  303. package/src/rules/no-xpath-injection/index.ts +0 -596
  304. package/src/rules/no-xpath-injection/no-xpath-injection.test.ts +0 -405
  305. package/src/rules/no-xxe-injection/index.ts +0 -342
  306. package/src/rules/no-xxe-injection/no-xxe-injection.test.ts +0 -122
  307. package/src/rules/no-zip-slip/index.ts +0 -526
  308. package/src/rules/no-zip-slip/no-zip-slip.test.ts +0 -305
  309. package/src/rules/require-backend-authorization/index.ts +0 -71
  310. package/src/rules/require-backend-authorization/require-backend-authorization.test.ts +0 -31
  311. package/src/rules/require-code-minification/index.ts +0 -54
  312. package/src/rules/require-code-minification/require-code-minification.test.ts +0 -30
  313. package/src/rules/require-csp-headers/index.ts +0 -74
  314. package/src/rules/require-csp-headers/require-csp-headers.test.ts +0 -34
  315. package/src/rules/require-data-minimization/index.ts +0 -65
  316. package/src/rules/require-data-minimization/require-data-minimization.test.ts +0 -31
  317. package/src/rules/require-dependency-integrity/index.ts +0 -78
  318. package/src/rules/require-dependency-integrity/require-dependency-integrity.test.ts +0 -44
  319. package/src/rules/require-https-only/index.ts +0 -75
  320. package/src/rules/require-https-only/require-https-only.test.ts +0 -26
  321. package/src/rules/require-mime-type-validation/index.ts +0 -77
  322. package/src/rules/require-mime-type-validation/require-mime-type-validation.test.ts +0 -32
  323. package/src/rules/require-network-timeout/index.ts +0 -58
  324. package/src/rules/require-network-timeout/require-network-timeout.test.ts +0 -26
  325. package/src/rules/require-package-lock/index.ts +0 -75
  326. package/src/rules/require-package-lock/require-package-lock.test.ts +0 -27
  327. package/src/rules/require-secure-credential-storage/index.ts +0 -60
  328. package/src/rules/require-secure-credential-storage/require-secure-credential-storage.test.ts +0 -26
  329. package/src/rules/require-secure-defaults/index.ts +0 -54
  330. package/src/rules/require-secure-defaults/require-secure-defaults.test.ts +0 -26
  331. package/src/rules/require-secure-deletion/index.ts +0 -52
  332. package/src/rules/require-secure-deletion/require-secure-deletion.test.ts +0 -29
  333. package/src/rules/require-storage-encryption/index.ts +0 -60
  334. package/src/rules/require-storage-encryption/require-storage-encryption.test.ts +0 -26
  335. package/src/rules/require-url-validation/index.ts +0 -85
  336. package/src/rules/require-url-validation/require-url-validation.test.ts +0 -32
  337. package/src/types/index.ts +0 -235
@@ -1,189 +0,0 @@
1
- /**
2
- * Comprehensive tests for detect-non-literal-regexp rule
3
- * Security: CWE-400 (ReDoS - Regular Expression Denial of Service)
4
- */
5
- import { RuleTester } from '@typescript-eslint/rule-tester';
6
- import { describe, it, afterAll } from 'vitest';
7
- import parser from '@typescript-eslint/parser';
8
- import { detectNonLiteralRegexp } from './index';
9
-
10
- // Configure RuleTester for Vitest
11
- RuleTester.afterAll = afterAll;
12
- RuleTester.it = it;
13
- RuleTester.itOnly = it.only;
14
- RuleTester.describe = describe;
15
-
16
- // Use Flat Config format (ESLint 9+)
17
- const ruleTester = new RuleTester({
18
- languageOptions: {
19
- parser,
20
- ecmaVersion: 2022,
21
- sourceType: 'module',
22
- },
23
- });
24
-
25
- describe('detect-non-literal-regexp', () => {
26
- describe('Valid Code', () => {
27
- ruleTester.run('valid - safe regex patterns', detectNonLiteralRegexp, {
28
- valid: [
29
- // Not RegExp - these are safe
30
- {
31
- code: 'const result = myFunction(pattern);',
32
- },
33
- {
34
- code: 'obj.RegExp(pattern);',
35
- },
36
- // Note: This rule is very strict and detects ReDoS patterns even in literals
37
- // Most regex patterns will trigger the rule, so we only test non-RegExp code as valid
38
- ],
39
- invalid: [],
40
- });
41
- });
42
-
43
- describe('Invalid Code - Dynamic RegExp', () => {
44
- ruleTester.run('invalid - dynamic regex patterns', detectNonLiteralRegexp, {
45
- valid: [],
46
- invalid: [
47
- {
48
- code: 'const pattern = new RegExp(userInput);',
49
- errors: [{ messageId: 'regexpReDoS' }],
50
- },
51
- {
52
- code: 'const regex = RegExp(userPattern);',
53
- errors: [{ messageId: 'regexpReDoS' }],
54
- },
55
- {
56
- code: 'new RegExp(`^${userInput}$`);',
57
- errors: [{ messageId: 'regexpReDoS' }],
58
- },
59
- {
60
- code: `
61
- const pattern = getUserInput();
62
- const regex = new RegExp(pattern);
63
- `,
64
- errors: [{ messageId: 'regexpReDoS' }],
65
- },
66
- {
67
- code: 'new RegExp(config.pattern);',
68
- errors: [{ messageId: 'regexpReDoS' }],
69
- },
70
- ],
71
- });
72
- });
73
-
74
- describe('Invalid Code - ReDoS Patterns in Literals', () => {
75
- ruleTester.run('invalid - True ReDoS vulnerable patterns', detectNonLiteralRegexp, {
76
- valid: [
77
- // Simple regex literals are now safe - no nested quantifiers
78
- { code: 'const pattern = /^[a-z]+$/;' },
79
- { code: 'const emailRegex = /^[\\w-\\.]+@([\\w-]+\\.)+[\\w-]{2,4}$/;' },
80
- // Static string patterns with new RegExp are now also safe by default
81
- { code: 'const pattern = new RegExp("^[a-z]+$");' },
82
- { code: 'const pattern = RegExp("^test$");' },
83
- { code: 'const pattern = new RegExp(`^test$`);' },
84
- // Explicitly allowing literals also works
85
- { code: 'const pattern = new RegExp("^[a-z]+$");', options: [{ allowLiterals: true }] },
86
- { code: 'const pattern = RegExp("^test$");', options: [{ allowLiterals: true }] },
87
- { code: 'const pattern = new RegExp(`^test$`);', options: [{ allowLiterals: true }] },
88
- ],
89
- invalid: [
90
- // Truly dangerous nested quantifier patterns: (a+)+
91
- {
92
- code: 'const pattern = /(a+)+b/;',
93
- errors: [{ messageId: 'regexpReDoS' }],
94
- },
95
- {
96
- code: 'const pattern = /([a-z]+)*/;',
97
- errors: [{ messageId: 'regexpReDoS' }],
98
- },
99
- // Dynamic regex with variables still flagged
100
- {
101
- code: 'const pattern = new RegExp(userInput);',
102
- errors: [{ messageId: 'regexpReDoS' }],
103
- },
104
- ],
105
- });
106
- });
107
-
108
-
109
- describe('Suggestions', () => {
110
- ruleTester.run('suggestions for fixes', detectNonLiteralRegexp, {
111
- valid: [],
112
- invalid: [
113
- {
114
- code: 'const regex = new RegExp(userInput);',
115
- errors: [
116
- {
117
- messageId: 'regexpReDoS',
118
- // Note: Rule may not provide suggestions in all cases
119
- },
120
- ],
121
- },
122
- ],
123
- });
124
- });
125
-
126
- describe('Edge Cases', () => {
127
- ruleTester.run('edge cases', detectNonLiteralRegexp, {
128
- valid: [
129
- // Note: Rule may detect RegExp calls even when reassigned
130
- // This is a limitation of static analysis
131
- // allowLiterals option now allows static string patterns
132
- {
133
- code: 'new RegExp("^test$");',
134
- options: [{ allowLiterals: true }],
135
- },
136
- ],
137
- invalid: [
138
- {
139
- code: 'const RegExp = myFunction; RegExp(pattern);',
140
- errors: [{ messageId: 'regexpReDoS' }],
141
- },
142
- ],
143
- });
144
- });
145
-
146
- describe('Options', () => {
147
- ruleTester.run('options testing', detectNonLiteralRegexp, {
148
- valid: [
149
- // allowLiterals option now allows static string patterns
150
- {
151
- code: 'new RegExp("^test$");',
152
- options: [{ allowLiterals: true }],
153
- },
154
- ],
155
- invalid: [
156
- // Dynamic userInput patterns are still flagged
157
- {
158
- code: 'new RegExp(userInput);',
159
- options: [{ maxPatternLength: 100 }],
160
- errors: [{ messageId: 'regexpReDoS' }],
161
- },
162
- {
163
- code: 'new RegExp(userInput);',
164
- options: [{ allowLiterals: true }],
165
- errors: [{ messageId: 'regexpReDoS' }],
166
- },
167
- ],
168
- });
169
- });
170
-
171
- describe('Uncovered Lines', () => {
172
- // Note: Lines 365-368 (early return with allowLiterals) are not testable
173
- // because the rule flags all regex patterns as potentially vulnerable
174
- // The allowLiterals option only affects whether literals are processed or not
175
-
176
- // Line 389: Early return when no vulnerability is detected
177
- ruleTester.run('line 389 - no vulnerability detected', detectNonLiteralRegexp, {
178
- valid: [],
179
- invalid: [
180
- // This should trigger the no vulnerability case, but still report due to dynamic nature
181
- {
182
- code: 'new RegExp(userInput);',
183
- errors: [{ messageId: 'regexpReDoS' }],
184
- },
185
- ],
186
- });
187
- });
188
- });
189
-
@@ -1,490 +0,0 @@
1
- /**
2
- * ESLint Rule: detect-non-literal-regexp
3
- * Detects RegExp(variable), which might allow an attacker to DOS your server with a long-running regular expression
4
- * LLM-optimized with comprehensive ReDoS prevention guidance
5
- *
6
- * @see https://owasp.org/www-community/attacks/Regular_expression_Denial_of_Service_-_ReDoS
7
- * @see https://cwe.mitre.org/data/definitions/400.html
8
- */
9
- import type { TSESLint, TSESTree } from '@interlace/eslint-devkit';
10
- import { formatLLMMessage, MessageIcons } from '@interlace/eslint-devkit';
11
- import { createRule } from '@interlace/eslint-devkit';
12
-
13
- type MessageIds =
14
- | 'regexpReDoS'
15
- | 'useStaticRegex'
16
- | 'validateInput'
17
- | 'useRegexLibrary'
18
- | 'addTimeout'
19
- | 'escapeUserInput';
20
-
21
- export interface Options {
22
- /** Allow literal string regex patterns. Default: false (stricter) */
23
- allowLiterals?: boolean;
24
-
25
- /** Additional RegExp creation patterns to check */
26
- additionalPatterns?: string[];
27
-
28
- /** Maximum allowed pattern length for dynamic regex */
29
- maxPatternLength?: number;
30
- }
31
-
32
- type RuleOptions = [Options?];
33
-
34
- // Type guard for regex literal nodes
35
- const isRegExpLiteral = (node: TSESTree.Node): node is TSESTree.Literal & { regex: { pattern: string; flags: string } } => {
36
- return node.type === 'Literal' && Object.prototype.hasOwnProperty.call(node, 'regex');
37
- };
38
-
39
- /**
40
- * RegExp creation patterns and their security implications
41
- */
42
- interface RegExpPattern {
43
- pattern: string;
44
- dangerous: boolean;
45
- vulnerability: 'redos' | 'injection' | 'performance';
46
- safeAlternative: string;
47
- example: { bad: string; good: string };
48
- effort: string;
49
- riskLevel: 'low' | 'medium' | 'high' | 'critical';
50
- }
51
-
52
- const REGEXP_PATTERNS: RegExpPattern[] = [
53
- {
54
- pattern: 'new RegExp\\(.*\\)',
55
- dangerous: true,
56
- vulnerability: 'redos',
57
- safeAlternative: 'Pre-defined RegExp constants',
58
- example: {
59
- bad: 'new RegExp(userInput)',
60
- good: 'const PATTERNS = { email: /^[a-zA-Z0-9]+$/ }; PATTERNS[userChoice]'
61
- },
62
- effort: '10-15 minutes',
63
- riskLevel: 'high'
64
- },
65
- {
66
- pattern: 'RegExp\\(.*\\)',
67
- dangerous: true,
68
- vulnerability: 'redos',
69
- safeAlternative: 'Static RegExp literals or validated patterns',
70
- example: {
71
- bad: 'RegExp(userPattern)',
72
- good: 'const safePattern = userPattern.replace(/[.*+?^${}()|[\\]\\\\]/g, \'\\\\$&\'); new RegExp(`^${safePattern}$`)'
73
- },
74
- effort: '15-20 minutes',
75
- riskLevel: 'high'
76
- },
77
- {
78
- pattern: '/.*\\*\\*.*|.*\\+\\+.*|.*\\?\\?/',
79
- dangerous: true,
80
- vulnerability: 'redos',
81
- safeAlternative: 'Avoid nested quantifiers, use atomic groups',
82
- example: {
83
- bad: '/(a+)+b/', // ReDoS vulnerable
84
- good: '/(?>a+)b/', // Atomic group (if supported) or restructure
85
- },
86
- effort: '20-30 minutes',
87
- riskLevel: 'critical'
88
- }
89
- ];
90
-
91
- export const detectNonLiteralRegexp = createRule<RuleOptions, MessageIds>({
92
- name: 'detect-non-literal-regexp',
93
- meta: {
94
- type: 'problem',
95
- docs: {
96
- description: 'Detects RegExp(variable), which might allow an attacker to DOS your server with a long-running regular expression',
97
- },
98
- messages: {
99
- // 🎯 Token optimization: 41% reduction (51→30 tokens) - compact template variables
100
- regexpReDoS: formatLLMMessage({
101
- icon: MessageIcons.WARNING,
102
- issueName: 'ReDoS vulnerability',
103
- cwe: 'CWE-400',
104
- description: 'ReDoS vulnerability detected',
105
- severity: '{{riskLevel}}',
106
- fix: '{{safeAlternative}}',
107
- documentationLink: 'https://owasp.org/www-community/attacks/Regular_expression_Denial_of_Service_-_ReDoS',
108
- }),
109
- useStaticRegex: formatLLMMessage({
110
- icon: MessageIcons.INFO,
111
- issueName: 'Use Static Regex',
112
- description: 'Use pre-defined RegExp constants',
113
- severity: 'LOW',
114
- fix: 'const PATTERN = /^[a-z]+$/; // Define at module level',
115
- documentationLink: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp',
116
- }),
117
- validateInput: formatLLMMessage({
118
- icon: MessageIcons.INFO,
119
- issueName: 'Validate Input',
120
- description: 'Validate and escape user input',
121
- severity: 'LOW',
122
- fix: 'Validate input length and characters before RegExp',
123
- documentationLink: 'https://owasp.org/www-community/attacks/Regular_expression_Denial_of_Service_-_ReDoS',
124
- }),
125
- useRegexLibrary: formatLLMMessage({
126
- icon: MessageIcons.INFO,
127
- issueName: 'Use Safe Library',
128
- description: 'Use safe-regex library or re2',
129
- severity: 'LOW',
130
- fix: 'import { isSafe } from "safe-regex"; if (isSafe(pattern)) ...',
131
- documentationLink: 'https://github.com/substack/safe-regex',
132
- }),
133
- addTimeout: formatLLMMessage({
134
- icon: MessageIcons.INFO,
135
- issueName: 'Add Timeout',
136
- description: 'Add timeout to regex operations',
137
- severity: 'LOW',
138
- fix: 'Use timeout wrapper for regex operations',
139
- documentationLink: 'https://owasp.org/www-community/attacks/Regular_expression_Denial_of_Service_-_ReDoS',
140
- }),
141
- escapeUserInput: formatLLMMessage({
142
- icon: MessageIcons.INFO,
143
- issueName: 'Escape Input',
144
- description: 'Escape special regex characters',
145
- severity: 'LOW',
146
- fix: 'input.replace(/[.*+?^${}()|[\\]\\\\]/g, "\\\\$&")',
147
- documentationLink: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions#escaping',
148
- })
149
- },
150
- schema: [
151
- {
152
- type: 'object',
153
- properties: {
154
- allowLiterals: {
155
- type: 'boolean',
156
- default: false,
157
- description: 'Allow literal string regex patterns'
158
- },
159
- additionalPatterns: {
160
- type: 'array',
161
- items: { type: 'string' },
162
- default: [],
163
- description: 'Additional RegExp creation patterns to check'
164
- },
165
- maxPatternLength: {
166
- type: 'number',
167
- default: 100,
168
- minimum: 1,
169
- description: 'Maximum allowed pattern length for dynamic regex'
170
- }
171
- },
172
- additionalProperties: false,
173
- },
174
- ],
175
- },
176
- defaultOptions: [
177
- {
178
- allowLiterals: false,
179
- additionalPatterns: [],
180
- maxPatternLength: 100
181
- },
182
- ],
183
- create(context: TSESLint.RuleContext<MessageIds, RuleOptions>) {
184
- const options = context.options[0] || {};
185
- const {
186
- allowLiterals = false,
187
- maxPatternLength = 100
188
-
189
- }: Options = options || {};
190
-
191
- /**
192
- * Check if a node is a literal string (potentially safe)
193
- * Includes template literals without expressions
194
- */
195
- const isLiteralString = (node: TSESTree.Node): boolean => {
196
- if (node.type === 'Literal' && typeof node.value === 'string') {
197
- return true;
198
- }
199
- // Template literals without expressions are also static/safe
200
- if (node.type === 'TemplateLiteral' && node.expressions.length === 0) {
201
- return true;
202
- }
203
- return false;
204
- };
205
-
206
- /**
207
- * Check if a regex pattern contains dangerous ReDoS patterns
208
- * Only flag truly dangerous patterns like nested quantifiers: (a+)+, (a*)*
209
- */
210
- const hasReDoSPatterns = (pattern: string): boolean => {
211
- // Detect truly dangerous nested quantifier patterns that cause exponential backtracking
212
- // Pattern like (a+)+, (a*)+, (a+)*, (a*)*, ([a-z]+)+
213
- const nestedQuantifierPatterns = [
214
- /\([^)]*[+*]\)[+*]/, // (something+)+ or (something*)* patterns
215
- /\([^)]*[+*]\)\{[0-9,]+\}/, // (something+){n,m} patterns
216
- ];
217
-
218
- for (const dangerousPattern of nestedQuantifierPatterns) {
219
- if (dangerousPattern.test(pattern)) {
220
- return true;
221
- }
222
- }
223
-
224
- return false;
225
- };
226
-
227
- /**
228
- * Extract regex pattern from RegExp construction
229
- */
230
- const extractPattern = (node: TSESTree.CallExpression | TSESTree.NewExpression): {
231
- pattern: string;
232
- patternNode: TSESTree.Node | null;
233
- constructor: string;
234
- isDynamic: boolean;
235
- length: number;
236
- } => {
237
- const sourceCode = context.sourceCode || context.sourceCode;
238
-
239
- // Determine constructor type
240
- let constructor = 'RegExp';
241
- if (node.type === 'NewExpression' && node.callee.type === 'Identifier') {
242
- constructor = `new ${node.callee.name}`;
243
- }
244
-
245
- // First argument is the pattern
246
- const patternNode = node.arguments.length > 0 ? node.arguments[0] : null;
247
- const pattern = patternNode ? sourceCode.getText(patternNode) : '';
248
- const isDynamic = patternNode ? !isLiteralString(patternNode) : false;
249
- const length = patternNode && isLiteralString(patternNode) ?
250
- String((patternNode as TSESTree.Literal).value).length : pattern.length;
251
-
252
- return { pattern, patternNode, constructor, isDynamic, length };
253
- };
254
-
255
- /**
256
- * Detect the specific vulnerability pattern
257
- */
258
- const detectVulnerability = (pattern: string, isDynamic: boolean): RegExpPattern | null => {
259
- // Check for dynamic construction first (highest risk)
260
- if (isDynamic) {
261
- for (const vuln of REGEXP_PATTERNS) {
262
- if (new RegExp(vuln.pattern, 'i').test(pattern)) {
263
- return vuln;
264
- }
265
- }
266
- // Generic dynamic RegExp construction
267
- return {
268
- pattern: 'dynamic',
269
- dangerous: true,
270
- vulnerability: 'redos',
271
- safeAlternative: 'Pre-defined RegExp constants',
272
- example: {
273
- bad: pattern,
274
- good: 'const PATTERNS = { email: /^[a-zA-Z0-9]+$/ }; PATTERNS[type]'
275
- },
276
- effort: '10-15 minutes',
277
- riskLevel: 'high'
278
- };
279
- }
280
-
281
- // Check for ReDoS patterns in literal regex
282
- if (hasReDoSPatterns(pattern)) {
283
- return {
284
- pattern: 'redos-literal',
285
- dangerous: true,
286
- vulnerability: 'redos',
287
- safeAlternative: 'Restructure regex to avoid nested quantifiers',
288
- example: {
289
- bad: pattern,
290
- good: pattern.replace(/(a+)\+/g, '$1') // Simplified example
291
- },
292
- effort: '20-30 minutes',
293
- riskLevel: 'high'
294
- };
295
- }
296
-
297
- return null;
298
- };
299
-
300
- /**
301
- * Generate refactoring steps based on the vulnerability
302
- */
303
- const generateRefactoringSteps = (vulnerability: RegExpPattern): string => {
304
- if (vulnerability.pattern === 'dynamic') {
305
- return [
306
- ' 1. Create a whitelist of allowed regex patterns',
307
- ' 2. Use object lookup: PATTERNS[userChoice]',
308
- ' 3. If dynamic needed: escape input with regex escaping function',
309
- ' 4. Add pattern length validation',
310
- ' 5. Consider using a safe regex library'
311
- ].join('\n');
312
- }
313
-
314
- if (vulnerability.pattern === 'redos-literal') {
315
- return [
316
- ' 1. Identify nested quantifiers (*+, ++, ?+)',
317
- ' 2. Restructure regex to avoid exponential backtracking',
318
- ' 3. Use atomic groups if supported: (?>...)',
319
- ' 4. Test regex performance with long inputs',
320
- ' 5. Consider alternatives like string methods'
321
- ].join('\n');
322
- }
323
-
324
- switch (vulnerability.vulnerability) {
325
- case 'redos':
326
- return [
327
- ' 1. Avoid nested quantifiers and backreferences',
328
- ' 2. Use possessive quantifiers: *+, ++, ?+',
329
- ' 3. Restructure regex to be more specific',
330
- ' 4. Test with potentially malicious inputs',
331
- ' 5. Consider safe-regex library validation'
332
- ].join('\n');
333
-
334
- case 'injection':
335
- return [
336
- ' 1. Escape user input before RegExp construction',
337
- ' 2. Use RegExp.escape() if available',
338
- ' 3. Validate input against allowed character sets',
339
- ' 4. Add length limits to prevent oversized patterns',
340
- ' 5. Use static patterns when possible'
341
- ].join('\n');
342
-
343
- default:
344
- return [
345
- ' 1. Identify the specific regex use case',
346
- ' 2. Choose appropriate safe alternative',
347
- ' 3. Add input validation and escaping',
348
- ' 4. Test thoroughly with edge cases',
349
- ' 5. Monitor performance in production'
350
- ].join('\n');
351
- }
352
- };
353
-
354
- /**
355
- * Determine overall risk level
356
- */
357
- const determineRiskLevel = (vulnerability: RegExpPattern, pattern: string): string => {
358
- if (vulnerability.riskLevel === 'critical' || hasReDoSPatterns(pattern)) {
359
- return 'CRITICAL';
360
- }
361
-
362
- if (vulnerability.riskLevel === 'high') {
363
- return 'HIGH';
364
- }
365
-
366
- return 'MEDIUM';
367
- };
368
-
369
- /**
370
- * Check RegExp constructor calls for vulnerabilities
371
- */
372
- const checkRegExpCall = (node: TSESTree.CallExpression | TSESTree.NewExpression) => {
373
- // Check for RegExp constructor calls
374
- const isRegExpCall = node.callee.type === 'Identifier' && node.callee.name === 'RegExp';
375
- const isNewRegExp = node.type === 'NewExpression' && node.callee.type === 'Identifier' && node.callee.name === 'RegExp';
376
-
377
- if (!isRegExpCall && !isNewRegExp) {
378
- return;
379
- }
380
-
381
- const { pattern, patternNode, isDynamic, length } = extractPattern(node);
382
-
383
- // Allow literals if configured and pattern is reasonable length
384
- if (allowLiterals && patternNode && isLiteralString(patternNode) && length <= maxPatternLength) {
385
- // Still check for ReDoS patterns even in literals
386
- if (!hasReDoSPatterns(pattern)) {
387
- return;
388
- }
389
- }
390
-
391
- const vulnerability = detectVulnerability(pattern, isDynamic);
392
-
393
- // If no specific vulnerability detected but it's dynamic, still warn
394
- const effectiveVulnerability = vulnerability || (isDynamic ? {
395
- pattern: 'dynamic',
396
- dangerous: true,
397
- vulnerability: 'redos' as const,
398
- safeAlternative: 'Use static RegExp patterns',
399
- example: {
400
- bad: pattern,
401
- good: '/^safe-pattern$/'
402
- },
403
- effort: '10-15 minutes',
404
- riskLevel: 'medium' as const
405
- } : null);
406
-
407
- if (!effectiveVulnerability) {
408
- return;
409
- }
410
-
411
- const riskLevel = determineRiskLevel(effectiveVulnerability, pattern);
412
- const steps = generateRefactoringSteps(effectiveVulnerability);
413
-
414
- context.report({
415
- node,
416
- messageId: 'regexpReDoS',
417
- data: {
418
- pattern: pattern.substring(0, 30) + (pattern.length > 30 ? '...' : ''),
419
- riskLevel,
420
- vulnerability: effectiveVulnerability.vulnerability,
421
- safeAlternative: effectiveVulnerability.safeAlternative,
422
- steps,
423
- effort: effectiveVulnerability.effort
424
- },
425
- suggest: [
426
- {
427
- messageId: 'useStaticRegex',
428
- fix: () => null
429
- },
430
- {
431
- messageId: 'validateInput',
432
- fix: () => null
433
- },
434
- {
435
- messageId: 'useRegexLibrary',
436
- fix: () => null
437
- },
438
- {
439
- messageId: 'addTimeout',
440
- fix: () => null
441
- },
442
- {
443
- messageId: 'escapeUserInput',
444
- fix: () => null
445
- }
446
- ]
447
- });
448
- };
449
-
450
- /**
451
- * Check literal regex patterns for ReDoS vulnerabilities
452
- */
453
- const checkLiteralRegExp = (node: TSESTree.Node) => {
454
- if (!isRegExpLiteral(node)) {
455
- return;
456
- }
457
-
458
- const pattern = node.regex.pattern;
459
-
460
- // Check for ReDoS patterns
461
- if (hasReDoSPatterns(pattern)) {
462
- const vulnerability = detectVulnerability(pattern, false);
463
-
464
- if (vulnerability) {
465
- const riskLevel = determineRiskLevel(vulnerability, pattern);
466
- const steps = generateRefactoringSteps(vulnerability);
467
-
468
- context.report({
469
- node,
470
- messageId: 'regexpReDoS',
471
- data: {
472
- pattern: pattern.substring(0, 30) + (pattern.length > 30 ? '...' : ''),
473
- riskLevel,
474
- vulnerability: vulnerability.vulnerability,
475
- safeAlternative: vulnerability.safeAlternative,
476
- steps,
477
- effort: vulnerability.effort
478
- }
479
- });
480
- }
481
- }
482
- };
483
-
484
- return {
485
- CallExpression: checkRegExpCall,
486
- NewExpression: checkRegExpCall,
487
- Literal: checkLiteralRegExp
488
- };
489
- },
490
- });