eslint-plugin-secure-coding 2.3.2 → 2.3.3

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 (361) hide show
  1. package/README.md +1 -0
  2. package/package.json +3 -10
  3. package/src/index.ts +605 -0
  4. package/src/rules/__tests__/integration-demo.test.ts +290 -0
  5. package/src/rules/__tests__/integration-llm.test.ts +89 -0
  6. package/src/rules/database-injection/database-injection.test.ts +456 -0
  7. package/src/rules/database-injection/index.ts +488 -0
  8. package/src/rules/detect-child-process/detect-child-process.test.ts +207 -0
  9. package/src/rules/detect-child-process/index.ts +634 -0
  10. package/src/rules/detect-eval-with-expression/detect-eval-with-expression.test.ts +416 -0
  11. package/src/rules/detect-eval-with-expression/index.ts +463 -0
  12. package/src/rules/detect-mixed-content/detect-mixed-content.test.ts +28 -0
  13. package/src/rules/detect-mixed-content/index.ts +52 -0
  14. package/src/rules/detect-non-literal-fs-filename/detect-non-literal-fs-filename.test.ts +269 -0
  15. package/src/rules/detect-non-literal-fs-filename/index.ts +551 -0
  16. package/src/rules/detect-non-literal-regexp/detect-non-literal-regexp.test.ts +189 -0
  17. package/src/rules/detect-non-literal-regexp/index.ts +490 -0
  18. package/src/rules/detect-object-injection/detect-object-injection.test.ts +440 -0
  19. package/src/rules/detect-object-injection/index.ts +674 -0
  20. package/src/rules/detect-suspicious-dependencies/detect-suspicious-dependencies.test.ts +32 -0
  21. package/src/rules/detect-suspicious-dependencies/index.ts +84 -0
  22. package/src/rules/detect-weak-password-validation/detect-weak-password-validation.test.ts +31 -0
  23. package/src/rules/detect-weak-password-validation/index.ts +68 -0
  24. package/src/rules/no-allow-arbitrary-loads/index.ts +54 -0
  25. package/src/rules/no-allow-arbitrary-loads/no-allow-arbitrary-loads.test.ts +28 -0
  26. package/src/rules/no-arbitrary-file-access/index.ts +238 -0
  27. package/src/rules/no-arbitrary-file-access/no-arbitrary-file-access.test.ts +119 -0
  28. package/src/rules/no-buffer-overread/index.ts +724 -0
  29. package/src/rules/no-buffer-overread/no-buffer-overread.test.ts +313 -0
  30. package/src/rules/no-clickjacking/index.ts +481 -0
  31. package/src/rules/no-clickjacking/no-clickjacking.test.ts +253 -0
  32. package/src/rules/no-client-side-auth-logic/index.ts +81 -0
  33. package/src/rules/no-client-side-auth-logic/no-client-side-auth-logic.test.ts +33 -0
  34. package/src/rules/no-credentials-in-query-params/index.ts +69 -0
  35. package/src/rules/no-credentials-in-query-params/no-credentials-in-query-params.test.ts +33 -0
  36. package/src/rules/no-credentials-in-storage-api/index.ts +64 -0
  37. package/src/rules/no-credentials-in-storage-api/no-credentials-in-storage-api.test.ts +31 -0
  38. package/src/rules/no-data-in-temp-storage/index.ts +75 -0
  39. package/src/rules/no-data-in-temp-storage/no-data-in-temp-storage.test.ts +33 -0
  40. package/src/rules/no-debug-code-in-production/index.ts +59 -0
  41. package/src/rules/no-debug-code-in-production/no-debug-code-in-production.test.ts +26 -0
  42. package/src/rules/no-directive-injection/index.ts +551 -0
  43. package/src/rules/no-directive-injection/no-directive-injection.test.ts +305 -0
  44. package/src/rules/no-disabled-certificate-validation/index.ts +72 -0
  45. package/src/rules/no-disabled-certificate-validation/no-disabled-certificate-validation.test.ts +33 -0
  46. package/src/rules/no-document-cookie/index.ts +113 -0
  47. package/src/rules/no-document-cookie/no-document-cookie.test.ts +382 -0
  48. package/src/rules/no-dynamic-dependency-loading/index.ts +60 -0
  49. package/src/rules/no-dynamic-dependency-loading/no-dynamic-dependency-loading.test.ts +27 -0
  50. package/src/rules/no-electron-security-issues/index.ts +504 -0
  51. package/src/rules/no-electron-security-issues/no-electron-security-issues.test.ts +324 -0
  52. package/src/rules/no-exposed-debug-endpoints/index.ts +73 -0
  53. package/src/rules/no-exposed-debug-endpoints/no-exposed-debug-endpoints.test.ts +40 -0
  54. package/src/rules/no-exposed-sensitive-data/index.ts +428 -0
  55. package/src/rules/no-exposed-sensitive-data/no-exposed-sensitive-data.test.ts +75 -0
  56. package/src/rules/no-format-string-injection/index.ts +801 -0
  57. package/src/rules/no-format-string-injection/no-format-string-injection.test.ts +437 -0
  58. package/src/rules/no-graphql-injection/index.ts +508 -0
  59. package/src/rules/no-graphql-injection/no-graphql-injection.test.ts +371 -0
  60. package/src/rules/no-hardcoded-credentials/index.ts +478 -0
  61. package/src/rules/no-hardcoded-credentials/no-hardcoded-credentials.test.ts +639 -0
  62. package/src/rules/no-hardcoded-session-tokens/index.ts +69 -0
  63. package/src/rules/no-hardcoded-session-tokens/no-hardcoded-session-tokens.test.ts +42 -0
  64. package/src/rules/no-http-urls/index.ts +131 -0
  65. package/src/rules/no-http-urls/no-http-urls.test.ts +60 -0
  66. package/src/rules/no-improper-sanitization/index.ts +502 -0
  67. package/src/rules/no-improper-sanitization/no-improper-sanitization.test.ts +156 -0
  68. package/src/rules/no-improper-type-validation/index.ts +572 -0
  69. package/src/rules/no-improper-type-validation/no-improper-type-validation.test.ts +372 -0
  70. package/src/rules/no-insecure-comparison/index.ts +232 -0
  71. package/src/rules/no-insecure-comparison/no-insecure-comparison.test.ts +218 -0
  72. package/src/rules/no-insecure-cookie-settings/index.ts +391 -0
  73. package/src/rules/no-insecure-cookie-settings/no-insecure-cookie-settings.test.ts +409 -0
  74. package/src/rules/no-insecure-jwt/index.ts +467 -0
  75. package/src/rules/no-insecure-jwt/no-insecure-jwt.test.ts +259 -0
  76. package/src/rules/no-insecure-redirects/index.ts +267 -0
  77. package/src/rules/no-insecure-redirects/no-insecure-redirects.test.ts +108 -0
  78. package/src/rules/no-insecure-websocket/index.ts +72 -0
  79. package/src/rules/no-insecure-websocket/no-insecure-websocket.test.ts +42 -0
  80. package/src/rules/no-insufficient-postmessage-validation/index.ts +497 -0
  81. package/src/rules/no-insufficient-postmessage-validation/no-insufficient-postmessage-validation.test.ts +360 -0
  82. package/src/rules/no-insufficient-random/index.ts +288 -0
  83. package/src/rules/no-insufficient-random/no-insufficient-random.test.ts +246 -0
  84. package/src/rules/no-ldap-injection/index.ts +547 -0
  85. package/src/rules/no-ldap-injection/no-ldap-injection.test.ts +317 -0
  86. package/src/rules/no-missing-authentication/index.ts +408 -0
  87. package/src/rules/no-missing-authentication/no-missing-authentication.test.ts +350 -0
  88. package/src/rules/no-missing-cors-check/index.ts +453 -0
  89. package/src/rules/no-missing-cors-check/no-missing-cors-check.test.ts +392 -0
  90. package/src/rules/no-missing-csrf-protection/index.ts +229 -0
  91. package/src/rules/no-missing-csrf-protection/no-missing-csrf-protection.test.ts +222 -0
  92. package/src/rules/no-missing-security-headers/index.ts +266 -0
  93. package/src/rules/no-missing-security-headers/no-missing-security-headers.test.ts +98 -0
  94. package/src/rules/no-password-in-url/index.ts +64 -0
  95. package/src/rules/no-password-in-url/no-password-in-url.test.ts +27 -0
  96. package/src/rules/no-permissive-cors/index.ts +78 -0
  97. package/src/rules/no-permissive-cors/no-permissive-cors.test.ts +28 -0
  98. package/src/rules/no-pii-in-logs/index.ts +83 -0
  99. package/src/rules/no-pii-in-logs/no-pii-in-logs.test.ts +26 -0
  100. package/src/rules/no-postmessage-origin-wildcard/index.ts +67 -0
  101. package/src/rules/no-postmessage-origin-wildcard/no-postmessage-origin-wildcard.test.ts +27 -0
  102. package/src/rules/no-privilege-escalation/index.ts +403 -0
  103. package/src/rules/no-privilege-escalation/no-privilege-escalation.test.ts +306 -0
  104. package/src/rules/no-redos-vulnerable-regex/index.ts +379 -0
  105. package/src/rules/no-redos-vulnerable-regex/no-redos-vulnerable-regex.test.ts +83 -0
  106. package/src/rules/no-sensitive-data-exposure/index.ts +294 -0
  107. package/src/rules/no-sensitive-data-exposure/no-sensitive-data-exposure.test.ts +262 -0
  108. package/src/rules/no-sensitive-data-in-analytics/index.ts +73 -0
  109. package/src/rules/no-sensitive-data-in-analytics/no-sensitive-data-in-analytics.test.ts +42 -0
  110. package/src/rules/no-sensitive-data-in-cache/index.ts +59 -0
  111. package/src/rules/no-sensitive-data-in-cache/no-sensitive-data-in-cache.test.ts +32 -0
  112. package/src/rules/no-sql-injection/index.ts +424 -0
  113. package/src/rules/no-sql-injection/no-sql-injection.test.ts +303 -0
  114. package/src/rules/no-timing-attack/index.ts +552 -0
  115. package/src/rules/no-timing-attack/no-timing-attack.test.ts +348 -0
  116. package/src/rules/no-toctou-vulnerability/index.ts +250 -0
  117. package/src/rules/no-toctou-vulnerability/no-toctou-vulnerability.test.ts +60 -0
  118. package/src/rules/no-tracking-without-consent/index.ts +78 -0
  119. package/src/rules/no-tracking-without-consent/no-tracking-without-consent.test.ts +34 -0
  120. package/src/rules/no-unchecked-loop-condition/index.ts +781 -0
  121. package/src/rules/no-unchecked-loop-condition/no-unchecked-loop-condition.test.ts +459 -0
  122. package/src/rules/no-unencrypted-local-storage/index.ts +73 -0
  123. package/src/rules/no-unencrypted-local-storage/no-unencrypted-local-storage.test.ts +41 -0
  124. package/src/rules/no-unencrypted-transmission/index.ts +296 -0
  125. package/src/rules/no-unencrypted-transmission/no-unencrypted-transmission.test.ts +287 -0
  126. package/src/rules/no-unescaped-url-parameter/index.ts +424 -0
  127. package/src/rules/no-unescaped-url-parameter/no-unescaped-url-parameter.test.ts +263 -0
  128. package/src/rules/no-unlimited-resource-allocation/index.ts +767 -0
  129. package/src/rules/no-unlimited-resource-allocation/no-unlimited-resource-allocation.test.ts +544 -0
  130. package/src/rules/no-unsafe-deserialization/index.ts +593 -0
  131. package/src/rules/no-unsafe-deserialization/no-unsafe-deserialization.test.ts +310 -0
  132. package/src/rules/no-unsafe-dynamic-require/index.ts +125 -0
  133. package/src/rules/no-unsafe-dynamic-require/no-unsafe-dynamic-require.test.ts +151 -0
  134. package/src/rules/no-unsafe-regex-construction/index.ts +370 -0
  135. package/src/rules/no-unsafe-regex-construction/no-unsafe-regex-construction.test.ts +181 -0
  136. package/src/rules/no-unsanitized-html/index.ts +400 -0
  137. package/src/rules/no-unsanitized-html/no-unsanitized-html.test.ts +488 -0
  138. package/src/rules/no-unvalidated-deeplinks/index.ts +73 -0
  139. package/src/rules/no-unvalidated-deeplinks/no-unvalidated-deeplinks.test.ts +29 -0
  140. package/src/rules/no-unvalidated-user-input/index.ts +498 -0
  141. package/src/rules/no-unvalidated-user-input/no-unvalidated-user-input.test.ts +463 -0
  142. package/src/rules/no-verbose-error-messages/index.ts +83 -0
  143. package/src/rules/no-verbose-error-messages/no-verbose-error-messages.test.ts +34 -0
  144. package/src/rules/no-weak-crypto/index.ts +447 -0
  145. package/src/rules/no-weak-crypto/no-weak-crypto.test.ts +297 -0
  146. package/src/rules/no-weak-password-recovery/index.ts +509 -0
  147. package/src/rules/no-weak-password-recovery/no-weak-password-recovery.test.ts +184 -0
  148. package/src/rules/no-xpath-injection/index.ts +596 -0
  149. package/src/rules/no-xpath-injection/no-xpath-injection.test.ts +405 -0
  150. package/src/rules/no-xxe-injection/index.ts +342 -0
  151. package/src/rules/no-xxe-injection/no-xxe-injection.test.ts +122 -0
  152. package/src/rules/no-zip-slip/index.ts +526 -0
  153. package/src/rules/no-zip-slip/no-zip-slip.test.ts +305 -0
  154. package/src/rules/require-backend-authorization/index.ts +71 -0
  155. package/src/rules/require-backend-authorization/require-backend-authorization.test.ts +31 -0
  156. package/src/rules/require-code-minification/index.ts +54 -0
  157. package/src/rules/require-code-minification/require-code-minification.test.ts +30 -0
  158. package/src/rules/require-csp-headers/index.ts +74 -0
  159. package/src/rules/require-csp-headers/require-csp-headers.test.ts +34 -0
  160. package/src/rules/require-data-minimization/index.ts +65 -0
  161. package/src/rules/require-data-minimization/require-data-minimization.test.ts +31 -0
  162. package/src/rules/require-dependency-integrity/index.ts +78 -0
  163. package/src/rules/require-dependency-integrity/require-dependency-integrity.test.ts +44 -0
  164. package/src/rules/require-https-only/index.ts +75 -0
  165. package/src/rules/require-https-only/require-https-only.test.ts +26 -0
  166. package/src/rules/require-mime-type-validation/index.ts +77 -0
  167. package/src/rules/require-mime-type-validation/require-mime-type-validation.test.ts +32 -0
  168. package/src/rules/require-network-timeout/index.ts +58 -0
  169. package/src/rules/require-network-timeout/require-network-timeout.test.ts +26 -0
  170. package/src/rules/require-package-lock/index.ts +75 -0
  171. package/src/rules/require-package-lock/require-package-lock.test.ts +27 -0
  172. package/src/rules/require-secure-credential-storage/index.ts +60 -0
  173. package/src/rules/require-secure-credential-storage/require-secure-credential-storage.test.ts +26 -0
  174. package/src/rules/require-secure-defaults/index.ts +54 -0
  175. package/src/rules/require-secure-defaults/require-secure-defaults.test.ts +26 -0
  176. package/src/rules/require-secure-deletion/index.ts +52 -0
  177. package/src/rules/require-secure-deletion/require-secure-deletion.test.ts +29 -0
  178. package/src/rules/require-storage-encryption/index.ts +60 -0
  179. package/src/rules/require-storage-encryption/require-storage-encryption.test.ts +26 -0
  180. package/src/rules/require-url-validation/index.ts +85 -0
  181. package/src/rules/require-url-validation/require-url-validation.test.ts +32 -0
  182. package/src/types/{index.d.ts → index.ts} +157 -53
  183. package/src/index.d.ts +0 -32
  184. package/src/index.js +0 -465
  185. package/src/rules/database-injection/index.d.ts +0 -13
  186. package/src/rules/database-injection/index.js +0 -406
  187. package/src/rules/detect-child-process/index.d.ts +0 -11
  188. package/src/rules/detect-child-process/index.js +0 -529
  189. package/src/rules/detect-eval-with-expression/index.d.ts +0 -9
  190. package/src/rules/detect-eval-with-expression/index.js +0 -392
  191. package/src/rules/detect-mixed-content/index.d.ts +0 -8
  192. package/src/rules/detect-mixed-content/index.js +0 -44
  193. package/src/rules/detect-non-literal-fs-filename/index.d.ts +0 -7
  194. package/src/rules/detect-non-literal-fs-filename/index.js +0 -454
  195. package/src/rules/detect-non-literal-regexp/index.d.ts +0 -9
  196. package/src/rules/detect-non-literal-regexp/index.js +0 -403
  197. package/src/rules/detect-object-injection/index.d.ts +0 -11
  198. package/src/rules/detect-object-injection/index.js +0 -560
  199. package/src/rules/detect-suspicious-dependencies/index.d.ts +0 -8
  200. package/src/rules/detect-suspicious-dependencies/index.js +0 -71
  201. package/src/rules/detect-weak-password-validation/index.d.ts +0 -6
  202. package/src/rules/detect-weak-password-validation/index.js +0 -58
  203. package/src/rules/no-allow-arbitrary-loads/index.d.ts +0 -8
  204. package/src/rules/no-allow-arbitrary-loads/index.js +0 -47
  205. package/src/rules/no-arbitrary-file-access/index.d.ts +0 -13
  206. package/src/rules/no-arbitrary-file-access/index.js +0 -195
  207. package/src/rules/no-buffer-overread/index.d.ts +0 -29
  208. package/src/rules/no-buffer-overread/index.js +0 -606
  209. package/src/rules/no-clickjacking/index.d.ts +0 -10
  210. package/src/rules/no-clickjacking/index.js +0 -396
  211. package/src/rules/no-client-side-auth-logic/index.d.ts +0 -6
  212. package/src/rules/no-client-side-auth-logic/index.js +0 -69
  213. package/src/rules/no-credentials-in-query-params/index.d.ts +0 -8
  214. package/src/rules/no-credentials-in-query-params/index.js +0 -57
  215. package/src/rules/no-credentials-in-storage-api/index.d.ts +0 -6
  216. package/src/rules/no-credentials-in-storage-api/index.js +0 -54
  217. package/src/rules/no-data-in-temp-storage/index.d.ts +0 -6
  218. package/src/rules/no-data-in-temp-storage/index.js +0 -64
  219. package/src/rules/no-debug-code-in-production/index.d.ts +0 -8
  220. package/src/rules/no-debug-code-in-production/index.js +0 -51
  221. package/src/rules/no-directive-injection/index.d.ts +0 -12
  222. package/src/rules/no-directive-injection/index.js +0 -457
  223. package/src/rules/no-disabled-certificate-validation/index.d.ts +0 -6
  224. package/src/rules/no-disabled-certificate-validation/index.js +0 -61
  225. package/src/rules/no-document-cookie/index.d.ts +0 -5
  226. package/src/rules/no-document-cookie/index.js +0 -89
  227. package/src/rules/no-dynamic-dependency-loading/index.d.ts +0 -8
  228. package/src/rules/no-dynamic-dependency-loading/index.js +0 -51
  229. package/src/rules/no-electron-security-issues/index.d.ts +0 -10
  230. package/src/rules/no-electron-security-issues/index.js +0 -423
  231. package/src/rules/no-exposed-debug-endpoints/index.d.ts +0 -6
  232. package/src/rules/no-exposed-debug-endpoints/index.js +0 -62
  233. package/src/rules/no-exposed-sensitive-data/index.d.ts +0 -11
  234. package/src/rules/no-exposed-sensitive-data/index.js +0 -340
  235. package/src/rules/no-format-string-injection/index.d.ts +0 -17
  236. package/src/rules/no-format-string-injection/index.js +0 -660
  237. package/src/rules/no-graphql-injection/index.d.ts +0 -12
  238. package/src/rules/no-graphql-injection/index.js +0 -411
  239. package/src/rules/no-hardcoded-credentials/index.d.ts +0 -26
  240. package/src/rules/no-hardcoded-credentials/index.js +0 -376
  241. package/src/rules/no-hardcoded-session-tokens/index.d.ts +0 -6
  242. package/src/rules/no-hardcoded-session-tokens/index.js +0 -59
  243. package/src/rules/no-http-urls/index.d.ts +0 -12
  244. package/src/rules/no-http-urls/index.js +0 -114
  245. package/src/rules/no-improper-sanitization/index.d.ts +0 -12
  246. package/src/rules/no-improper-sanitization/index.js +0 -411
  247. package/src/rules/no-improper-type-validation/index.d.ts +0 -10
  248. package/src/rules/no-improper-type-validation/index.js +0 -475
  249. package/src/rules/no-insecure-comparison/index.d.ts +0 -7
  250. package/src/rules/no-insecure-comparison/index.js +0 -193
  251. package/src/rules/no-insecure-cookie-settings/index.d.ts +0 -9
  252. package/src/rules/no-insecure-cookie-settings/index.js +0 -306
  253. package/src/rules/no-insecure-jwt/index.d.ts +0 -10
  254. package/src/rules/no-insecure-jwt/index.js +0 -380
  255. package/src/rules/no-insecure-redirects/index.d.ts +0 -7
  256. package/src/rules/no-insecure-redirects/index.js +0 -216
  257. package/src/rules/no-insecure-websocket/index.d.ts +0 -6
  258. package/src/rules/no-insecure-websocket/index.js +0 -61
  259. package/src/rules/no-insufficient-postmessage-validation/index.d.ts +0 -14
  260. package/src/rules/no-insufficient-postmessage-validation/index.js +0 -392
  261. package/src/rules/no-insufficient-random/index.d.ts +0 -9
  262. package/src/rules/no-insufficient-random/index.js +0 -208
  263. package/src/rules/no-ldap-injection/index.d.ts +0 -10
  264. package/src/rules/no-ldap-injection/index.js +0 -455
  265. package/src/rules/no-missing-authentication/index.d.ts +0 -13
  266. package/src/rules/no-missing-authentication/index.js +0 -333
  267. package/src/rules/no-missing-cors-check/index.d.ts +0 -9
  268. package/src/rules/no-missing-cors-check/index.js +0 -399
  269. package/src/rules/no-missing-csrf-protection/index.d.ts +0 -11
  270. package/src/rules/no-missing-csrf-protection/index.js +0 -180
  271. package/src/rules/no-missing-security-headers/index.d.ts +0 -7
  272. package/src/rules/no-missing-security-headers/index.js +0 -218
  273. package/src/rules/no-password-in-url/index.d.ts +0 -8
  274. package/src/rules/no-password-in-url/index.js +0 -54
  275. package/src/rules/no-permissive-cors/index.d.ts +0 -8
  276. package/src/rules/no-permissive-cors/index.js +0 -65
  277. package/src/rules/no-pii-in-logs/index.d.ts +0 -8
  278. package/src/rules/no-pii-in-logs/index.js +0 -70
  279. package/src/rules/no-postmessage-origin-wildcard/index.d.ts +0 -8
  280. package/src/rules/no-postmessage-origin-wildcard/index.js +0 -56
  281. package/src/rules/no-privilege-escalation/index.d.ts +0 -13
  282. package/src/rules/no-privilege-escalation/index.js +0 -321
  283. package/src/rules/no-redos-vulnerable-regex/index.d.ts +0 -7
  284. package/src/rules/no-redos-vulnerable-regex/index.js +0 -306
  285. package/src/rules/no-sensitive-data-exposure/index.d.ts +0 -11
  286. package/src/rules/no-sensitive-data-exposure/index.js +0 -250
  287. package/src/rules/no-sensitive-data-in-analytics/index.d.ts +0 -8
  288. package/src/rules/no-sensitive-data-in-analytics/index.js +0 -62
  289. package/src/rules/no-sensitive-data-in-cache/index.d.ts +0 -8
  290. package/src/rules/no-sensitive-data-in-cache/index.js +0 -52
  291. package/src/rules/no-sql-injection/index.d.ts +0 -10
  292. package/src/rules/no-sql-injection/index.js +0 -335
  293. package/src/rules/no-timing-attack/index.d.ts +0 -10
  294. package/src/rules/no-timing-attack/index.js +0 -447
  295. package/src/rules/no-toctou-vulnerability/index.d.ts +0 -7
  296. package/src/rules/no-toctou-vulnerability/index.js +0 -208
  297. package/src/rules/no-tracking-without-consent/index.d.ts +0 -6
  298. package/src/rules/no-tracking-without-consent/index.js +0 -67
  299. package/src/rules/no-unchecked-loop-condition/index.d.ts +0 -12
  300. package/src/rules/no-unchecked-loop-condition/index.js +0 -646
  301. package/src/rules/no-unencrypted-local-storage/index.d.ts +0 -8
  302. package/src/rules/no-unencrypted-local-storage/index.js +0 -61
  303. package/src/rules/no-unencrypted-transmission/index.d.ts +0 -11
  304. package/src/rules/no-unencrypted-transmission/index.js +0 -236
  305. package/src/rules/no-unescaped-url-parameter/index.d.ts +0 -9
  306. package/src/rules/no-unescaped-url-parameter/index.js +0 -355
  307. package/src/rules/no-unlimited-resource-allocation/index.d.ts +0 -12
  308. package/src/rules/no-unlimited-resource-allocation/index.js +0 -643
  309. package/src/rules/no-unsafe-deserialization/index.d.ts +0 -10
  310. package/src/rules/no-unsafe-deserialization/index.js +0 -491
  311. package/src/rules/no-unsafe-dynamic-require/index.d.ts +0 -5
  312. package/src/rules/no-unsafe-dynamic-require/index.js +0 -106
  313. package/src/rules/no-unsafe-regex-construction/index.d.ts +0 -9
  314. package/src/rules/no-unsafe-regex-construction/index.js +0 -291
  315. package/src/rules/no-unsanitized-html/index.d.ts +0 -9
  316. package/src/rules/no-unsanitized-html/index.js +0 -335
  317. package/src/rules/no-unvalidated-deeplinks/index.d.ts +0 -6
  318. package/src/rules/no-unvalidated-deeplinks/index.js +0 -62
  319. package/src/rules/no-unvalidated-user-input/index.d.ts +0 -9
  320. package/src/rules/no-unvalidated-user-input/index.js +0 -420
  321. package/src/rules/no-verbose-error-messages/index.d.ts +0 -8
  322. package/src/rules/no-verbose-error-messages/index.js +0 -68
  323. package/src/rules/no-weak-crypto/index.d.ts +0 -11
  324. package/src/rules/no-weak-crypto/index.js +0 -351
  325. package/src/rules/no-weak-password-recovery/index.d.ts +0 -12
  326. package/src/rules/no-weak-password-recovery/index.js +0 -424
  327. package/src/rules/no-xpath-injection/index.d.ts +0 -10
  328. package/src/rules/no-xpath-injection/index.js +0 -487
  329. package/src/rules/no-xxe-injection/index.d.ts +0 -7
  330. package/src/rules/no-xxe-injection/index.js +0 -266
  331. package/src/rules/no-zip-slip/index.d.ts +0 -9
  332. package/src/rules/no-zip-slip/index.js +0 -445
  333. package/src/rules/require-backend-authorization/index.d.ts +0 -6
  334. package/src/rules/require-backend-authorization/index.js +0 -60
  335. package/src/rules/require-code-minification/index.d.ts +0 -8
  336. package/src/rules/require-code-minification/index.js +0 -47
  337. package/src/rules/require-csp-headers/index.d.ts +0 -6
  338. package/src/rules/require-csp-headers/index.js +0 -64
  339. package/src/rules/require-data-minimization/index.d.ts +0 -8
  340. package/src/rules/require-data-minimization/index.js +0 -53
  341. package/src/rules/require-dependency-integrity/index.d.ts +0 -6
  342. package/src/rules/require-dependency-integrity/index.js +0 -64
  343. package/src/rules/require-https-only/index.d.ts +0 -8
  344. package/src/rules/require-https-only/index.js +0 -62
  345. package/src/rules/require-mime-type-validation/index.d.ts +0 -6
  346. package/src/rules/require-mime-type-validation/index.js +0 -66
  347. package/src/rules/require-network-timeout/index.d.ts +0 -8
  348. package/src/rules/require-network-timeout/index.js +0 -50
  349. package/src/rules/require-package-lock/index.d.ts +0 -8
  350. package/src/rules/require-package-lock/index.js +0 -63
  351. package/src/rules/require-secure-credential-storage/index.d.ts +0 -8
  352. package/src/rules/require-secure-credential-storage/index.js +0 -50
  353. package/src/rules/require-secure-defaults/index.d.ts +0 -8
  354. package/src/rules/require-secure-defaults/index.js +0 -47
  355. package/src/rules/require-secure-deletion/index.d.ts +0 -8
  356. package/src/rules/require-secure-deletion/index.js +0 -44
  357. package/src/rules/require-storage-encryption/index.d.ts +0 -8
  358. package/src/rules/require-storage-encryption/index.js +0 -50
  359. package/src/rules/require-url-validation/index.d.ts +0 -6
  360. package/src/rules/require-url-validation/index.js +0 -72
  361. package/src/types/index.js +0 -17
