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
@@ -1,399 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.noMissingCorsCheck = void 0;
4
- const eslint_devkit_1 = require("@interlace/eslint-devkit");
5
- const eslint_devkit_2 = require("@interlace/eslint-devkit");
6
- /**
7
- * Check if a string matches any ignore pattern
8
- */
9
- function matchesIgnorePattern(text, ignorePatterns) {
10
- return ignorePatterns.some(pattern => {
11
- try {
12
- const regex = new RegExp(pattern, 'i');
13
- return regex.test(text);
14
- }
15
- catch {
16
- return false;
17
- }
18
- });
19
- }
20
- exports.noMissingCorsCheck = (0, eslint_devkit_2.createRule)({
21
- name: 'no-missing-cors-check',
22
- meta: {
23
- type: 'problem',
24
- deprecated: true,
25
- replacedBy: ['@see eslint-plugin-express-security/no-permissive-cors'],
26
- docs: {
27
- description: 'Detects missing CORS validation (wildcard CORS, missing origin check)',
28
- },
29
- hasSuggestions: true,
30
- messages: {
31
- missingCorsCheck: (0, eslint_devkit_1.formatLLMMessage)({
32
- icon: eslint_devkit_1.MessageIcons.SECURITY,
33
- issueName: 'Missing CORS Validation',
34
- cwe: 'CWE-346',
35
- description: 'Missing CORS validation detected: {{issue}}',
36
- severity: 'HIGH',
37
- fix: '{{safeAlternative}}',
38
- documentationLink: 'https://cwe.mitre.org/data/definitions/346.html',
39
- }),
40
- useOriginValidation: (0, eslint_devkit_1.formatLLMMessage)({
41
- icon: eslint_devkit_1.MessageIcons.INFO,
42
- issueName: 'Validate Origin',
43
- description: 'Validate CORS origin',
44
- severity: 'LOW',
45
- fix: 'cors({ origin: (origin, cb) => allowedOrigins.includes(origin) ? cb(null, true) : cb(new Error()) })',
46
- documentationLink: 'https://github.com/expressjs/cors#configuration-options',
47
- }),
48
- useCorsMiddleware: (0, eslint_devkit_1.formatLLMMessage)({
49
- icon: eslint_devkit_1.MessageIcons.INFO,
50
- issueName: 'Use CORS Middleware',
51
- description: 'Use CORS middleware with origin validation',
52
- severity: 'LOW',
53
- fix: 'app.use(cors({ origin: allowedOrigins }))',
54
- documentationLink: 'https://github.com/expressjs/cors',
55
- }),
56
- },
57
- schema: [
58
- {
59
- type: 'object',
60
- properties: {
61
- allowInTests: {
62
- type: 'boolean',
63
- default: false,
64
- description: 'Allow missing CORS checks in test files',
65
- },
66
- trustedLibraries: {
67
- type: 'array',
68
- items: { type: 'string' },
69
- default: [],
70
- description: 'Custom CORS libraries to trust (wildcard origins in these libraries will not be reported)',
71
- },
72
- ignorePatterns: {
73
- type: 'array',
74
- items: { type: 'string' },
75
- default: [],
76
- description: 'Additional safe patterns to ignore',
77
- },
78
- },
79
- additionalProperties: false,
80
- },
81
- ],
82
- },
83
- defaultOptions: [
84
- {
85
- allowInTests: false,
86
- trustedLibraries: [], // Empty by default - users can add custom CORS libraries they trust
87
- ignorePatterns: [],
88
- },
89
- ],
90
- create(context, [options = {}]) {
91
- const { allowInTests = false, trustedLibraries: corsTrustedLibraries = [], ignorePatterns = [], } = options;
92
- const trustedLibraries = corsTrustedLibraries;
93
- const filename = context.getFilename();
94
- const isTestFile = allowInTests && /\.(test|spec)\.(ts|tsx|js|jsx)$/.test(filename);
95
- const sourceCode = context.sourceCode || context.sourceCode;
96
- function checkLiteral(node) {
97
- if (isTestFile) {
98
- return;
99
- }
100
- // Check for wildcard CORS origin
101
- if (node.value === '*' && typeof node.value === 'string') {
102
- const text = sourceCode.getText(node);
103
- // Check if it matches any ignore pattern
104
- if (matchesIgnorePattern(text, ignorePatterns)) {
105
- return;
106
- }
107
- // Check if it's in contexts handled by other checkers
108
- // 1. setHeader/header calls - checkMemberExpression handles these
109
- // 2. app.use(cors({ origin: "*" })) - checkCallExpression handles these with suggestions
110
- let shouldSkip = false;
111
- let current = node;
112
- while (current && current.parent) {
113
- current = current.parent;
114
- if (current.type === 'CallExpression') {
115
- const callText = sourceCode.getText(current);
116
- // Check if it's a setHeader/header call with Access-Control-Allow-Origin
117
- // Skip these - checkMemberExpression handles them
118
- if (/\b(setHeader|header)\s*\(/i.test(callText) && /\bAccess-Control-Allow-Origin\b/i.test(callText)) {
119
- shouldSkip = true;
120
- break;
121
- }
122
- // Check if it's app.use(cors({ origin: "*" })) - checkCallExpression handles these with suggestions
123
- if (/\buse\s*\(/i.test(callText) && /\bcors\s*\(/i.test(callText)) {
124
- // Check if the literal is in an object property named "origin"
125
- if (node.parent && node.parent.type === 'Property') {
126
- const prop = node.parent;
127
- if (prop.key.type === 'Identifier' && prop.key.name === 'origin') {
128
- shouldSkip = true;
129
- break;
130
- }
131
- }
132
- }
133
- }
134
- }
135
- // Skip if it's in a context handled by another checker
136
- if (shouldSkip) {
137
- return;
138
- }
139
- // Check if it's in a CORS-related context
140
- // Only report if it's actually in a CORS configuration (app.use(cors(...)), etc.)
141
- // Not just any object with origin: "*"
142
- let isActualCorsContext = false;
143
- // Check if it's in app.use(cors(...)) or similar
144
- current = node;
145
- while (current && current.parent) {
146
- current = current.parent;
147
- if (current.type === 'CallExpression') {
148
- const callText = sourceCode.getText(current);
149
- // Check if it's a CORS middleware call
150
- if (/\b(use|cors)\s*\(/i.test(callText) && /\bcors\s*\(/i.test(callText)) {
151
- isActualCorsContext = true;
152
- break;
153
- }
154
- }
155
- }
156
- // Also check if it's in an object property with name "origin" or "allowedOrigins"
157
- // but only if it's in a CORS-related call expression
158
- if (node.parent && node.parent.type === 'Property') {
159
- const prop = node.parent;
160
- if (prop.key.type === 'Identifier') {
161
- const keyName = prop.key.name.toLowerCase();
162
- if (keyName === 'origin' || keyName === 'allowedorigins') {
163
- // Check if this property is in a CORS call context
164
- let inCorsCall = false;
165
- let checkNode = prop;
166
- while (checkNode && checkNode.parent) {
167
- checkNode = checkNode.parent;
168
- if (checkNode.type === 'CallExpression') {
169
- const callText = sourceCode.getText(checkNode);
170
- if (/\bcors\s*\(/i.test(callText) ||
171
- (/\buse\s*\(/i.test(callText) && /\bcors/i.test(callText))) {
172
- inCorsCall = true;
173
- break;
174
- }
175
- }
176
- }
177
- if (inCorsCall) {
178
- // Always report wildcard CORS origin - it's never safe
179
- context.report({
180
- node,
181
- messageId: 'missingCorsCheck',
182
- data: {
183
- issue: 'Wildcard CORS origin (*) allows all origins',
184
- safeAlternative: 'Use origin validation: app.use(cors({ origin: (origin, callback) => { if (allowedOrigins.includes(origin)) callback(null, true); else callback(new Error("Not allowed")); } } }));',
185
- },
186
- suggest: [
187
- {
188
- messageId: 'useOriginValidation',
189
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
190
- fix: (_fixer) => null,
191
- },
192
- ],
193
- });
194
- return;
195
- }
196
- }
197
- }
198
- }
199
- // Only report if it's in an actual CORS context
200
- if (isActualCorsContext) {
201
- // Always report wildcard CORS origin - it's never safe
202
- context.report({
203
- node,
204
- messageId: 'missingCorsCheck',
205
- data: {
206
- issue: 'Wildcard CORS origin (*) allows all origins',
207
- safeAlternative: 'Use origin validation: app.use(cors({ origin: (origin, callback) => { if (allowedOrigins.includes(origin)) callback(null, true); else callback(new Error("Not allowed")); } } }));',
208
- },
209
- suggest: [
210
- {
211
- messageId: 'useOriginValidation',
212
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
213
- fix: (_fixer) => null,
214
- },
215
- ],
216
- });
217
- }
218
- }
219
- }
220
- function checkCallExpression(node) {
221
- if (isTestFile) {
222
- return;
223
- }
224
- // Check for app.use(cors({ origin: "*" })) or similar
225
- if (node.callee.type === 'MemberExpression') {
226
- const property = node.callee.property;
227
- if (property.type === 'Identifier' && property.name === 'use') {
228
- // Check if CORS is being used
229
- const text = sourceCode.getText(node);
230
- // Check if it matches any ignore pattern
231
- if (matchesIgnorePattern(text, ignorePatterns)) {
232
- return;
233
- }
234
- // Check if it's a CORS middleware call
235
- // Check for cors() or trusted library calls
236
- const firstArg = node.arguments.length > 0 ? node.arguments[0] : null;
237
- let isCorsCall = /\bcors\s*\(/i.test(text);
238
- if (!isCorsCall && firstArg && firstArg.type === 'CallExpression' && firstArg.callee.type === 'Identifier') {
239
- const callee = firstArg.callee;
240
- const calleeName = callee.name.toLowerCase();
241
- // Check if it's the standard 'cors' library or a trusted library
242
- isCorsCall = calleeName === 'cors' || trustedLibraries.some(lib => {
243
- return calleeName.includes(lib.toLowerCase());
244
- });
245
- }
246
- // Check if it's a trusted library - skip if explicitly trusted
247
- let isTrustedLibrary = false;
248
- if (firstArg && firstArg.type === 'CallExpression' && firstArg.callee.type === 'Identifier') {
249
- const calleeName = firstArg.callee.name.toLowerCase();
250
- isTrustedLibrary = trustedLibraries.some(lib => calleeName.includes(lib.toLowerCase()));
251
- }
252
- if (isTrustedLibrary) {
253
- return; // Trusted library, skip
254
- }
255
- // Check if it's a CORS call
256
- if (/\bcors\s*\(/i.test(text) || isCorsCall) {
257
- // Check arguments for wildcard origin
258
- // For app.use(cors({ origin: "*" })), we need to check the arguments to cors(), not app.use()
259
- const corsCallArg = firstArg && firstArg.type === 'CallExpression' ? firstArg : null;
260
- const argsToCheck = corsCallArg ? corsCallArg.arguments : node.arguments;
261
- for (const arg of argsToCheck) {
262
- if (arg.type === 'ObjectExpression') {
263
- // Check for origin property with wildcard value
264
- for (const prop of arg.properties) {
265
- if (prop.type === 'Property' &&
266
- prop.key.type === 'Identifier' &&
267
- prop.key.name === 'origin' &&
268
- prop.value.type === 'Literal' &&
269
- prop.value.value === '*') {
270
- context.report({
271
- node: prop.value,
272
- messageId: 'missingCorsCheck',
273
- data: {
274
- issue: 'Wildcard CORS origin (*) allows all origins',
275
- safeAlternative: 'Use origin validation: app.use(cors({ origin: (origin, callback) => { if (allowedOrigins.includes(origin)) callback(null, true); else callback(new Error("Not allowed")); } } }));',
276
- },
277
- suggest: [
278
- {
279
- messageId: 'useOriginValidation',
280
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
281
- fix: (_fixer) => null,
282
- },
283
- ],
284
- });
285
- }
286
- }
287
- }
288
- else if (arg.type === 'Identifier') {
289
- // Check if this identifier was assigned an object literal with origin: "*"
290
- // For cases like: const config = { origin: "*" }; app.use(cors(config));
291
- const varName = arg.name;
292
- // Traverse the AST to find the variable declaration
293
- let current = node;
294
- while (current) {
295
- if (current.type === 'Program' || current.type === 'FunctionDeclaration' || current.type === 'FunctionExpression' || current.type === 'ArrowFunctionExpression') {
296
- // Search for variable declarations in this scope
297
- const scopeBody = current.type === 'Program' ? current.body :
298
- (current.type === 'FunctionDeclaration' || current.type === 'FunctionExpression' || current.type === 'ArrowFunctionExpression') ?
299
- (current.body.type === 'BlockStatement' ? current.body.body : []) : [];
300
- for (const stmt of scopeBody) {
301
- if (stmt.type === 'VariableDeclaration') {
302
- for (const declarator of stmt.declarations) {
303
- if (declarator.id.type === 'Identifier' && declarator.id.name === varName && declarator.init) {
304
- // Check if init is an object literal with origin: "*"
305
- if (declarator.init.type === 'ObjectExpression') {
306
- for (const prop of declarator.init.properties) {
307
- if (prop.type === 'Property' &&
308
- prop.key.type === 'Identifier' &&
309
- prop.key.name === 'origin' &&
310
- prop.value.type === 'Literal' &&
311
- prop.value.value === '*') {
312
- context.report({
313
- node: arg,
314
- messageId: 'missingCorsCheck',
315
- data: {
316
- issue: 'Wildcard CORS origin (*) allows all origins',
317
- safeAlternative: 'Use origin validation: app.use(cors({ origin: (origin, callback) => { if (allowedOrigins.includes(origin)) callback(null, true); else callback(new Error("Not allowed")); } } }));',
318
- },
319
- suggest: [
320
- {
321
- messageId: 'useOriginValidation',
322
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
323
- fix: (_fixer) => null,
324
- },
325
- ],
326
- });
327
- return; // Found and reported, exit
328
- }
329
- }
330
- }
331
- }
332
- }
333
- }
334
- }
335
- break; // Only check the immediate scope
336
- }
337
- if (current.parent) {
338
- current = current.parent;
339
- }
340
- else {
341
- break;
342
- }
343
- }
344
- }
345
- }
346
- }
347
- }
348
- }
349
- }
350
- function checkMemberExpression(node) {
351
- if (isTestFile) {
352
- return;
353
- }
354
- // Check for Access-Control-Allow-Origin header without validation
355
- if (node.property.type === 'Identifier') {
356
- const propertyName = node.property.name;
357
- if (propertyName === 'setHeader' || propertyName === 'header') {
358
- // Check if it matches any ignore pattern
359
- const text = sourceCode.getText(node);
360
- if (matchesIgnorePattern(text, ignorePatterns)) {
361
- return;
362
- }
363
- // Check if it's setting CORS headers
364
- // Need to check the full call expression, not just the member expression
365
- const parent = node.parent;
366
- if (parent && parent.type === 'CallExpression') {
367
- const callText = sourceCode.getText(parent);
368
- if (/\bAccess-Control-Allow-Origin\b/i.test(callText)) {
369
- // Check if the value is a wildcard
370
- const args = parent.arguments;
371
- if (args.length >= 2 && args[1].type === 'Literal' && args[1].value === '*') {
372
- context.report({
373
- node: args[1],
374
- messageId: 'missingCorsCheck',
375
- data: {
376
- issue: 'Wildcard CORS header allows all origins',
377
- safeAlternative: 'Validate origin before setting header: res.setHeader("Access-Control-Allow-Origin", allowedOrigins.includes(origin) ? origin : "null");',
378
- },
379
- suggest: [
380
- {
381
- messageId: 'useOriginValidation',
382
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
383
- fix: (_fixer) => null,
384
- },
385
- ],
386
- });
387
- }
388
- }
389
- }
390
- }
391
- }
392
- }
393
- return {
394
- Literal: checkLiteral,
395
- CallExpression: checkCallExpression,
396
- MemberExpression: checkMemberExpression,
397
- };
398
- },
399
- });
@@ -1,11 +0,0 @@
1
- export interface Options {
2
- /** Allow missing CSRF protection in test files. Default: false */
3
- allowInTests?: boolean;
4
- /** CSRF middleware patterns to recognize. Default: ['csrf', 'csurf', 'csrfProtection', 'verifyCsrfToken'] */
5
- csrfMiddlewarePatterns?: string[];
6
- /** HTTP methods that require CSRF protection. Default: ['post', 'put', 'delete', 'patch'] */
7
- protectedMethods?: string[];
8
- /** Additional safe patterns to ignore. Default: [] */
9
- ignorePatterns?: string[];
10
- }
11
- export declare const noMissingCsrfProtection: ESLintUtils.RuleModule<MessageIds, Options, unknown, ESLintUtils.RuleListener>;
@@ -1,180 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.noMissingCsrfProtection = void 0;
4
- const eslint_devkit_1 = require("@interlace/eslint-devkit");
5
- const eslint_devkit_2 = require("@interlace/eslint-devkit");
6
- /**
7
- * Default CSRF middleware patterns
8
- */
9
- const DEFAULT_CSRF_MIDDLEWARE_PATTERNS = [
10
- 'csrf',
11
- 'csurf',
12
- 'csrfProtection',
13
- 'verifyCsrfToken',
14
- 'csrfToken',
15
- 'validateCsrf',
16
- 'checkCsrf',
17
- 'csrfMiddleware',
18
- ];
19
- /**
20
- * Default HTTP methods that require CSRF protection
21
- */
22
- const DEFAULT_PROTECTED_METHODS = ['post', 'put', 'delete', 'patch'];
23
- /**
24
- * Check if a string matches any ignore pattern
25
- */
26
- function matchesIgnorePattern(text, patterns) {
27
- return patterns.some(pattern => {
28
- try {
29
- const regex = new RegExp(pattern, 'i');
30
- return regex.test(text);
31
- }
32
- catch {
33
- return text.toLowerCase().includes(pattern.toLowerCase());
34
- }
35
- });
36
- }
37
- exports.noMissingCsrfProtection = (0, eslint_devkit_2.createRule)({
38
- name: 'no-missing-csrf-protection',
39
- meta: {
40
- type: 'problem',
41
- deprecated: true,
42
- replacedBy: ['@see eslint-plugin-express-security/require-csrf-protection'],
43
- docs: {
44
- description: 'Detects missing CSRF token validation in POST/PUT/DELETE requests',
45
- },
46
- hasSuggestions: true,
47
- messages: {
48
- missingCsrfProtection: (0, eslint_devkit_1.formatLLMMessage)({
49
- icon: eslint_devkit_1.MessageIcons.SECURITY,
50
- issueName: 'Missing CSRF Protection',
51
- cwe: 'CWE-352',
52
- description: 'Missing CSRF protection detected: {{issue}}',
53
- severity: 'HIGH',
54
- fix: '{{safeAlternative}}',
55
- documentationLink: 'https://cwe.mitre.org/data/definitions/352.html',
56
- }),
57
- addCsrfValidation: (0, eslint_devkit_1.formatLLMMessage)({
58
- icon: eslint_devkit_1.MessageIcons.INFO,
59
- issueName: 'Add CSRF Validation',
60
- description: 'Add CSRF middleware',
61
- severity: 'LOW',
62
- fix: 'app.use(csrf({ cookie: true }))',
63
- documentationLink: 'https://github.com/expressjs/csurf',
64
- }),
65
- },
66
- schema: [
67
- {
68
- type: 'object',
69
- properties: {
70
- allowInTests: {
71
- type: 'boolean',
72
- default: false,
73
- description: 'Allow missing CSRF protection in test files',
74
- },
75
- csrfMiddlewarePatterns: {
76
- type: 'array',
77
- items: { type: 'string' },
78
- default: [],
79
- description: 'CSRF middleware patterns to recognize',
80
- },
81
- protectedMethods: {
82
- type: 'array',
83
- items: { type: 'string' },
84
- default: [],
85
- description: 'HTTP methods that require CSRF protection',
86
- },
87
- ignorePatterns: {
88
- type: 'array',
89
- items: { type: 'string' },
90
- default: [],
91
- description: 'Additional safe patterns to ignore',
92
- },
93
- },
94
- additionalProperties: false,
95
- },
96
- ],
97
- },
98
- defaultOptions: [
99
- {
100
- allowInTests: false,
101
- csrfMiddlewarePatterns: [],
102
- protectedMethods: [],
103
- ignorePatterns: [],
104
- },
105
- ],
106
- create(context, [options = {}]) {
107
- const { allowInTests = false, csrfMiddlewarePatterns, protectedMethods: customProtectedMethods, ignorePatterns = [], } = options;
108
- const csrfPatterns = csrfMiddlewarePatterns && csrfMiddlewarePatterns.length > 0
109
- ? csrfMiddlewarePatterns
110
- : DEFAULT_CSRF_MIDDLEWARE_PATTERNS;
111
- const protectedMethods = customProtectedMethods && customProtectedMethods.length > 0
112
- ? customProtectedMethods
113
- : DEFAULT_PROTECTED_METHODS;
114
- // Pre-compute Set for O(1) lookups (performance optimization)
115
- const protectedMethodsSet = new Set(protectedMethods.map(m => m.toLowerCase()));
116
- const filename = context.filename;
117
- const isTestFile = allowInTests && /\.(test|spec)\.(ts|tsx|js|jsx)$/.test(filename);
118
- const sourceCode = context.sourceCode;
119
- function checkCallExpression(node) {
120
- if (isTestFile) {
121
- return;
122
- }
123
- const callee = node.callee;
124
- const callText = sourceCode.getText(node);
125
- // Check if it matches any ignore pattern
126
- if (matchesIgnorePattern(callText, ignorePatterns)) {
127
- return;
128
- }
129
- // Check for route handler methods (app.post, router.put, etc.)
130
- if (callee.type === eslint_devkit_1.AST_NODE_TYPES.MemberExpression && callee.property.type === eslint_devkit_1.AST_NODE_TYPES.Identifier) {
131
- const methodName = callee.property.name;
132
- // Only check if it's a route handler that requires CSRF (O(1) Set lookup)
133
- if (protectedMethodsSet.has(methodName.toLowerCase())) {
134
- // Must have at least 2 arguments (path and handler)
135
- if (node.arguments.length < 2) {
136
- return;
137
- }
138
- // Check if CSRF middleware is in the route chain arguments
139
- let hasCsrfInChain = false;
140
- // Check if any argument (after the first path argument) is a CSRF middleware
141
- // Skip the first argument (path) and check the rest
142
- for (let i = 1; i < node.arguments.length; i++) {
143
- const arg = node.arguments[i];
144
- const argText = sourceCode.getText(arg);
145
- if (csrfPatterns.some(pattern => argText.toLowerCase().includes(pattern.toLowerCase()))) {
146
- hasCsrfInChain = true;
147
- break;
148
- }
149
- }
150
- if (!hasCsrfInChain) {
151
- context.report({
152
- node,
153
- messageId: 'missingCsrfProtection',
154
- data: {
155
- issue: `${methodName.toUpperCase()} route handler missing CSRF protection`,
156
- safeAlternative: `Add CSRF middleware: app.${methodName}("/path", csrf(), handler) or use app.use(csrf()) globally`,
157
- },
158
- suggest: [
159
- {
160
- messageId: 'addCsrfValidation',
161
- fix(fixer) {
162
- // Add CSRF middleware after the first argument (path)
163
- const firstArg = node.arguments[0];
164
- if (firstArg) {
165
- return fixer.insertTextAfter(firstArg, ', csrf()');
166
- }
167
- return null;
168
- },
169
- },
170
- ],
171
- });
172
- }
173
- }
174
- }
175
- }
176
- return {
177
- CallExpression: checkCallExpression,
178
- };
179
- },
180
- });
@@ -1,7 +0,0 @@
1
- export interface Options {
2
- /** Required security headers. Default: ['Content-Security-Policy', 'X-Frame-Options', 'X-Content-Type-Options'] */
3
- requiredHeaders?: string[];
4
- /** Ignore in test files. Default: true */
5
- ignoreInTests?: boolean;
6
- }
7
- export declare const noMissingSecurityHeaders: ESLintUtils.RuleModule<MessageIds, Options, unknown, ESLintUtils.RuleListener>;