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,222 @@
1
+ /**
2
+ * Comprehensive tests for no-missing-csrf-protection rule
3
+ * CWE-352: Cross-Site Request Forgery (CSRF)
4
+ */
5
+ import { RuleTester } from '@typescript-eslint/rule-tester';
6
+ import { describe, it, afterAll } from 'vitest';
7
+ import parser from '@typescript-eslint/parser';
8
+ import { noMissingCsrfProtection } from './index';
9
+
10
+ RuleTester.afterAll = afterAll;
11
+ RuleTester.it = it;
12
+ RuleTester.itOnly = it.only;
13
+ RuleTester.describe = describe;
14
+
15
+ const ruleTester = new RuleTester({
16
+ languageOptions: {
17
+ parser,
18
+ ecmaVersion: 2022,
19
+ sourceType: 'module',
20
+ parserOptions: {
21
+ ecmaFeatures: {
22
+ jsx: true,
23
+ },
24
+ },
25
+ },
26
+ });
27
+
28
+ describe('no-missing-csrf-protection', () => {
29
+ describe('Valid Code', () => {
30
+ ruleTester.run('valid - CSRF protection present', noMissingCsrfProtection, {
31
+ valid: [
32
+ // CSRF middleware in route chain
33
+ {
34
+ code: 'app.post("/api/users", csrf(), handler);',
35
+ },
36
+ {
37
+ code: 'router.put("/api/users/:id", csrf(), handler);',
38
+ },
39
+ {
40
+ code: 'app.delete("/api/users/:id", csrf(), handler);',
41
+ },
42
+ // CSRF middleware globally
43
+ {
44
+ code: 'app.use(csrf());',
45
+ },
46
+ {
47
+ code: 'app.get("/api/users", handler);', // GET doesn't require CSRF
48
+ },
49
+ // Test files (when allowInTests is true)
50
+ {
51
+ code: 'app.post("/test", handler);',
52
+ filename: 'test.spec.ts',
53
+ options: [{ allowInTests: true }],
54
+ },
55
+ ],
56
+ invalid: [],
57
+ });
58
+ });
59
+
60
+ describe('Invalid Code - Missing CSRF', () => {
61
+ ruleTester.run('invalid - POST without CSRF', noMissingCsrfProtection, {
62
+ valid: [],
63
+ invalid: [
64
+ {
65
+ code: 'app.post("/api/users", handler);',
66
+ errors: [
67
+ {
68
+ messageId: 'missingCsrfProtection',
69
+ data: {
70
+ issue: 'POST route handler missing CSRF protection',
71
+ safeAlternative: 'Add CSRF middleware: app.post("/path", csrf(), handler) or use app.use(csrf()) globally',
72
+ },
73
+ suggestions: [
74
+ {
75
+ messageId: 'addCsrfValidation',
76
+ output: 'app.post("/api/users", csrf(), handler);',
77
+ },
78
+ ],
79
+ },
80
+ ],
81
+ },
82
+ {
83
+ code: 'router.post("/api/users", (req, res) => {});',
84
+ errors: [
85
+ {
86
+ messageId: 'missingCsrfProtection',
87
+ data: {
88
+ issue: 'POST route handler missing CSRF protection',
89
+ safeAlternative: 'Add CSRF middleware: app.post("/path", csrf(), handler) or use app.use(csrf()) globally',
90
+ },
91
+ suggestions: [
92
+ {
93
+ messageId: 'addCsrfValidation',
94
+ output: 'router.post("/api/users", csrf(), (req, res) => {});',
95
+ },
96
+ ],
97
+ },
98
+ ],
99
+ },
100
+ ],
101
+ });
102
+
103
+ ruleTester.run('invalid - PUT without CSRF', noMissingCsrfProtection, {
104
+ valid: [],
105
+ invalid: [
106
+ {
107
+ code: 'app.put("/api/users/:id", handler);',
108
+ errors: [
109
+ {
110
+ messageId: 'missingCsrfProtection',
111
+ data: {
112
+ issue: 'PUT route handler missing CSRF protection',
113
+ safeAlternative: 'Add CSRF middleware: app.put("/path", csrf(), handler) or use app.use(csrf()) globally',
114
+ },
115
+ suggestions: [
116
+ {
117
+ messageId: 'addCsrfValidation',
118
+ output: 'app.put("/api/users/:id", csrf(), handler);',
119
+ },
120
+ ],
121
+ },
122
+ ],
123
+ },
124
+ ],
125
+ });
126
+
127
+ ruleTester.run('invalid - DELETE without CSRF', noMissingCsrfProtection, {
128
+ valid: [],
129
+ invalid: [
130
+ {
131
+ code: 'app.delete("/api/users/:id", handler);',
132
+ errors: [
133
+ {
134
+ messageId: 'missingCsrfProtection',
135
+ data: {
136
+ issue: 'DELETE route handler missing CSRF protection',
137
+ safeAlternative: 'Add CSRF middleware: app.delete("/path", csrf(), handler) or use app.use(csrf()) globally',
138
+ },
139
+ suggestions: [
140
+ {
141
+ messageId: 'addCsrfValidation',
142
+ output: 'app.delete("/api/users/:id", csrf(), handler);',
143
+ },
144
+ ],
145
+ },
146
+ ],
147
+ },
148
+ ],
149
+ });
150
+
151
+ ruleTester.run('invalid - PATCH without CSRF', noMissingCsrfProtection, {
152
+ valid: [],
153
+ invalid: [
154
+ {
155
+ code: 'app.patch("/api/users/:id", handler);',
156
+ errors: [
157
+ {
158
+ messageId: 'missingCsrfProtection',
159
+ data: {
160
+ issue: 'PATCH route handler missing CSRF protection',
161
+ safeAlternative: 'Add CSRF middleware: app.patch("/path", csrf(), handler) or use app.use(csrf()) globally',
162
+ },
163
+ suggestions: [
164
+ {
165
+ messageId: 'addCsrfValidation',
166
+ output: 'app.patch("/api/users/:id", csrf(), handler);',
167
+ },
168
+ ],
169
+ },
170
+ ],
171
+ },
172
+ ],
173
+ });
174
+ });
175
+
176
+ describe('Options', () => {
177
+ ruleTester.run('options - ignorePatterns', noMissingCsrfProtection, {
178
+ valid: [
179
+ // Valid ignorePattern - pattern must match the call text
180
+ {
181
+ code: 'app.post("/api/internal", handler);',
182
+ options: [{ ignorePatterns: ['api/internal'] }],
183
+ },
184
+ // Invalid regex pattern fallback to string includes - the text must contain the pattern
185
+ {
186
+ code: 'app.post("/api/internal", handler);',
187
+ options: [{ ignorePatterns: ['internal'] }],
188
+ },
189
+ ],
190
+ invalid: [],
191
+ });
192
+
193
+ ruleTester.run('options - custom CSRF patterns', noMissingCsrfProtection, {
194
+ valid: [
195
+ {
196
+ code: 'app.post("/api/users", customCsrf(), handler);',
197
+ options: [{ csrfMiddlewarePatterns: ['customCsrf'] }],
198
+ },
199
+ ],
200
+ invalid: [],
201
+ });
202
+
203
+ ruleTester.run('options - custom protected methods', noMissingCsrfProtection, {
204
+ valid: [
205
+ {
206
+ code: 'app.options("/api/users", handler);', // OPTIONS not protected by default
207
+ },
208
+ ],
209
+ invalid: [
210
+ {
211
+ code: 'app.options("/api/users", handler);',
212
+ options: [{ protectedMethods: ['options'] }],
213
+ errors: [{
214
+ messageId: 'missingCsrfProtection',
215
+ suggestions: [{ messageId: 'addCsrfValidation', output: 'app.options("/api/users", csrf(), handler);' }],
216
+ }],
217
+ },
218
+ ],
219
+ });
220
+ });
221
+ });
222
+
@@ -0,0 +1,266 @@
1
+ /**
2
+ * ESLint Rule: no-missing-security-headers
3
+ * Detects missing security headers in HTTP responses
4
+ * CWE-693: Protection Mechanism Failure
5
+ *
6
+ * @see https://cwe.mitre.org/data/definitions/693.html
7
+ * @see https://owasp.org/www-project-secure-headers/
8
+ */
9
+ import type { TSESLint, TSESTree } from '@interlace/eslint-devkit';
10
+ import { formatLLMMessage, MessageIcons } from '@interlace/eslint-devkit';
11
+ import { createRule } from '@interlace/eslint-devkit';
12
+
13
+ type MessageIds =
14
+ | 'missingSecurityHeader'
15
+ | 'addSecurityHeaders'
16
+ | 'useMiddleware'
17
+ | 'setHeader';
18
+
19
+ export interface Options {
20
+ /** Required security headers. Default: ['Content-Security-Policy', 'X-Frame-Options', 'X-Content-Type-Options'] */
21
+ requiredHeaders?: string[];
22
+
23
+ /** Ignore in test files. Default: true */
24
+ ignoreInTests?: boolean;
25
+ }
26
+
27
+ type RuleOptions = [Options?];
28
+
29
+ const DEFAULT_REQUIRED_HEADERS = [
30
+ 'Content-Security-Policy',
31
+ 'X-Frame-Options',
32
+ 'X-Content-Type-Options',
33
+ ];
34
+
35
+ /**
36
+ * Extract header name from setHeader call
37
+ */
38
+ function extractHeaderName(node: TSESTree.CallExpression): string | null {
39
+ if (node.arguments.length > 0 && node.arguments[0].type === 'Literal') {
40
+ return String(node.arguments[0].value);
41
+ }
42
+ return null;
43
+ }
44
+
45
+ /**
46
+ * Check if all security headers are set in the current scope
47
+ */
48
+ function checkFunctionForSecurityHeaders(
49
+ node: TSESTree.CallExpression,
50
+ requiredHeaders: string[],
51
+ context: TSESLint.RuleContext<MessageIds, RuleOptions>
52
+ ): string[] {
53
+ const setHeaders = new Set<string>();
54
+
55
+ // Find the function that contains this setHeader call
56
+ let current: TSESTree.Node | null = node;
57
+ let scopeNode: TSESTree.Node | null = null;
58
+
59
+ while (current) {
60
+ if (current.type === 'FunctionDeclaration' ||
61
+ current.type === 'FunctionExpression' ||
62
+ current.type === 'ArrowFunctionExpression') {
63
+ scopeNode = current;
64
+ break;
65
+ }
66
+ current = (current as TSESTree.Node & { parent?: TSESTree.Node }).parent ?? null;
67
+ }
68
+
69
+ // If no function found, use the program scope (for test cases)
70
+ if (!scopeNode) {
71
+ scopeNode = context.sourceCode.ast;
72
+ }
73
+
74
+ // Collect all setHeader calls in this scope
75
+ function collectHeaders(node: TSESTree.Node): void {
76
+ if (node.type === 'CallExpression' &&
77
+ node.callee.type === 'MemberExpression' &&
78
+ node.callee.property.type === 'Identifier' &&
79
+ ['setHeader', 'header', 'set'].includes(node.callee.property.name)) {
80
+ const headerName = extractHeaderName(node);
81
+ if (headerName) {
82
+ setHeaders.add(headerName);
83
+ }
84
+ }
85
+
86
+ // Recursively check children - only traverse standard AST properties
87
+ if (node.type === 'Program' && node.body) {
88
+ node.body.forEach(collectHeaders);
89
+ } else if ((node.type === 'FunctionDeclaration' ||
90
+ node.type === 'FunctionExpression' ||
91
+ node.type === 'ArrowFunctionExpression') && node.body) {
92
+ collectHeaders(node.body);
93
+ } else if (node.type === 'BlockStatement' && node.body) {
94
+ node.body.forEach(collectHeaders);
95
+ } else if (node.type === 'ExpressionStatement' && node.expression) {
96
+ collectHeaders(node.expression);
97
+ }
98
+ }
99
+
100
+ if (scopeNode) {
101
+ collectHeaders(scopeNode);
102
+ }
103
+
104
+ // Return missing headers
105
+ return requiredHeaders.filter(header => !setHeaders.has(header));
106
+ }
107
+
108
+ export const noMissingSecurityHeaders = createRule<RuleOptions, MessageIds>({
109
+ name: 'no-missing-security-headers',
110
+ meta: {
111
+ type: 'problem',
112
+ deprecated: true,
113
+ replacedBy: ['@see eslint-plugin-express-security/require-helmet'],
114
+ docs: {
115
+ description: 'Detects missing security headers in HTTP responses',
116
+ },
117
+ hasSuggestions: true,
118
+ messages: {
119
+ missingSecurityHeader: formatLLMMessage({
120
+ icon: MessageIcons.SECURITY,
121
+ issueName: 'Missing security headers',
122
+ cwe: 'CWE-693',
123
+ description: 'Missing security headers: {{headers}}',
124
+ severity: 'HIGH',
125
+ fix: 'Set security headers: Content-Security-Policy, X-Frame-Options, X-Content-Type-Options',
126
+ documentationLink: 'https://owasp.org/www-project-secure-headers/',
127
+ }),
128
+ addSecurityHeaders: formatLLMMessage({
129
+ icon: MessageIcons.INFO,
130
+ issueName: 'Add Security Headers',
131
+ description: 'Add security headers middleware',
132
+ severity: 'LOW',
133
+ fix: 'Add Content-Security-Policy, X-Frame-Options headers',
134
+ documentationLink: 'https://owasp.org/www-project-secure-headers/',
135
+ }),
136
+ useMiddleware: formatLLMMessage({
137
+ icon: MessageIcons.INFO,
138
+ issueName: 'Use Helmet',
139
+ description: 'Use helmet.js for security headers',
140
+ severity: 'LOW',
141
+ fix: 'app.use(helmet())',
142
+ documentationLink: 'https://helmetjs.github.io/',
143
+ }),
144
+ setHeader: formatLLMMessage({
145
+ icon: MessageIcons.INFO,
146
+ issueName: 'Set Headers',
147
+ description: 'Set security headers manually',
148
+ severity: 'LOW',
149
+ fix: 'res.setHeader("X-Frame-Options", "DENY")',
150
+ documentationLink: 'https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers',
151
+ }),
152
+ },
153
+ schema: [
154
+ {
155
+ type: 'object',
156
+ properties: {
157
+ requiredHeaders: {
158
+ type: 'array',
159
+ items: { type: 'string' },
160
+ default: DEFAULT_REQUIRED_HEADERS,
161
+ },
162
+ ignoreInTests: {
163
+ type: 'boolean',
164
+ default: true,
165
+ },
166
+ },
167
+ additionalProperties: false,
168
+ },
169
+ ],
170
+ },
171
+ defaultOptions: [
172
+ {
173
+ requiredHeaders: DEFAULT_REQUIRED_HEADERS,
174
+ ignoreInTests: true,
175
+ },
176
+ ],
177
+ create(context: TSESLint.RuleContext<MessageIds, RuleOptions>, [options = {}]) {
178
+ const {
179
+ requiredHeaders = DEFAULT_REQUIRED_HEADERS,
180
+ ignoreInTests = true,
181
+
182
+ }: Options = options || {};
183
+
184
+ const filename = context.getFilename();
185
+ const isTestFile = ignoreInTests && /\.(test|spec)\.(ts|tsx|js|jsx)$/.test(filename);
186
+
187
+ if (isTestFile) {
188
+ return {};
189
+ }
190
+
191
+ const reportedScopes = new Set<string>();
192
+
193
+ /**
194
+ * Get a unique key for the current scope
195
+ */
196
+ function getScopeKey(node: TSESTree.CallExpression): string {
197
+ // Find the function that contains this call
198
+ let current: TSESTree.Node | null = node;
199
+ while (current) {
200
+ if (current.type === 'FunctionDeclaration' ||
201
+ current.type === 'FunctionExpression' ||
202
+ current.type === 'ArrowFunctionExpression') {
203
+ return `${current.range?.[0]}-${current.range?.[1]}`;
204
+ }
205
+ current = (current as TSESTree.Node & { parent?: TSESTree.Node }).parent ?? null;
206
+ }
207
+ // If no function found, use program scope
208
+ return 'program';
209
+ }
210
+
211
+ /**
212
+ * Check for response header setting
213
+ */
214
+ function checkCallExpression(node: TSESTree.CallExpression) {
215
+ // Check for res.setHeader, res.header, res.set
216
+ if (node.callee.type === 'MemberExpression' &&
217
+ node.callee.property.type === 'Identifier') {
218
+ const methodName = node.callee.property.name;
219
+
220
+ if (['setHeader', 'header', 'set'].includes(methodName)) {
221
+ const scopeKey = getScopeKey(node);
222
+
223
+ // Only check once per scope
224
+ if (reportedScopes.has(scopeKey)) {
225
+ return;
226
+ }
227
+
228
+ const missing = checkFunctionForSecurityHeaders(node, requiredHeaders, context);
229
+
230
+ if (missing.length > 0) {
231
+ reportedScopes.add(scopeKey);
232
+ context.report({
233
+ node,
234
+ messageId: 'missingSecurityHeader',
235
+ data: {
236
+ headers: missing.join(', '),
237
+ },
238
+ suggest: [
239
+ {
240
+ messageId: 'addSecurityHeaders',
241
+ fix: () => null,
242
+ },
243
+ {
244
+ messageId: 'useMiddleware',
245
+ fix: () => null,
246
+ },
247
+ {
248
+ messageId: 'setHeader',
249
+ fix: () => null,
250
+ },
251
+ ],
252
+ });
253
+ } else {
254
+ // Mark as checked even if no error
255
+ reportedScopes.add(scopeKey);
256
+ }
257
+ }
258
+ }
259
+ }
260
+
261
+ return {
262
+ CallExpression: checkCallExpression,
263
+ };
264
+ },
265
+ });
266
+
@@ -0,0 +1,98 @@
1
+ /**
2
+ * Comprehensive tests for no-missing-security-headers rule
3
+ * Security: CWE-693 - Detects missing security headers in HTTP responses
4
+ */
5
+ import { RuleTester } from '@typescript-eslint/rule-tester';
6
+ import { describe, it, afterAll } from 'vitest';
7
+ import parser from '@typescript-eslint/parser';
8
+ import { noMissingSecurityHeaders } from './index';
9
+
10
+ RuleTester.afterAll = afterAll;
11
+ RuleTester.it = it;
12
+ RuleTester.itOnly = it.only;
13
+ RuleTester.describe = describe;
14
+
15
+ const ruleTester = new RuleTester({
16
+ languageOptions: {
17
+ parser,
18
+ ecmaVersion: 2022,
19
+ sourceType: 'module',
20
+ },
21
+ });
22
+
23
+ describe('no-missing-security-headers', () => {
24
+ describe('Valid Code', () => {
25
+ ruleTester.run('valid - security headers set', noMissingSecurityHeaders, {
26
+ valid: [
27
+ // All required headers
28
+ {
29
+ code: `
30
+ res.setHeader('Content-Security-Policy', 'default-src self');
31
+ res.setHeader('X-Frame-Options', 'DENY');
32
+ res.setHeader('X-Content-Type-Options', 'nosniff');
33
+ `,
34
+ },
35
+ // Test files (if ignoreInTests is true)
36
+ {
37
+ code: 'res.setHeader("X-Custom", "value");',
38
+ filename: 'test.spec.ts',
39
+ options: [{ ignoreInTests: true }],
40
+ },
41
+ ],
42
+ invalid: [],
43
+ });
44
+ });
45
+
46
+ describe('Invalid Code - Missing Security Headers', () => {
47
+ ruleTester.run('invalid - missing headers', noMissingSecurityHeaders, {
48
+ valid: [],
49
+ invalid: [
50
+ {
51
+ code: 'res.setHeader("X-Custom", "value");',
52
+ errors: [{ messageId: 'missingSecurityHeader' }],
53
+ },
54
+ {
55
+ code: 'res.setHeader("Content-Security-Policy", "default-src self");',
56
+ errors: [{ messageId: 'missingSecurityHeader' }], // Missing other headers
57
+ },
58
+ ],
59
+ });
60
+ });
61
+
62
+ describe('Options', () => {
63
+ ruleTester.run('options - ignoreInTests', noMissingSecurityHeaders, {
64
+ valid: [
65
+ {
66
+ code: 'res.setHeader("X-Custom", "value");',
67
+ filename: 'test.spec.ts',
68
+ options: [{ ignoreInTests: true }],
69
+ },
70
+ ],
71
+ invalid: [
72
+ {
73
+ code: 'res.setHeader("X-Custom", "value");',
74
+ filename: 'test.spec.ts',
75
+ options: [{ ignoreInTests: false }],
76
+ errors: [{ messageId: 'missingSecurityHeader' }],
77
+ },
78
+ ],
79
+ });
80
+
81
+ ruleTester.run('options - requiredHeaders', noMissingSecurityHeaders, {
82
+ valid: [
83
+ {
84
+ code: 'res.setHeader("Custom-Header", "value");',
85
+ options: [{ requiredHeaders: ['Custom-Header'] }],
86
+ },
87
+ ],
88
+ invalid: [
89
+ {
90
+ code: 'res.setHeader("Other-Header", "value");',
91
+ options: [{ requiredHeaders: ['Custom-Header'] }],
92
+ errors: [{ messageId: 'missingSecurityHeader' }],
93
+ },
94
+ ],
95
+ });
96
+ });
97
+ });
98
+
@@ -0,0 +1,64 @@
1
+ /**
2
+ * @fileoverview Prevent passwords in URLs
3
+ * @see https://owasp.org/www-project-mobile-top-10/
4
+ * @see https://cwe.mitre.org/data/definitions/598.html
5
+ */
6
+
7
+ import { createRule, formatLLMMessage, MessageIcons } from '@interlace/eslint-devkit';
8
+ import type { TSESTree } from '@interlace/eslint-devkit';
9
+
10
+ type MessageIds = 'violationDetected';
11
+
12
+ // eslint-disable-next-line @typescript-eslint/no-empty-object-type, @typescript-eslint/no-empty-interface -- Rule has no configurable options
13
+ export interface Options {}
14
+
15
+ type RuleOptions = [Options?];
16
+
17
+ export const noPasswordInUrl = createRule<RuleOptions, MessageIds>({
18
+ name: 'no-password-in-url',
19
+ meta: {
20
+ type: 'problem',
21
+ docs: {
22
+ description: 'Prevent passwords in URLs',
23
+ category: 'Security',
24
+ recommended: true,
25
+ owaspMobile: ['M3'],
26
+ cweIds: ["CWE-598"],
27
+ },
28
+ messages: {
29
+ violationDetected: formatLLMMessage({
30
+ icon: MessageIcons.SECURITY,
31
+ issueName: 'violation Detected',
32
+ cwe: 'CWE-521',
33
+ description: 'Prevent passwords in URLs detected - this is a security risk',
34
+ severity: 'CRITICAL',
35
+ fix: 'Review and apply secure practices',
36
+ documentationLink: 'https://cwe.mitre.org/data/definitions/521.html',
37
+ })
38
+ },
39
+ schema: [],
40
+ },
41
+ defaultOptions: [],
42
+ create(context) {
43
+ function report(node: TSESTree.Node) {
44
+ context.report({
45
+ node,
46
+ messageId: 'violationDetected',
47
+ });
48
+ }
49
+
50
+ return {
51
+ Literal(node: TSESTree.Literal) {
52
+
53
+ // Check for http://user:password@host patterns
54
+ if (node.type === 'Literal' && typeof node.value === 'string') {
55
+ const urlPattern = /https?:\/\/[^:]+:[^@]+@/;
56
+ if (urlPattern.test(node.value)) {
57
+ report(node);
58
+ }
59
+ }
60
+
61
+ },
62
+ };
63
+ },
64
+ });
@@ -0,0 +1,27 @@
1
+ /**
2
+ * @fileoverview Tests for no-password-in-url
3
+ *
4
+ * Coverage: Comprehensive test suite with valid and invalid cases
5
+ */
6
+
7
+ import { RuleTester } from '@typescript-eslint/rule-tester';
8
+ import { noPasswordInUrl } from './index';
9
+
10
+ const ruleTester = new RuleTester({
11
+ languageOptions: {
12
+ ecmaVersion: 2022,
13
+ sourceType: 'module',
14
+ },
15
+ });
16
+
17
+ ruleTester.run('no-password-in-url', noPasswordInUrl, {
18
+ valid: [
19
+ { code: "const url = 'https://example.com/api'" },
20
+ { code: "fetch('https://api.example.com')" }
21
+ ],
22
+
23
+ invalid: [
24
+ { code: "const url = 'https://user:password@example.com'", errors: [{ messageId: 'violationDetected' }] },
25
+ { code: "fetch('https://admin:secret123@api.com')", errors: [{ messageId: 'violationDetected' }] }
26
+ ],
27
+ });