@@ -0,0 +1,767 @@
1
+ /**
2
+ * ESLint Rule: no-unlimited-resource-allocation
3
+ * Detects unlimited resource allocation vulnerabilities (CWE-770)
4
+ *
5
+ * Unlimited resource allocation can cause denial of service by exhausting
6
+ * system resources like memory, file handles, or network connections.
7
+ * This rule detects patterns where resources are allocated without limits.
8
+ *
9
+ * False Positive Reduction:
10
+ * This rule uses security utilities to reduce false positives by detecting:
11
+ * - Safe resource allocation patterns
12
+ * - Proper resource limits
13
+ * - JSDoc annotations (@limited-resource, @safe-allocation)
14
+ * - Resource cleanup patterns
15
+ */
16
+ import type { TSESLint, TSESTree } from '@interlace/eslint-devkit';
17
+ import { createRule } from '@interlace/eslint-devkit';
18
+ import { formatLLMMessage, MessageIcons } from '@interlace/eslint-devkit';
19
+ import {
20
+ createSafetyChecker,
21
+ isInsideLoop,
22
+ isUserInputExpression,
23
+ type SecurityRuleOptions,
24
+ } from '@interlace/eslint-devkit';
25
+
26
+ type MessageIds =
27
+ | 'unlimitedResourceAllocation'
28
+ | 'unlimitedBufferAllocation'
29
+ | 'unlimitedFileOperations'
30
+ | 'unlimitedNetworkConnections'
31
+ | 'unlimitedMemoryAllocation'
32
+ | 'userControlledResourceSize'
33
+ | 'missingResourceLimits'
34
+ | 'resourceAllocationInLoop'
35
+ | 'implementResourceLimits'
36
+ | 'validateResourceSize'
37
+ | 'useResourcePools'
38
+ | 'strategyResourceManagement'
39
+ | 'strategyRateLimiting'
40
+ | 'strategyResourceCleanup';
41
+
42
+ export interface Options extends SecurityRuleOptions {
43
+ /** Maximum allowed resource size for static analysis */
44
+ maxResourceSize?: number;
45
+
46
+ /** Variables that contain user input */
47
+ userInputVariables?: string[];
48
+
49
+ /** Safe resource allocation functions */
50
+ safeResourceFunctions?: string[];
51
+
52
+ /** Require resource validation */
53
+ requireResourceValidation?: boolean;
54
+ }
55
+
56
+ type RuleOptions = [Options?];
57
+
58
+ export const noUnlimitedResourceAllocation = createRule<RuleOptions, MessageIds>({
59
+ name: 'no-unlimited-resource-allocation',
60
+ meta: {
61
+ type: 'problem',
62
+ docs: {
63
+ description: 'Detects unlimited resource allocation that could cause DoS',
64
+ },
65
+ fixable: 'code',
66
+ hasSuggestions: true,
67
+ messages: {
68
+ unlimitedResourceAllocation: formatLLMMessage({
69
+ icon: MessageIcons.SECURITY,
70
+ issueName: 'Unlimited Resource Allocation',
71
+ cwe: 'CWE-770',
72
+ description: 'Resource allocation without limits',
73
+ severity: '{{severity}}',
74
+ fix: '{{safeAlternative}}',
75
+ documentationLink: 'https://cwe.mitre.org/data/definitions/770.html',
76
+ }),
77
+ unlimitedBufferAllocation: formatLLMMessage({
78
+ icon: MessageIcons.SECURITY,
79
+ issueName: 'Unlimited Buffer Allocation',
80
+ cwe: 'CWE-770',
81
+ description: 'Buffer allocated without size limits',
82
+ severity: 'HIGH',
83
+ fix: 'Set maximum buffer size limits',
84
+ documentationLink: 'https://nodejs.org/api/buffer.html',
85
+ }),
86
+ unlimitedFileOperations: formatLLMMessage({
87
+ icon: MessageIcons.SECURITY,
88
+ issueName: 'Unlimited File Operations',
89
+ cwe: 'CWE-770',
90
+ description: 'File operations without size limits',
91
+ severity: 'MEDIUM',
92
+ fix: 'Validate file size before operations',
93
+ documentationLink: 'https://nodejs.org/api/fs.html',
94
+ }),
95
+ unlimitedNetworkConnections: formatLLMMessage({
96
+ icon: MessageIcons.SECURITY,
97
+ issueName: 'Unlimited Network Connections',
98
+ cwe: 'CWE-770',
99
+ description: 'Network connections without limits',
100
+ severity: 'MEDIUM',
101
+ fix: 'Limit concurrent connections',
102
+ documentationLink: 'https://nodejs.org/api/http.html',
103
+ }),
104
+ unlimitedMemoryAllocation: formatLLMMessage({
105
+ icon: MessageIcons.SECURITY,
106
+ issueName: 'Unlimited Memory Allocation',
107
+ cwe: 'CWE-770',
108
+ description: 'Memory allocated without limits',
109
+ severity: 'MEDIUM',
110
+ fix: 'Set memory allocation limits',
111
+ documentationLink: 'https://nodejs.org/api/buffer.html',
112
+ }),
113
+ userControlledResourceSize: formatLLMMessage({
114
+ icon: MessageIcons.SECURITY,
115
+ issueName: 'User Controlled Resource Size',
116
+ cwe: 'CWE-770',
117
+ description: 'Resource size controlled by user input',
118
+ severity: 'HIGH',
119
+ fix: 'Validate and limit user-controlled resource sizes',
120
+ documentationLink: 'https://cwe.mitre.org/data/definitions/770.html',
121
+ }),
122
+ missingResourceLimits: formatLLMMessage({
123
+ icon: MessageIcons.SECURITY,
124
+ issueName: 'Missing Resource Limits',
125
+ cwe: 'CWE-770',
126
+ description: 'Resource allocation lacks proper limits',
127
+ severity: 'MEDIUM',
128
+ fix: 'Implement resource size validation',
129
+ documentationLink: 'https://cwe.mitre.org/data/definitions/770.html',
130
+ }),
131
+ resourceAllocationInLoop: formatLLMMessage({
132
+ icon: MessageIcons.SECURITY,
133
+ issueName: 'Resource Allocation in Loop',
134
+ cwe: 'CWE-770',
135
+ description: 'Resource allocation inside loop without limits',
136
+ severity: 'HIGH',
137
+ fix: 'Move resource allocation outside loop or add iteration limits',
138
+ documentationLink: 'https://cwe.mitre.org/data/definitions/770.html',
139
+ }),
140
+ implementResourceLimits: formatLLMMessage({
141
+ icon: MessageIcons.INFO,
142
+ issueName: 'Implement Resource Limits',
143
+ description: 'Add limits to resource allocation',
144
+ severity: 'LOW',
145
+ fix: 'const limitedSize = Math.min(userSize, MAX_SIZE);',
146
+ documentationLink: 'https://cwe.mitre.org/data/definitions/770.html',
147
+ }),
148
+ validateResourceSize: formatLLMMessage({
149
+ icon: MessageIcons.INFO,
150
+ issueName: 'Validate Resource Size',
151
+ description: 'Validate resource size before allocation',
152
+ severity: 'LOW',
153
+ fix: 'if (size > MAX_SIZE) throw new Error("Size too large");',
154
+ documentationLink: 'https://cwe.mitre.org/data/definitions/770.html',
155
+ }),
156
+ useResourcePools: formatLLMMessage({
157
+ icon: MessageIcons.INFO,
158
+ issueName: 'Use Resource Pools',
159
+ description: 'Use resource pools for better control',
160
+ severity: 'LOW',
161
+ fix: 'Implement connection pooling and resource reuse',
162
+ documentationLink: 'https://en.wikipedia.org/wiki/Object_pool_pattern',
163
+ }),
164
+ strategyResourceManagement: formatLLMMessage({
165
+ icon: MessageIcons.STRATEGY,
166
+ issueName: 'Resource Management Strategy',
167
+ description: 'Implement comprehensive resource management',
168
+ severity: 'LOW',
169
+ fix: 'Use resource pools, limits, and cleanup mechanisms',
170
+ documentationLink: 'https://cwe.mitre.org/data/definitions/770.html',
171
+ }),
172
+ strategyRateLimiting: formatLLMMessage({
173
+ icon: MessageIcons.STRATEGY,
174
+ issueName: 'Rate Limiting Strategy',
175
+ description: 'Implement rate limiting for resource allocation',
176
+ severity: 'LOW',
177
+ fix: 'Use rate limiters to prevent resource exhaustion',
178
+ documentationLink: 'https://en.wikipedia.org/wiki/Rate_limiting',
179
+ }),
180
+ strategyResourceCleanup: formatLLMMessage({
181
+ icon: MessageIcons.STRATEGY,
182
+ issueName: 'Resource Cleanup Strategy',
183
+ description: 'Ensure proper resource cleanup',
184
+ severity: 'LOW',
185
+ fix: 'Implement try-finally blocks and resource disposal',
186
+ documentationLink: 'https://en.wikipedia.org/wiki/Resource_management_(computing)',
187
+ })
188
+ },
189
+ schema: [
190
+ {
191
+ type: 'object',
192
+ properties: {
193
+ maxResourceSize: {
194
+ type: 'number',
195
+ minimum: 1024,
196
+ default: 1048576, // 1MB
197
+ },
198
+ userInputVariables: {
199
+ type: 'array',
200
+ items: { type: 'string' },
201
+ default: ['req', 'request', 'body', 'query', 'params', 'input', 'data'],
202
+ },
203
+ safeResourceFunctions: {
204
+ type: 'array',
205
+ items: { type: 'string' },
206
+ default: ['validateSize', 'checkLimits', 'limitResource', 'safeAlloc'],
207
+ },
208
+ requireResourceValidation: {
209
+ type: 'boolean',
210
+ default: true,
211
+ },
212
+ trustedSanitizers: {
213
+ type: 'array',
214
+ items: { type: 'string' },
215
+ default: [],
216
+ description: 'Additional function names to consider as resource validators',
217
+ },
218
+ trustedAnnotations: {
219
+ type: 'array',
220
+ items: { type: 'string' },
221
+ default: [],
222
+ description: 'Additional JSDoc annotations to consider as safe markers',
223
+ },
224
+ strictMode: {
225
+ type: 'boolean',
226
+ default: false,
227
+ description: 'Disable all false positive detection (strict mode)',
228
+ },
229
+ },
230
+ additionalProperties: false,
231
+ },
232
+ ],
233
+ },
234
+ defaultOptions: [
235
+ {
236
+ maxResourceSize: 1048576, // 1MB
237
+ userInputVariables: ['req', 'request', 'body', 'query', 'params', 'input', 'data'],
238
+ safeResourceFunctions: ['validateSize', 'checkLimits', 'limitResource', 'safeAlloc'],
239
+ requireResourceValidation: true,
240
+ trustedSanitizers: [],
241
+ trustedAnnotations: [],
242
+ strictMode: false,
243
+ },
244
+ ],
245
+ create(context: TSESLint.RuleContext<MessageIds, RuleOptions>) {
246
+ const options = context.options[0] || {};
247
+ const {
248
+ maxResourceSize = 1048576,
249
+ userInputVariables = ['req', 'request', 'body', 'query', 'params', 'input', 'data'],
250
+ safeResourceFunctions = ['validateSize', 'checkLimits', 'limitResource', 'safeAlloc'],
251
+ requireResourceValidation = true,
252
+ trustedSanitizers = [],
253
+ trustedAnnotations = [],
254
+ strictMode = false,
255
+ }: Options = options;
256
+
257
+ const sourceCode = context.sourceCode || context.sourceCode;
258
+ const filename = context.filename || context.getFilename();
259
+
260
+ // Create safety checker for false positive detection
261
+ const safetyChecker = createSafetyChecker({
262
+ trustedSanitizers,
263
+ trustedAnnotations,
264
+ trustedOrmPatterns: [],
265
+ strictMode,
266
+ });
267
+
268
+ /**
269
+ * Check if an expression contains user input - using shared utility
270
+ */
271
+ const isUserInput = (expression: TSESTree.Expression): boolean =>
272
+ isUserInputExpression(expression, sourceCode, userInputVariables);
273
+
274
+ /**
275
+ * Check if resource allocation has size validation
276
+ */
277
+ const hasSizeValidation = (node: TSESTree.CallExpression | TSESTree.NewExpression): boolean => {
278
+ const args = node.arguments;
279
+ if (args.length === 0) {
280
+ return false;
281
+ }
282
+
283
+ // Check if size argument is a validated expression
284
+ const sizeArg = args[0];
285
+ const sizeText = sourceCode.getText(sizeArg);
286
+
287
+ // Look for validation patterns
288
+ return sizeText.includes('Math.min(') ||
289
+ sizeText.includes('Math.max(') ||
290
+ sizeText.includes('Math.clamp(') ||
291
+ safeResourceFunctions.some(func => sizeText.includes(func));
292
+ };
293
+
294
+ /**
295
+ * Estimate resource size from static analysis
296
+ */
297
+ const estimateResourceSize = (sizeExpression: TSESTree.Expression): number | null => {
298
+ if (sizeExpression.type === 'Literal' && typeof sizeExpression.value === 'number') {
299
+ return sizeExpression.value;
300
+ }
301
+
302
+ // Handle binary expressions like 1024 * 1024 * 100
303
+ if (sizeExpression.type === 'BinaryExpression') {
304
+ const left = estimateResourceSize(sizeExpression.left as TSESTree.Expression);
305
+ const right = estimateResourceSize(sizeExpression.right as TSESTree.Expression);
306
+
307
+ if (left !== null && right !== null) {
308
+ switch (sizeExpression.operator) {
309
+ case '*':
310
+ return left * right;
311
+ case '+':
312
+ return left + right;
313
+ case '-':
314
+ return left - right;
315
+ case '/':
316
+ return right !== 0 ? left / right : null;
317
+ default:
318
+ return null;
319
+ }
320
+ }
321
+ }
322
+
323
+ return null;
324
+ };
325
+
326
+ return {
327
+ // Check Buffer allocation
328
+ CallExpression(node: TSESTree.CallExpression) {
329
+ const callee = node.callee;
330
+ const calleeText = sourceCode.getText(callee);
331
+
332
+ // Check for Buffer.alloc(), Buffer.allocUnsafe() or new Buffer()
333
+ const isBufferAlloc =
334
+ callee.type === 'MemberExpression' &&
335
+ callee.object.type === 'Identifier' &&
336
+ callee.object.name === 'Buffer' &&
337
+ callee.property.type === 'Identifier' &&
338
+ (callee.property.name === 'alloc' || callee.property.name === 'allocUnsafe');
339
+
340
+ const isNewBuffer =
341
+ callee.type === 'NewExpression' &&
342
+ callee.callee.type === 'Identifier' &&
343
+ callee.callee.name === 'Buffer';
344
+
345
+ if (isBufferAlloc || isNewBuffer) {
346
+
347
+ const args = node.arguments;
348
+ if (args.length > 0) {
349
+ const sizeArg = args[0];
350
+
351
+ // Check if size comes from user input (but skip if validated)
352
+ if (sizeArg.type !== 'SpreadElement' && isUserInput(sizeArg) && !hasSizeValidation(node)) {
353
+ /* c8 ignore start -- safetyChecker requires JSDoc annotations not testable via RuleTester */
354
+ if (safetyChecker.isSafe(node, context)) {
355
+ return;
356
+ }
357
+ /* c8 ignore stop */
358
+
359
+ context.report({
360
+ node: sizeArg,
361
+ messageId: 'userControlledResourceSize',
362
+ data: {
363
+ filePath: filename,
364
+ line: String(node.loc?.start.line ?? 0),
365
+ },
366
+ });
367
+ return;
368
+ }
369
+
370
+ // Check if size exceeds limits
371
+ const estimatedSize = sizeArg.type === 'SpreadElement' ? null : estimateResourceSize(sizeArg);
372
+ if (estimatedSize && estimatedSize > maxResourceSize) {
373
+ /* c8 ignore start -- safetyChecker requires JSDoc annotations not testable via RuleTester */
374
+ if (safetyChecker.isSafe(node, context)) {
375
+ return;
376
+ }
377
+ /* c8 ignore stop */
378
+
379
+ context.report({
380
+ node: sizeArg,
381
+ messageId: 'unlimitedBufferAllocation',
382
+ data: {
383
+ filePath: filename,
384
+ line: String(node.loc?.start.line ?? 0),
385
+ },
386
+ });
387
+ return;
388
+ }
389
+
390
+ // Check if no size validation present (only for non-literal sizes from user input)
391
+ const isLiteralSize = sizeArg.type === 'Literal' && typeof sizeArg.value === 'number';
392
+ const comesFromUserInput = sizeArg.type !== 'SpreadElement' && isUserInput(sizeArg);
393
+ if (requireResourceValidation && !hasSizeValidation(node) && !isLiteralSize && comesFromUserInput) {
394
+ /* c8 ignore start -- safetyChecker requires JSDoc annotations not testable via RuleTester */
395
+ if (safetyChecker.isSafe(node, context)) {
396
+ return;
397
+ }
398
+ /* c8 ignore stop */
399
+
400
+ context.report({
401
+ node,
402
+ messageId: 'missingResourceLimits',
403
+ data: {
404
+ filePath: filename,
405
+ line: String(node.loc?.start.line ?? 0),
406
+ },
407
+ });
408
+ }
409
+ }
410
+ }
411
+
412
+ // Check for multer configuration without limits
413
+ if (callee.type === 'Identifier' && callee.name === 'multer') {
414
+ const args = node.arguments;
415
+ if (args.length > 0 && args[0].type === 'ObjectExpression') {
416
+ const props = args[0].properties as TSESTree.ObjectLiteralElement[];
417
+
418
+ // Check for valid limits definition
419
+ const hasValidLimits = props.some((prop: TSESTree.ObjectLiteralElement): boolean => {
420
+ if (prop.type !== 'Property' || prop.key.type !== 'Identifier') {
421
+ return false;
422
+ }
423
+
424
+ // Direct fileSize (not standard but maybe used?)
425
+ if (prop.key.name === 'fileSize') return true;
426
+
427
+ // Limits object
428
+ if (prop.key.name === 'limits' && prop.value.type === 'ObjectExpression') {
429
+ return prop.value.properties.some(
430
+ (limitProp: TSESTree.ObjectLiteralElement): limitProp is TSESTree.Property =>
431
+ limitProp.type === 'Property' &&
432
+ limitProp.key.type === 'Identifier' &&
433
+ limitProp.key.name === 'fileSize'
434
+ );
435
+ }
436
+
437
+ return false;
438
+ });
439
+
440
+ if (!hasValidLimits) {
441
+ /* c8 ignore start -- safetyChecker requires JSDoc annotations not testable via RuleTester */
442
+ if (safetyChecker.isSafe(node, context)) {
443
+ return;
444
+ }
445
+ /* c8 ignore stop */
446
+
447
+ context.report({
448
+ node,
449
+ messageId: 'unlimitedFileOperations',
450
+ data: {
451
+ filePath: filename,
452
+ line: String(node.loc?.start.line ?? 0),
453
+ },
454
+ });
455
+ }
456
+ }
457
+ return;
458
+ }
459
+
460
+ // Check for fs operations
461
+ if (callee.type === 'MemberExpression' &&
462
+ callee.object.type === 'Identifier' &&
463
+ callee.object.name === 'fs' &&
464
+ callee.property.type === 'Identifier' &&
465
+ ['readFile', 'writeFile', 'readFileSync', 'writeFileSync'].includes(callee.property.name)) {
466
+
467
+ const args = node.arguments;
468
+ if (args.length > 0) {
469
+ // Check if file path comes from user input (potential for large files)
470
+ const pathArg = args[0];
471
+
472
+ // SAFE: Static path construction with path.join(__dirname, ...literals)
473
+ // This is a common pattern that doesn't involve user input
474
+ if (pathArg.type === 'CallExpression' &&
475
+ pathArg.callee.type === 'MemberExpression' &&
476
+ pathArg.callee.object.type === 'Identifier' &&
477
+ pathArg.callee.object.name === 'path' &&
478
+ pathArg.callee.property.type === 'Identifier' &&
479
+ (pathArg.callee.property.name === 'join' || pathArg.callee.property.name === 'resolve')) {
480
+ // Check if first arg is __dirname and all subsequent args are literals
481
+ const pathArgs = pathArg.arguments;
482
+ if (pathArgs.length > 0 &&
483
+ pathArgs[0].type === 'Identifier' &&
484
+ pathArgs[0].name === '__dirname' &&
485
+ pathArgs.slice(1).every(arg => arg.type === 'Literal')) {
486
+ // Safe: path.join(__dirname, 'static', 'path')
487
+ return;
488
+ }
489
+ }
490
+
491
+ if (pathArg.type !== 'SpreadElement' && isUserInput(pathArg)) {
492
+ /* c8 ignore start -- safetyChecker requires JSDoc annotations not testable via RuleTester */
493
+ if (safetyChecker.isSafe(node, context)) {
494
+ return;
495
+ }
496
+ /* c8 ignore stop */
497
+
498
+ context.report({
499
+ node: pathArg,
500
+ messageId: 'unlimitedFileOperations',
501
+ data: {
502
+ filePath: filename,
503
+ line: String(node.loc?.start.line ?? 0),
504
+ },
505
+ });
506
+ }
507
+ }
508
+ }
509
+
510
+ // Check for Array constructor with user input
511
+ if (callee.type === 'Identifier' && callee.name === 'Array') {
512
+ const args = node.arguments;
513
+ if (args.length === 1) {
514
+ const sizeArg = args[0];
515
+ if (sizeArg.type !== 'SpreadElement' && isUserInput(sizeArg)) {
516
+ /* c8 ignore start -- safetyChecker requires JSDoc annotations not testable via RuleTester */
517
+ if (safetyChecker.isSafe(node, context)) {
518
+ return;
519
+ }
520
+ /* c8 ignore stop */
521
+
522
+ context.report({
523
+ node: sizeArg,
524
+ messageId: 'unlimitedMemoryAllocation',
525
+ data: {
526
+ filePath: filename,
527
+ line: String(node.loc?.start.line ?? 0),
528
+ },
529
+ });
530
+ }
531
+ }
532
+ }
533
+
534
+ // Check for complex resource exhaustion patterns
535
+ /* c8 ignore start -- defensive detectors for rare patterns */
536
+ // ZIP bomb detection - unlimited decompression
537
+ if (calleeText.includes('unzipper') || calleeText.includes('Extract')) {
538
+ // Check for unlimited ZIP extraction
539
+ context.report({
540
+ node,
541
+ messageId: 'unlimitedFileOperations',
542
+ data: {
543
+ filePath: filename,
544
+ line: String(node.loc?.start.line ?? 0),
545
+ },
546
+ });
547
+ }
548
+
549
+ // XML expansion attack detection
550
+ if (calleeText.includes('xml2js') || calleeText.includes('parseString')) {
551
+ context.report({
552
+ node,
553
+ messageId: 'unlimitedMemoryAllocation',
554
+ data: {
555
+ filePath: filename,
556
+ line: String(node.loc?.start.line ?? 0),
557
+ },
558
+ });
559
+ }
560
+
561
+
562
+
563
+ // Check for cache with unlimited growth
564
+ if (calleeText.includes('set') && sourceCode.getText(node).includes('Buffer.alloc')) {
565
+ // Detect cache patterns that allocate buffers without limits
566
+ const args = node.arguments;
567
+ if (args.length >= 2) {
568
+ const valueArg = args[1];
569
+ const valueText = sourceCode.getText(valueArg);
570
+ if (valueText.includes('Buffer.alloc') && valueText.includes('length')) {
571
+ context.report({
572
+ node,
573
+ messageId: 'unlimitedMemoryAllocation',
574
+ data: {
575
+ filePath: filename,
576
+ line: String(node.loc?.start.line ?? 0),
577
+ },
578
+ });
579
+ }
580
+ }
581
+ }
582
+
583
+ // Check for recursive data structure processing
584
+ if (calleeText.includes('map') || calleeText.includes('forEach')) {
585
+ const args = node.arguments;
586
+ if (args.length > 0) {
587
+ const callbackArg = args[0];
588
+ const callbackText = sourceCode.getText(callbackArg);
589
+ // Detect patterns that create arrays from nested object properties
590
+ if (callbackText.includes('Object.keys') && callbackText.includes('map')) {
591
+ context.report({
592
+ node,
593
+ messageId: 'unlimitedMemoryAllocation',
594
+ data: {
595
+ filePath: filename,
596
+ line: String(node.loc?.start.line ?? 0),
597
+ },
598
+ });
599
+ }
600
+ }
601
+ }
602
+ /* c8 ignore stop */
603
+
604
+ // Check for resource allocation inside loops
605
+ if (isInsideLoop(node)) {
606
+ const calleeText = sourceCode.getText(callee);
607
+
608
+ // Check if this allocates resources
609
+ if (calleeText.includes('alloc') ||
610
+ calleeText.includes('Array') ||
611
+ calleeText.includes('Buffer') ||
612
+ calleeText.includes('readFile') ||
613
+ calleeText.includes('writeFile')) {
614
+
615
+ /* c8 ignore start -- safetyChecker requires JSDoc annotations not testable via RuleTester */
616
+ if (safetyChecker.isSafe(node, context)) {
617
+ return;
618
+ }
619
+ /* c8 ignore stop */
620
+
621
+ // Skip if this is an assignment to an array element (pre-allocated pattern)
622
+ const parent = node.parent;
623
+ if (parent && parent.type === 'AssignmentExpression' &&
624
+ parent.left.type === 'MemberExpression' &&
625
+ parent.left.object.type === 'Identifier') {
626
+ // This is assigning to an array element, likely pre-allocated
627
+ return;
628
+ }
629
+
630
+ // Report resourceAllocationInLoop - this can be in addition to user input errors
631
+ context.report({
632
+ node,
633
+ messageId: 'resourceAllocationInLoop',
634
+ data: {
635
+ filePath: filename,
636
+ line: String(node.loc?.start.line ?? 0),
637
+ },
638
+ });
639
+ }
640
+ }
641
+ },
642
+
643
+ // Check new expressions for resource allocation
644
+ NewExpression(node: TSESTree.NewExpression) {
645
+ const callee = node.callee;
646
+
647
+ // Check for new Buffer() with user input
648
+ if (callee.type === 'Identifier' && callee.name === 'Buffer') {
649
+ const args = node.arguments;
650
+ if (args.length > 0) {
651
+ const sizeArg = args[0];
652
+
653
+ // Check if size comes from user input (but skip if validated)
654
+ if (sizeArg.type !== 'SpreadElement' && isUserInput(sizeArg) && !hasSizeValidation(node)) {
655
+ /* c8 ignore start -- safetyChecker requires JSDoc annotations not testable via RuleTester */
656
+ if (safetyChecker.isSafe(node, context)) {
657
+ return;
658
+ }
659
+ /* c8 ignore stop */
660
+
661
+ context.report({
662
+ node: sizeArg,
663
+ messageId: 'userControlledResourceSize',
664
+ data: {
665
+ filePath: filename,
666
+ line: String(node.loc?.start.line ?? 0),
667
+ },
668
+ });
669
+ return;
670
+ }
671
+
672
+ // Check if size exceeds limits
673
+ const estimatedSize = sizeArg.type === 'SpreadElement' ? null : estimateResourceSize(sizeArg);
674
+ if (estimatedSize && estimatedSize > maxResourceSize) {
675
+ /* c8 ignore start -- safetyChecker requires JSDoc annotations not testable via RuleTester */
676
+ if (safetyChecker.isSafe(node, context)) {
677
+ return;
678
+ }
679
+ /* c8 ignore stop */
680
+
681
+ context.report({
682
+ node: sizeArg,
683
+ messageId: 'unlimitedBufferAllocation',
684
+ data: {
685
+ filePath: filename,
686
+ line: String(node.loc?.start.line ?? 0),
687
+ },
688
+ });
689
+ return;
690
+ }
691
+
692
+ // Check if no size validation present (only for non-literal sizes from user input)
693
+ const isLiteralSize = sizeArg.type === 'Literal' && typeof sizeArg.value === 'number';
694
+ const comesFromUserInput = sizeArg.type !== 'SpreadElement' && isUserInput(sizeArg);
695
+ if (requireResourceValidation && !hasSizeValidation(node) && !isLiteralSize && comesFromUserInput) {
696
+ /* c8 ignore start -- safetyChecker requires JSDoc annotations not testable via RuleTester */
697
+ if (safetyChecker.isSafe(node, context)) {
698
+ return;
699
+ }
700
+ /* c8 ignore stop */
701
+
702
+ context.report({
703
+ node,
704
+ messageId: 'missingResourceLimits',
705
+ data: {
706
+ filePath: filename,
707
+ line: String(node.loc?.start.line ?? 0),
708
+ },
709
+ });
710
+ }
711
+ }
712
+ }
713
+
714
+ // Check for new Array() with user input
715
+ if (callee.type === 'Identifier' && callee.name === 'Array') {
716
+ const args = node.arguments;
717
+ if (args.length === 1) {
718
+ const sizeArg = args[0];
719
+ if (sizeArg.type !== 'SpreadElement' && isUserInput(sizeArg)) {
720
+ /* c8 ignore start -- safetyChecker requires JSDoc annotations not testable via RuleTester */
721
+ if (safetyChecker.isSafe(node, context)) {
722
+ return;
723
+ }
724
+ /* c8 ignore stop */
725
+
726
+ context.report({
727
+ node: sizeArg,
728
+ messageId: 'unlimitedMemoryAllocation',
729
+ data: {
730
+ filePath: filename,
731
+ line: String(node.loc?.start.line ?? 0),
732
+ },
733
+ });
734
+ }
735
+ }
736
+ }
737
+
738
+ // Check for resource allocation inside loops
739
+ if (isInsideLoop(node)) {
740
+ const calleeText = sourceCode.getText(callee);
741
+
742
+ // Check if this allocates resources
743
+ if (calleeText.includes('Buffer') ||
744
+ calleeText.includes('Array') ||
745
+ calleeText.includes('Map') ||
746
+ calleeText.includes('Set')) {
747
+
748
+ /* c8 ignore start -- safetyChecker requires JSDoc annotations not testable via RuleTester */
749
+ if (safetyChecker.isSafe(node, context)) {
750
+ return;
751
+ }
752
+ /* c8 ignore stop */
753
+
754
+ context.report({
755
+ node,
756
+ messageId: 'resourceAllocationInLoop',
757
+ data: {
758
+ filePath: filename,
759
+ line: String(node.loc?.start.line ?? 0),
760
+ },
761
+ });
762
+ }
763
+ }
764
+ }
765
+ };
766
+ },
767
+ });