codeslick-cli 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (455) hide show
  1. package/README.md +458 -0
  2. package/__tests__/cli-reporter.test.ts +86 -0
  3. package/__tests__/config-loader.test.ts +247 -0
  4. package/__tests__/local-scanner.test.ts +245 -0
  5. package/bin/codeslick.cjs +153 -0
  6. package/dist/packages/cli/src/commands/auth.d.ts +36 -0
  7. package/dist/packages/cli/src/commands/auth.d.ts.map +1 -0
  8. package/dist/packages/cli/src/commands/auth.js +226 -0
  9. package/dist/packages/cli/src/commands/auth.js.map +1 -0
  10. package/dist/packages/cli/src/commands/config.d.ts +37 -0
  11. package/dist/packages/cli/src/commands/config.d.ts.map +1 -0
  12. package/dist/packages/cli/src/commands/config.js +196 -0
  13. package/dist/packages/cli/src/commands/config.js.map +1 -0
  14. package/dist/packages/cli/src/commands/init.d.ts +32 -0
  15. package/dist/packages/cli/src/commands/init.d.ts.map +1 -0
  16. package/dist/packages/cli/src/commands/init.js +171 -0
  17. package/dist/packages/cli/src/commands/init.js.map +1 -0
  18. package/dist/packages/cli/src/commands/scan.d.ts +40 -0
  19. package/dist/packages/cli/src/commands/scan.d.ts.map +1 -0
  20. package/dist/packages/cli/src/commands/scan.js +204 -0
  21. package/dist/packages/cli/src/commands/scan.js.map +1 -0
  22. package/dist/packages/cli/src/config/config-loader.d.ts +67 -0
  23. package/dist/packages/cli/src/config/config-loader.d.ts.map +1 -0
  24. package/dist/packages/cli/src/config/config-loader.js +146 -0
  25. package/dist/packages/cli/src/config/config-loader.js.map +1 -0
  26. package/dist/packages/cli/src/reporters/cli-reporter.d.ts +69 -0
  27. package/dist/packages/cli/src/reporters/cli-reporter.d.ts.map +1 -0
  28. package/dist/packages/cli/src/reporters/cli-reporter.js +244 -0
  29. package/dist/packages/cli/src/reporters/cli-reporter.js.map +1 -0
  30. package/dist/packages/cli/src/scanner/local-scanner.d.ts +92 -0
  31. package/dist/packages/cli/src/scanner/local-scanner.d.ts.map +1 -0
  32. package/dist/packages/cli/src/scanner/local-scanner.js +221 -0
  33. package/dist/packages/cli/src/scanner/local-scanner.js.map +1 -0
  34. package/dist/src/lib/analyzers/helpers/ai-code-detection-utils.d.ts +88 -0
  35. package/dist/src/lib/analyzers/helpers/ai-code-detection-utils.d.ts.map +1 -0
  36. package/dist/src/lib/analyzers/helpers/ai-code-detection-utils.js +371 -0
  37. package/dist/src/lib/analyzers/helpers/ai-code-detection-utils.js.map +1 -0
  38. package/dist/src/lib/analyzers/helpers/jsx-helpers.d.ts +63 -0
  39. package/dist/src/lib/analyzers/helpers/jsx-helpers.d.ts.map +1 -0
  40. package/dist/src/lib/analyzers/helpers/jsx-helpers.js +95 -0
  41. package/dist/src/lib/analyzers/helpers/jsx-helpers.js.map +1 -0
  42. package/dist/src/lib/analyzers/helpers/variable-tracker.d.ts +59 -0
  43. package/dist/src/lib/analyzers/helpers/variable-tracker.d.ts.map +1 -0
  44. package/dist/src/lib/analyzers/helpers/variable-tracker.js +231 -0
  45. package/dist/src/lib/analyzers/helpers/variable-tracker.js.map +1 -0
  46. package/dist/src/lib/analyzers/java/security-checks/access-control.d.ts +20 -0
  47. package/dist/src/lib/analyzers/java/security-checks/access-control.d.ts.map +1 -0
  48. package/dist/src/lib/analyzers/java/security-checks/access-control.js +129 -0
  49. package/dist/src/lib/analyzers/java/security-checks/access-control.js.map +1 -0
  50. package/dist/src/lib/analyzers/java/security-checks/ai-generated-code.d.ts +25 -0
  51. package/dist/src/lib/analyzers/java/security-checks/ai-generated-code.d.ts.map +1 -0
  52. package/dist/src/lib/analyzers/java/security-checks/ai-generated-code.js +221 -0
  53. package/dist/src/lib/analyzers/java/security-checks/ai-generated-code.js.map +1 -0
  54. package/dist/src/lib/analyzers/java/security-checks/code-quality.d.ts +18 -0
  55. package/dist/src/lib/analyzers/java/security-checks/code-quality.d.ts.map +1 -0
  56. package/dist/src/lib/analyzers/java/security-checks/code-quality.js +84 -0
  57. package/dist/src/lib/analyzers/java/security-checks/code-quality.js.map +1 -0
  58. package/dist/src/lib/analyzers/java/security-checks/crypto-validation.d.ts +18 -0
  59. package/dist/src/lib/analyzers/java/security-checks/crypto-validation.d.ts.map +1 -0
  60. package/dist/src/lib/analyzers/java/security-checks/crypto-validation.js +161 -0
  61. package/dist/src/lib/analyzers/java/security-checks/crypto-validation.js.map +1 -0
  62. package/dist/src/lib/analyzers/java/security-checks/deserialization-xxe.d.ts +20 -0
  63. package/dist/src/lib/analyzers/java/security-checks/deserialization-xxe.d.ts.map +1 -0
  64. package/dist/src/lib/analyzers/java/security-checks/deserialization-xxe.js +163 -0
  65. package/dist/src/lib/analyzers/java/security-checks/deserialization-xxe.js.map +1 -0
  66. package/dist/src/lib/analyzers/java/security-checks/enhanced-supply-chain.d.ts +24 -0
  67. package/dist/src/lib/analyzers/java/security-checks/enhanced-supply-chain.d.ts.map +1 -0
  68. package/dist/src/lib/analyzers/java/security-checks/enhanced-supply-chain.js +178 -0
  69. package/dist/src/lib/analyzers/java/security-checks/enhanced-supply-chain.js.map +1 -0
  70. package/dist/src/lib/analyzers/java/security-checks/exception-handling.d.ts +25 -0
  71. package/dist/src/lib/analyzers/java/security-checks/exception-handling.d.ts.map +1 -0
  72. package/dist/src/lib/analyzers/java/security-checks/exception-handling.js +179 -0
  73. package/dist/src/lib/analyzers/java/security-checks/exception-handling.js.map +1 -0
  74. package/dist/src/lib/analyzers/java/security-checks/file-operations.d.ts +17 -0
  75. package/dist/src/lib/analyzers/java/security-checks/file-operations.d.ts.map +1 -0
  76. package/dist/src/lib/analyzers/java/security-checks/file-operations.js +67 -0
  77. package/dist/src/lib/analyzers/java/security-checks/file-operations.js.map +1 -0
  78. package/dist/src/lib/analyzers/java/security-checks/framework-security.d.ts +25 -0
  79. package/dist/src/lib/analyzers/java/security-checks/framework-security.d.ts.map +1 -0
  80. package/dist/src/lib/analyzers/java/security-checks/framework-security.js +396 -0
  81. package/dist/src/lib/analyzers/java/security-checks/framework-security.js.map +1 -0
  82. package/dist/src/lib/analyzers/java/security-checks/hardcoded-credentials.d.ts +20 -0
  83. package/dist/src/lib/analyzers/java/security-checks/hardcoded-credentials.d.ts.map +1 -0
  84. package/dist/src/lib/analyzers/java/security-checks/hardcoded-credentials.js +123 -0
  85. package/dist/src/lib/analyzers/java/security-checks/hardcoded-credentials.js.map +1 -0
  86. package/dist/src/lib/analyzers/java/security-checks/injection-attacks.d.ts +23 -0
  87. package/dist/src/lib/analyzers/java/security-checks/injection-attacks.d.ts.map +1 -0
  88. package/dist/src/lib/analyzers/java/security-checks/injection-attacks.js +201 -0
  89. package/dist/src/lib/analyzers/java/security-checks/injection-attacks.js.map +1 -0
  90. package/dist/src/lib/analyzers/java/security-checks/insecure-design.d.ts +20 -0
  91. package/dist/src/lib/analyzers/java/security-checks/insecure-design.d.ts.map +1 -0
  92. package/dist/src/lib/analyzers/java/security-checks/insecure-design.js +121 -0
  93. package/dist/src/lib/analyzers/java/security-checks/insecure-design.js.map +1 -0
  94. package/dist/src/lib/analyzers/java/security-checks/logging-failures.d.ts +20 -0
  95. package/dist/src/lib/analyzers/java/security-checks/logging-failures.d.ts.map +1 -0
  96. package/dist/src/lib/analyzers/java/security-checks/logging-failures.js +89 -0
  97. package/dist/src/lib/analyzers/java/security-checks/logging-failures.js.map +1 -0
  98. package/dist/src/lib/analyzers/java/security-checks/security-misconfiguration.d.ts +26 -0
  99. package/dist/src/lib/analyzers/java/security-checks/security-misconfiguration.d.ts.map +1 -0
  100. package/dist/src/lib/analyzers/java/security-checks/security-misconfiguration.js +309 -0
  101. package/dist/src/lib/analyzers/java/security-checks/security-misconfiguration.js.map +1 -0
  102. package/dist/src/lib/analyzers/java/security-checks/unsafe-patterns.d.ts +18 -0
  103. package/dist/src/lib/analyzers/java/security-checks/unsafe-patterns.d.ts.map +1 -0
  104. package/dist/src/lib/analyzers/java/security-checks/unsafe-patterns.js +114 -0
  105. package/dist/src/lib/analyzers/java/security-checks/unsafe-patterns.js.map +1 -0
  106. package/dist/src/lib/analyzers/java/utils/createVulnerability.d.ts +58 -0
  107. package/dist/src/lib/analyzers/java/utils/createVulnerability.d.ts.map +1 -0
  108. package/dist/src/lib/analyzers/java/utils/createVulnerability.js +71 -0
  109. package/dist/src/lib/analyzers/java/utils/createVulnerability.js.map +1 -0
  110. package/dist/src/lib/analyzers/java-analyzer.d.ts +209 -0
  111. package/dist/src/lib/analyzers/java-analyzer.d.ts.map +1 -0
  112. package/dist/src/lib/analyzers/java-analyzer.js +1720 -0
  113. package/dist/src/lib/analyzers/java-analyzer.js.map +1 -0
  114. package/dist/src/lib/analyzers/javascript/quality-checks/ai-hallucinations.d.ts +27 -0
  115. package/dist/src/lib/analyzers/javascript/quality-checks/ai-hallucinations.d.ts.map +1 -0
  116. package/dist/src/lib/analyzers/javascript/quality-checks/ai-hallucinations.js +123 -0
  117. package/dist/src/lib/analyzers/javascript/quality-checks/ai-hallucinations.js.map +1 -0
  118. package/dist/src/lib/analyzers/javascript/quality-checks/async-patterns.d.ts +44 -0
  119. package/dist/src/lib/analyzers/javascript/quality-checks/async-patterns.d.ts.map +1 -0
  120. package/dist/src/lib/analyzers/javascript/quality-checks/async-patterns.js +224 -0
  121. package/dist/src/lib/analyzers/javascript/quality-checks/async-patterns.js.map +1 -0
  122. package/dist/src/lib/analyzers/javascript/quality-checks/code-patterns.d.ts +50 -0
  123. package/dist/src/lib/analyzers/javascript/quality-checks/code-patterns.d.ts.map +1 -0
  124. package/dist/src/lib/analyzers/javascript/quality-checks/code-patterns.js +284 -0
  125. package/dist/src/lib/analyzers/javascript/quality-checks/code-patterns.js.map +1 -0
  126. package/dist/src/lib/analyzers/javascript/quality-checks/comparison-issues.d.ts +27 -0
  127. package/dist/src/lib/analyzers/javascript/quality-checks/comparison-issues.d.ts.map +1 -0
  128. package/dist/src/lib/analyzers/javascript/quality-checks/comparison-issues.js +86 -0
  129. package/dist/src/lib/analyzers/javascript/quality-checks/comparison-issues.js.map +1 -0
  130. package/dist/src/lib/analyzers/javascript/quality-checks/reference-errors.d.ts +32 -0
  131. package/dist/src/lib/analyzers/javascript/quality-checks/reference-errors.d.ts.map +1 -0
  132. package/dist/src/lib/analyzers/javascript/quality-checks/reference-errors.js +44 -0
  133. package/dist/src/lib/analyzers/javascript/quality-checks/reference-errors.js.map +1 -0
  134. package/dist/src/lib/analyzers/javascript/security-checks/access-control.d.ts +22 -0
  135. package/dist/src/lib/analyzers/javascript/security-checks/access-control.d.ts.map +1 -0
  136. package/dist/src/lib/analyzers/javascript/security-checks/access-control.js +168 -0
  137. package/dist/src/lib/analyzers/javascript/security-checks/access-control.js.map +1 -0
  138. package/dist/src/lib/analyzers/javascript/security-checks/ai-generated-code.d.ts +25 -0
  139. package/dist/src/lib/analyzers/javascript/security-checks/ai-generated-code.d.ts.map +1 -0
  140. package/dist/src/lib/analyzers/javascript/security-checks/ai-generated-code.js +232 -0
  141. package/dist/src/lib/analyzers/javascript/security-checks/ai-generated-code.js.map +1 -0
  142. package/dist/src/lib/analyzers/javascript/security-checks/authentication-failures.d.ts +27 -0
  143. package/dist/src/lib/analyzers/javascript/security-checks/authentication-failures.d.ts.map +1 -0
  144. package/dist/src/lib/analyzers/javascript/security-checks/authentication-failures.js +222 -0
  145. package/dist/src/lib/analyzers/javascript/security-checks/authentication-failures.js.map +1 -0
  146. package/dist/src/lib/analyzers/javascript/security-checks/credential-crypto.d.ts +28 -0
  147. package/dist/src/lib/analyzers/javascript/security-checks/credential-crypto.d.ts.map +1 -0
  148. package/dist/src/lib/analyzers/javascript/security-checks/credential-crypto.js +176 -0
  149. package/dist/src/lib/analyzers/javascript/security-checks/credential-crypto.js.map +1 -0
  150. package/dist/src/lib/analyzers/javascript/security-checks/enhanced-supply-chain.d.ts +23 -0
  151. package/dist/src/lib/analyzers/javascript/security-checks/enhanced-supply-chain.d.ts.map +1 -0
  152. package/dist/src/lib/analyzers/javascript/security-checks/enhanced-supply-chain.js +113 -0
  153. package/dist/src/lib/analyzers/javascript/security-checks/enhanced-supply-chain.js.map +1 -0
  154. package/dist/src/lib/analyzers/javascript/security-checks/exception-handling.d.ts +28 -0
  155. package/dist/src/lib/analyzers/javascript/security-checks/exception-handling.d.ts.map +1 -0
  156. package/dist/src/lib/analyzers/javascript/security-checks/exception-handling.js +227 -0
  157. package/dist/src/lib/analyzers/javascript/security-checks/exception-handling.js.map +1 -0
  158. package/dist/src/lib/analyzers/javascript/security-checks/injection-attacks.d.ts +32 -0
  159. package/dist/src/lib/analyzers/javascript/security-checks/injection-attacks.d.ts.map +1 -0
  160. package/dist/src/lib/analyzers/javascript/security-checks/injection-attacks.js +260 -0
  161. package/dist/src/lib/analyzers/javascript/security-checks/injection-attacks.js.map +1 -0
  162. package/dist/src/lib/analyzers/javascript/security-checks/insecure-design.d.ts +26 -0
  163. package/dist/src/lib/analyzers/javascript/security-checks/insecure-design.d.ts.map +1 -0
  164. package/dist/src/lib/analyzers/javascript/security-checks/insecure-design.js +164 -0
  165. package/dist/src/lib/analyzers/javascript/security-checks/insecure-design.js.map +1 -0
  166. package/dist/src/lib/analyzers/javascript/security-checks/security-misconfiguration.d.ts +26 -0
  167. package/dist/src/lib/analyzers/javascript/security-checks/security-misconfiguration.d.ts.map +1 -0
  168. package/dist/src/lib/analyzers/javascript/security-checks/security-misconfiguration.js +775 -0
  169. package/dist/src/lib/analyzers/javascript/security-checks/security-misconfiguration.js.map +1 -0
  170. package/dist/src/lib/analyzers/javascript/security-checks/software-integrity.d.ts +25 -0
  171. package/dist/src/lib/analyzers/javascript/security-checks/software-integrity.d.ts.map +1 -0
  172. package/dist/src/lib/analyzers/javascript/security-checks/software-integrity.js +168 -0
  173. package/dist/src/lib/analyzers/javascript/security-checks/software-integrity.js.map +1 -0
  174. package/dist/src/lib/analyzers/javascript/security-checks/storage-security.d.ts +27 -0
  175. package/dist/src/lib/analyzers/javascript/security-checks/storage-security.d.ts.map +1 -0
  176. package/dist/src/lib/analyzers/javascript/security-checks/storage-security.js +108 -0
  177. package/dist/src/lib/analyzers/javascript/security-checks/storage-security.js.map +1 -0
  178. package/dist/src/lib/analyzers/javascript/security-checks/xss-dom-security.d.ts +28 -0
  179. package/dist/src/lib/analyzers/javascript/security-checks/xss-dom-security.d.ts.map +1 -0
  180. package/dist/src/lib/analyzers/javascript/security-checks/xss-dom-security.js +143 -0
  181. package/dist/src/lib/analyzers/javascript/security-checks/xss-dom-security.js.map +1 -0
  182. package/dist/src/lib/analyzers/javascript/syntax/syntax-helpers.d.ts +53 -0
  183. package/dist/src/lib/analyzers/javascript/syntax/syntax-helpers.d.ts.map +1 -0
  184. package/dist/src/lib/analyzers/javascript/syntax/syntax-helpers.js +144 -0
  185. package/dist/src/lib/analyzers/javascript/syntax/syntax-helpers.js.map +1 -0
  186. package/dist/src/lib/analyzers/javascript/syntax/typescript-syntax.d.ts +72 -0
  187. package/dist/src/lib/analyzers/javascript/syntax/typescript-syntax.d.ts.map +1 -0
  188. package/dist/src/lib/analyzers/javascript/syntax/typescript-syntax.js +314 -0
  189. package/dist/src/lib/analyzers/javascript/syntax/typescript-syntax.js.map +1 -0
  190. package/dist/src/lib/analyzers/javascript/utils/createVulnerability.d.ts +58 -0
  191. package/dist/src/lib/analyzers/javascript/utils/createVulnerability.d.ts.map +1 -0
  192. package/dist/src/lib/analyzers/javascript/utils/createVulnerability.js +71 -0
  193. package/dist/src/lib/analyzers/javascript/utils/createVulnerability.js.map +1 -0
  194. package/dist/src/lib/analyzers/javascript/utils/metrics-calculator.d.ts +36 -0
  195. package/dist/src/lib/analyzers/javascript/utils/metrics-calculator.d.ts.map +1 -0
  196. package/dist/src/lib/analyzers/javascript/utils/metrics-calculator.js +70 -0
  197. package/dist/src/lib/analyzers/javascript/utils/metrics-calculator.js.map +1 -0
  198. package/dist/src/lib/analyzers/javascript/utils/performance-analyzer.d.ts +29 -0
  199. package/dist/src/lib/analyzers/javascript/utils/performance-analyzer.d.ts.map +1 -0
  200. package/dist/src/lib/analyzers/javascript/utils/performance-analyzer.js +55 -0
  201. package/dist/src/lib/analyzers/javascript/utils/performance-analyzer.js.map +1 -0
  202. package/dist/src/lib/analyzers/javascript-analyzer.d.ts +95 -0
  203. package/dist/src/lib/analyzers/javascript-analyzer.d.ts.map +1 -0
  204. package/dist/src/lib/analyzers/javascript-analyzer.js +2141 -0
  205. package/dist/src/lib/analyzers/javascript-analyzer.js.map +1 -0
  206. package/dist/src/lib/analyzers/python/security-checks/access-control.d.ts +21 -0
  207. package/dist/src/lib/analyzers/python/security-checks/access-control.d.ts.map +1 -0
  208. package/dist/src/lib/analyzers/python/security-checks/access-control.js +305 -0
  209. package/dist/src/lib/analyzers/python/security-checks/access-control.js.map +1 -0
  210. package/dist/src/lib/analyzers/python/security-checks/ai-generated-code.d.ts +25 -0
  211. package/dist/src/lib/analyzers/python/security-checks/ai-generated-code.d.ts.map +1 -0
  212. package/dist/src/lib/analyzers/python/security-checks/ai-generated-code.js +242 -0
  213. package/dist/src/lib/analyzers/python/security-checks/ai-generated-code.js.map +1 -0
  214. package/dist/src/lib/analyzers/python/security-checks/authentication-flaws.d.ts +24 -0
  215. package/dist/src/lib/analyzers/python/security-checks/authentication-flaws.d.ts.map +1 -0
  216. package/dist/src/lib/analyzers/python/security-checks/authentication-flaws.js +207 -0
  217. package/dist/src/lib/analyzers/python/security-checks/authentication-flaws.js.map +1 -0
  218. package/dist/src/lib/analyzers/python/security-checks/code-quality.d.ts +27 -0
  219. package/dist/src/lib/analyzers/python/security-checks/code-quality.d.ts.map +1 -0
  220. package/dist/src/lib/analyzers/python/security-checks/code-quality.js +206 -0
  221. package/dist/src/lib/analyzers/python/security-checks/code-quality.js.map +1 -0
  222. package/dist/src/lib/analyzers/python/security-checks/credentials-crypto.d.ts +24 -0
  223. package/dist/src/lib/analyzers/python/security-checks/credentials-crypto.d.ts.map +1 -0
  224. package/dist/src/lib/analyzers/python/security-checks/credentials-crypto.js +113 -0
  225. package/dist/src/lib/analyzers/python/security-checks/credentials-crypto.js.map +1 -0
  226. package/dist/src/lib/analyzers/python/security-checks/crypto-failures.d.ts +20 -0
  227. package/dist/src/lib/analyzers/python/security-checks/crypto-failures.d.ts.map +1 -0
  228. package/dist/src/lib/analyzers/python/security-checks/crypto-failures.js +129 -0
  229. package/dist/src/lib/analyzers/python/security-checks/crypto-failures.js.map +1 -0
  230. package/dist/src/lib/analyzers/python/security-checks/data-integrity.d.ts +19 -0
  231. package/dist/src/lib/analyzers/python/security-checks/data-integrity.d.ts.map +1 -0
  232. package/dist/src/lib/analyzers/python/security-checks/data-integrity.js +90 -0
  233. package/dist/src/lib/analyzers/python/security-checks/data-integrity.js.map +1 -0
  234. package/dist/src/lib/analyzers/python/security-checks/deserialization.d.ts +20 -0
  235. package/dist/src/lib/analyzers/python/security-checks/deserialization.d.ts.map +1 -0
  236. package/dist/src/lib/analyzers/python/security-checks/deserialization.js +68 -0
  237. package/dist/src/lib/analyzers/python/security-checks/deserialization.js.map +1 -0
  238. package/dist/src/lib/analyzers/python/security-checks/django-security.d.ts +25 -0
  239. package/dist/src/lib/analyzers/python/security-checks/django-security.d.ts.map +1 -0
  240. package/dist/src/lib/analyzers/python/security-checks/django-security.js +180 -0
  241. package/dist/src/lib/analyzers/python/security-checks/django-security.js.map +1 -0
  242. package/dist/src/lib/analyzers/python/security-checks/enhanced-supply-chain.d.ts +23 -0
  243. package/dist/src/lib/analyzers/python/security-checks/enhanced-supply-chain.d.ts.map +1 -0
  244. package/dist/src/lib/analyzers/python/security-checks/enhanced-supply-chain.js +127 -0
  245. package/dist/src/lib/analyzers/python/security-checks/enhanced-supply-chain.js.map +1 -0
  246. package/dist/src/lib/analyzers/python/security-checks/exception-handling.d.ts +23 -0
  247. package/dist/src/lib/analyzers/python/security-checks/exception-handling.d.ts.map +1 -0
  248. package/dist/src/lib/analyzers/python/security-checks/exception-handling.js +120 -0
  249. package/dist/src/lib/analyzers/python/security-checks/exception-handling.js.map +1 -0
  250. package/dist/src/lib/analyzers/python/security-checks/flask-security.d.ts +24 -0
  251. package/dist/src/lib/analyzers/python/security-checks/flask-security.d.ts.map +1 -0
  252. package/dist/src/lib/analyzers/python/security-checks/flask-security.js +143 -0
  253. package/dist/src/lib/analyzers/python/security-checks/flask-security.js.map +1 -0
  254. package/dist/src/lib/analyzers/python/security-checks/injection-attacks.d.ts +28 -0
  255. package/dist/src/lib/analyzers/python/security-checks/injection-attacks.d.ts.map +1 -0
  256. package/dist/src/lib/analyzers/python/security-checks/injection-attacks.js +174 -0
  257. package/dist/src/lib/analyzers/python/security-checks/injection-attacks.js.map +1 -0
  258. package/dist/src/lib/analyzers/python/security-checks/insecure-design.d.ts +20 -0
  259. package/dist/src/lib/analyzers/python/security-checks/insecure-design.d.ts.map +1 -0
  260. package/dist/src/lib/analyzers/python/security-checks/insecure-design.js +160 -0
  261. package/dist/src/lib/analyzers/python/security-checks/insecure-design.js.map +1 -0
  262. package/dist/src/lib/analyzers/python/security-checks/logging-failures.d.ts +20 -0
  263. package/dist/src/lib/analyzers/python/security-checks/logging-failures.d.ts.map +1 -0
  264. package/dist/src/lib/analyzers/python/security-checks/logging-failures.js +121 -0
  265. package/dist/src/lib/analyzers/python/security-checks/logging-failures.js.map +1 -0
  266. package/dist/src/lib/analyzers/python/security-checks/nosql-injection.d.ts +26 -0
  267. package/dist/src/lib/analyzers/python/security-checks/nosql-injection.d.ts.map +1 -0
  268. package/dist/src/lib/analyzers/python/security-checks/nosql-injection.js +248 -0
  269. package/dist/src/lib/analyzers/python/security-checks/nosql-injection.js.map +1 -0
  270. package/dist/src/lib/analyzers/python/security-checks/security-misconfiguration.d.ts +26 -0
  271. package/dist/src/lib/analyzers/python/security-checks/security-misconfiguration.d.ts.map +1 -0
  272. package/dist/src/lib/analyzers/python/security-checks/security-misconfiguration.js +375 -0
  273. package/dist/src/lib/analyzers/python/security-checks/security-misconfiguration.js.map +1 -0
  274. package/dist/src/lib/analyzers/python/security-checks/ssrf-detection.d.ts +26 -0
  275. package/dist/src/lib/analyzers/python/security-checks/ssrf-detection.d.ts.map +1 -0
  276. package/dist/src/lib/analyzers/python/security-checks/ssrf-detection.js +160 -0
  277. package/dist/src/lib/analyzers/python/security-checks/ssrf-detection.js.map +1 -0
  278. package/dist/src/lib/analyzers/python/security-checks/web-security.d.ts +23 -0
  279. package/dist/src/lib/analyzers/python/security-checks/web-security.d.ts.map +1 -0
  280. package/dist/src/lib/analyzers/python/security-checks/web-security.js +117 -0
  281. package/dist/src/lib/analyzers/python/security-checks/web-security.js.map +1 -0
  282. package/dist/src/lib/analyzers/python/utils/createVulnerability.d.ts +58 -0
  283. package/dist/src/lib/analyzers/python/utils/createVulnerability.d.ts.map +1 -0
  284. package/dist/src/lib/analyzers/python/utils/createVulnerability.js +71 -0
  285. package/dist/src/lib/analyzers/python/utils/createVulnerability.js.map +1 -0
  286. package/dist/src/lib/analyzers/python-analyzer.d.ts +111 -0
  287. package/dist/src/lib/analyzers/python-analyzer.d.ts.map +1 -0
  288. package/dist/src/lib/analyzers/python-analyzer.js +1600 -0
  289. package/dist/src/lib/analyzers/python-analyzer.js.map +1 -0
  290. package/dist/src/lib/analyzers/secrets/patterns/api-keys/ai-providers.d.ts +14 -0
  291. package/dist/src/lib/analyzers/secrets/patterns/api-keys/ai-providers.d.ts.map +1 -0
  292. package/dist/src/lib/analyzers/secrets/patterns/api-keys/ai-providers.js +47 -0
  293. package/dist/src/lib/analyzers/secrets/patterns/api-keys/ai-providers.js.map +1 -0
  294. package/dist/src/lib/analyzers/secrets/patterns/api-keys/aws.d.ts +13 -0
  295. package/dist/src/lib/analyzers/secrets/patterns/api-keys/aws.d.ts.map +1 -0
  296. package/dist/src/lib/analyzers/secrets/patterns/api-keys/aws.js +36 -0
  297. package/dist/src/lib/analyzers/secrets/patterns/api-keys/aws.js.map +1 -0
  298. package/dist/src/lib/analyzers/secrets/patterns/api-keys/cloud-providers.d.ts +15 -0
  299. package/dist/src/lib/analyzers/secrets/patterns/api-keys/cloud-providers.d.ts.map +1 -0
  300. package/dist/src/lib/analyzers/secrets/patterns/api-keys/cloud-providers.js +68 -0
  301. package/dist/src/lib/analyzers/secrets/patterns/api-keys/cloud-providers.js.map +1 -0
  302. package/dist/src/lib/analyzers/secrets/patterns/api-keys/communication.d.ts +15 -0
  303. package/dist/src/lib/analyzers/secrets/patterns/api-keys/communication.d.ts.map +1 -0
  304. package/dist/src/lib/analyzers/secrets/patterns/api-keys/communication.js +68 -0
  305. package/dist/src/lib/analyzers/secrets/patterns/api-keys/communication.js.map +1 -0
  306. package/dist/src/lib/analyzers/secrets/patterns/api-keys/generic.d.ts +12 -0
  307. package/dist/src/lib/analyzers/secrets/patterns/api-keys/generic.d.ts.map +1 -0
  308. package/dist/src/lib/analyzers/secrets/patterns/api-keys/generic.js +45 -0
  309. package/dist/src/lib/analyzers/secrets/patterns/api-keys/generic.js.map +1 -0
  310. package/dist/src/lib/analyzers/secrets/patterns/api-keys/github.d.ts +14 -0
  311. package/dist/src/lib/analyzers/secrets/patterns/api-keys/github.d.ts.map +1 -0
  312. package/dist/src/lib/analyzers/secrets/patterns/api-keys/github.js +47 -0
  313. package/dist/src/lib/analyzers/secrets/patterns/api-keys/github.js.map +1 -0
  314. package/dist/src/lib/analyzers/secrets/patterns/api-keys/stripe.d.ts +13 -0
  315. package/dist/src/lib/analyzers/secrets/patterns/api-keys/stripe.d.ts.map +1 -0
  316. package/dist/src/lib/analyzers/secrets/patterns/api-keys/stripe.js +36 -0
  317. package/dist/src/lib/analyzers/secrets/patterns/api-keys/stripe.js.map +1 -0
  318. package/dist/src/lib/analyzers/secrets/patterns/api-keys.d.ts +15 -0
  319. package/dist/src/lib/analyzers/secrets/patterns/api-keys.d.ts.map +1 -0
  320. package/dist/src/lib/analyzers/secrets/patterns/api-keys.js +32 -0
  321. package/dist/src/lib/analyzers/secrets/patterns/api-keys.js.map +1 -0
  322. package/dist/src/lib/analyzers/secrets/patterns/credentials.d.ts +15 -0
  323. package/dist/src/lib/analyzers/secrets/patterns/credentials.d.ts.map +1 -0
  324. package/dist/src/lib/analyzers/secrets/patterns/credentials.js +68 -0
  325. package/dist/src/lib/analyzers/secrets/patterns/credentials.js.map +1 -0
  326. package/dist/src/lib/analyzers/secrets/patterns/private-keys.d.ts +16 -0
  327. package/dist/src/lib/analyzers/secrets/patterns/private-keys.d.ts.map +1 -0
  328. package/dist/src/lib/analyzers/secrets/patterns/private-keys.js +79 -0
  329. package/dist/src/lib/analyzers/secrets/patterns/private-keys.js.map +1 -0
  330. package/dist/src/lib/analyzers/secrets/patterns/tokens.d.ts +15 -0
  331. package/dist/src/lib/analyzers/secrets/patterns/tokens.d.ts.map +1 -0
  332. package/dist/src/lib/analyzers/secrets/patterns/tokens.js +58 -0
  333. package/dist/src/lib/analyzers/secrets/patterns/tokens.js.map +1 -0
  334. package/dist/src/lib/analyzers/secrets/secrets-analyzer.d.ts +88 -0
  335. package/dist/src/lib/analyzers/secrets/secrets-analyzer.d.ts.map +1 -0
  336. package/dist/src/lib/analyzers/secrets/secrets-analyzer.js +162 -0
  337. package/dist/src/lib/analyzers/secrets/secrets-analyzer.js.map +1 -0
  338. package/dist/src/lib/analyzers/secrets/validators/context-checker.d.ts +56 -0
  339. package/dist/src/lib/analyzers/secrets/validators/context-checker.d.ts.map +1 -0
  340. package/dist/src/lib/analyzers/secrets/validators/context-checker.js +199 -0
  341. package/dist/src/lib/analyzers/secrets/validators/context-checker.js.map +1 -0
  342. package/dist/src/lib/analyzers/secrets/validators/entropy-checker.d.ts +56 -0
  343. package/dist/src/lib/analyzers/secrets/validators/entropy-checker.d.ts.map +1 -0
  344. package/dist/src/lib/analyzers/secrets/validators/entropy-checker.js +102 -0
  345. package/dist/src/lib/analyzers/secrets/validators/entropy-checker.js.map +1 -0
  346. package/dist/src/lib/analyzers/security-checks/es6-security.d.ts +38 -0
  347. package/dist/src/lib/analyzers/security-checks/es6-security.d.ts.map +1 -0
  348. package/dist/src/lib/analyzers/security-checks/es6-security.js +125 -0
  349. package/dist/src/lib/analyzers/security-checks/es6-security.js.map +1 -0
  350. package/dist/src/lib/analyzers/security-checks/python-async-security.d.ts +46 -0
  351. package/dist/src/lib/analyzers/security-checks/python-async-security.d.ts.map +1 -0
  352. package/dist/src/lib/analyzers/security-checks/python-async-security.js +92 -0
  353. package/dist/src/lib/analyzers/security-checks/python-async-security.js.map +1 -0
  354. package/dist/src/lib/analyzers/security-checks/react-security.d.ts +49 -0
  355. package/dist/src/lib/analyzers/security-checks/react-security.d.ts.map +1 -0
  356. package/dist/src/lib/analyzers/security-checks/react-security.js +125 -0
  357. package/dist/src/lib/analyzers/security-checks/react-security.js.map +1 -0
  358. package/dist/src/lib/analyzers/types.d.ts +92 -0
  359. package/dist/src/lib/analyzers/types.d.ts.map +1 -0
  360. package/dist/src/lib/analyzers/types.js +3 -0
  361. package/dist/src/lib/analyzers/types.js.map +1 -0
  362. package/dist/src/lib/analyzers/typescript/security-checks/access-control.d.ts +19 -0
  363. package/dist/src/lib/analyzers/typescript/security-checks/access-control.d.ts.map +1 -0
  364. package/dist/src/lib/analyzers/typescript/security-checks/access-control.js +210 -0
  365. package/dist/src/lib/analyzers/typescript/security-checks/access-control.js.map +1 -0
  366. package/dist/src/lib/analyzers/typescript/security-checks/ai-generated-code.d.ts +25 -0
  367. package/dist/src/lib/analyzers/typescript/security-checks/ai-generated-code.d.ts.map +1 -0
  368. package/dist/src/lib/analyzers/typescript/security-checks/ai-generated-code.js +242 -0
  369. package/dist/src/lib/analyzers/typescript/security-checks/ai-generated-code.js.map +1 -0
  370. package/dist/src/lib/analyzers/typescript/security-checks/authentication.d.ts +28 -0
  371. package/dist/src/lib/analyzers/typescript/security-checks/authentication.d.ts.map +1 -0
  372. package/dist/src/lib/analyzers/typescript/security-checks/authentication.js +357 -0
  373. package/dist/src/lib/analyzers/typescript/security-checks/authentication.js.map +1 -0
  374. package/dist/src/lib/analyzers/typescript/security-checks/code-injection.d.ts +26 -0
  375. package/dist/src/lib/analyzers/typescript/security-checks/code-injection.d.ts.map +1 -0
  376. package/dist/src/lib/analyzers/typescript/security-checks/code-injection.js +380 -0
  377. package/dist/src/lib/analyzers/typescript/security-checks/code-injection.js.map +1 -0
  378. package/dist/src/lib/analyzers/typescript/security-checks/code-quality.d.ts +23 -0
  379. package/dist/src/lib/analyzers/typescript/security-checks/code-quality.d.ts.map +1 -0
  380. package/dist/src/lib/analyzers/typescript/security-checks/code-quality.js +109 -0
  381. package/dist/src/lib/analyzers/typescript/security-checks/code-quality.js.map +1 -0
  382. package/dist/src/lib/analyzers/typescript/security-checks/credentials-crypto.d.ts +21 -0
  383. package/dist/src/lib/analyzers/typescript/security-checks/credentials-crypto.d.ts.map +1 -0
  384. package/dist/src/lib/analyzers/typescript/security-checks/credentials-crypto.js +153 -0
  385. package/dist/src/lib/analyzers/typescript/security-checks/credentials-crypto.js.map +1 -0
  386. package/dist/src/lib/analyzers/typescript/security-checks/enhanced-supply-chain.d.ts +23 -0
  387. package/dist/src/lib/analyzers/typescript/security-checks/enhanced-supply-chain.d.ts.map +1 -0
  388. package/dist/src/lib/analyzers/typescript/security-checks/enhanced-supply-chain.js +146 -0
  389. package/dist/src/lib/analyzers/typescript/security-checks/enhanced-supply-chain.js.map +1 -0
  390. package/dist/src/lib/analyzers/typescript/security-checks/exception-handling.d.ts +23 -0
  391. package/dist/src/lib/analyzers/typescript/security-checks/exception-handling.d.ts.map +1 -0
  392. package/dist/src/lib/analyzers/typescript/security-checks/exception-handling.js +187 -0
  393. package/dist/src/lib/analyzers/typescript/security-checks/exception-handling.js.map +1 -0
  394. package/dist/src/lib/analyzers/typescript/security-checks/information-disclosure.d.ts +19 -0
  395. package/dist/src/lib/analyzers/typescript/security-checks/information-disclosure.d.ts.map +1 -0
  396. package/dist/src/lib/analyzers/typescript/security-checks/information-disclosure.js +97 -0
  397. package/dist/src/lib/analyzers/typescript/security-checks/information-disclosure.js.map +1 -0
  398. package/dist/src/lib/analyzers/typescript/security-checks/injection-attacks.d.ts +29 -0
  399. package/dist/src/lib/analyzers/typescript/security-checks/injection-attacks.d.ts.map +1 -0
  400. package/dist/src/lib/analyzers/typescript/security-checks/injection-attacks.js +319 -0
  401. package/dist/src/lib/analyzers/typescript/security-checks/injection-attacks.js.map +1 -0
  402. package/dist/src/lib/analyzers/typescript/security-checks/logging-failures.d.ts +21 -0
  403. package/dist/src/lib/analyzers/typescript/security-checks/logging-failures.d.ts.map +1 -0
  404. package/dist/src/lib/analyzers/typescript/security-checks/logging-failures.js +121 -0
  405. package/dist/src/lib/analyzers/typescript/security-checks/logging-failures.js.map +1 -0
  406. package/dist/src/lib/analyzers/typescript/security-checks/security-misconfiguration.d.ts +27 -0
  407. package/dist/src/lib/analyzers/typescript/security-checks/security-misconfiguration.d.ts.map +1 -0
  408. package/dist/src/lib/analyzers/typescript/security-checks/security-misconfiguration.js +213 -0
  409. package/dist/src/lib/analyzers/typescript/security-checks/security-misconfiguration.js.map +1 -0
  410. package/dist/src/lib/analyzers/typescript/security-checks/type-security.d.ts +19 -0
  411. package/dist/src/lib/analyzers/typescript/security-checks/type-security.d.ts.map +1 -0
  412. package/dist/src/lib/analyzers/typescript/security-checks/type-security.js +59 -0
  413. package/dist/src/lib/analyzers/typescript/security-checks/type-security.js.map +1 -0
  414. package/dist/src/lib/analyzers/typescript/type-checker.d.ts +17 -0
  415. package/dist/src/lib/analyzers/typescript/type-checker.d.ts.map +1 -0
  416. package/dist/src/lib/analyzers/typescript/type-checker.js +515 -0
  417. package/dist/src/lib/analyzers/typescript/type-checker.js.map +1 -0
  418. package/dist/src/lib/analyzers/typescript/utils/createVulnerability.d.ts +58 -0
  419. package/dist/src/lib/analyzers/typescript/utils/createVulnerability.d.ts.map +1 -0
  420. package/dist/src/lib/analyzers/typescript/utils/createVulnerability.js +71 -0
  421. package/dist/src/lib/analyzers/typescript/utils/createVulnerability.js.map +1 -0
  422. package/dist/src/lib/analyzers/typescript-analyzer.d.ts +116 -0
  423. package/dist/src/lib/analyzers/typescript-analyzer.d.ts.map +1 -0
  424. package/dist/src/lib/analyzers/typescript-analyzer.js +1660 -0
  425. package/dist/src/lib/analyzers/typescript-analyzer.js.map +1 -0
  426. package/dist/src/lib/security/compliance-mapping.d.ts +29 -0
  427. package/dist/src/lib/security/compliance-mapping.d.ts.map +1 -0
  428. package/dist/src/lib/security/compliance-mapping.js +1342 -0
  429. package/dist/src/lib/security/compliance-mapping.js.map +1 -0
  430. package/dist/src/lib/security/severity-scoring.d.ts +47 -0
  431. package/dist/src/lib/security/severity-scoring.d.ts.map +1 -0
  432. package/dist/src/lib/security/severity-scoring.js +965 -0
  433. package/dist/src/lib/security/severity-scoring.js.map +1 -0
  434. package/dist/src/lib/standards/references.d.ts +16 -0
  435. package/dist/src/lib/standards/references.d.ts.map +1 -0
  436. package/dist/src/lib/standards/references.js +1161 -0
  437. package/dist/src/lib/standards/references.js.map +1 -0
  438. package/dist/src/lib/types/index.d.ts +167 -0
  439. package/dist/src/lib/types/index.d.ts.map +1 -0
  440. package/dist/src/lib/types/index.js +3 -0
  441. package/dist/src/lib/types/index.js.map +1 -0
  442. package/dist/src/lib/utils/code-cleaner.d.ts +59 -0
  443. package/dist/src/lib/utils/code-cleaner.d.ts.map +1 -0
  444. package/dist/src/lib/utils/code-cleaner.js +283 -0
  445. package/dist/src/lib/utils/code-cleaner.js.map +1 -0
  446. package/package.json +51 -0
  447. package/src/commands/auth.ts +308 -0
  448. package/src/commands/config.ts +226 -0
  449. package/src/commands/init.ts +202 -0
  450. package/src/commands/scan.ts +238 -0
  451. package/src/config/config-loader.ts +175 -0
  452. package/src/reporters/cli-reporter.ts +282 -0
  453. package/src/scanner/local-scanner.ts +250 -0
  454. package/tsconfig.json +24 -0
  455. package/tsconfig.tsbuildinfo +1 -0
@@ -0,0 +1,1660 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TypeScriptAnalyzer = void 0;
4
+ const references_1 = require("../standards/references");
5
+ const code_cleaner_1 = require("../utils/code-cleaner");
6
+ // Modular TypeScript Security Checks (2025-12-01)
7
+ const injection_attacks_1 = require("./typescript/security-checks/injection-attacks");
8
+ const credentials_crypto_1 = require("./typescript/security-checks/credentials-crypto");
9
+ const code_injection_1 = require("./typescript/security-checks/code-injection");
10
+ const code_quality_1 = require("./typescript/security-checks/code-quality");
11
+ const type_security_1 = require("./typescript/security-checks/type-security");
12
+ const security_misconfiguration_1 = require("./typescript/security-checks/security-misconfiguration");
13
+ const exception_handling_1 = require("./typescript/security-checks/exception-handling");
14
+ const enhanced_supply_chain_1 = require("./typescript/security-checks/enhanced-supply-chain");
15
+ const access_control_1 = require("./typescript/security-checks/access-control");
16
+ const information_disclosure_1 = require("./typescript/security-checks/information-disclosure");
17
+ const authentication_1 = require("./typescript/security-checks/authentication");
18
+ const logging_failures_1 = require("./typescript/security-checks/logging-failures");
19
+ const secrets_analyzer_1 = require("./secrets/secrets-analyzer");
20
+ const ai_generated_code_1 = require("./typescript/security-checks/ai-generated-code");
21
+ // TypeScript Compiler API Integration (2025-12-02)
22
+ const type_checker_1 = require("./typescript/type-checker");
23
+ class TypeScriptAnalyzer {
24
+ constructor() {
25
+ this.language = 'typescript';
26
+ }
27
+ /**
28
+ * Remove string literal content from a line of code
29
+ * This prevents false positives when analyzing string content as code
30
+ * Example: 'MyP@ssw0rd!' → ' ' (preserves quotes, replaces content with spaces)
31
+ *
32
+ * FIX (2025-11-18): Added to fix false positive detection of ! in string literals
33
+ * Bug: "const PASSWORD = 'MyP@ssw0rd!';" was detected as non-null assertion
34
+ */
35
+ removeStringLiterals(line) {
36
+ let result = '';
37
+ let inString = false;
38
+ let stringChar = '';
39
+ let escaped = false;
40
+ for (let i = 0; i < line.length; i++) {
41
+ const char = line[i];
42
+ // Handle escape sequences
43
+ if (escaped) {
44
+ result += inString ? ' ' : char;
45
+ escaped = false;
46
+ continue;
47
+ }
48
+ if (char === '\\') {
49
+ escaped = true;
50
+ result += inString ? ' ' : char;
51
+ continue;
52
+ }
53
+ // Handle string delimiters
54
+ if (char === '"' || char === "'" || char === '`') {
55
+ if (!inString) {
56
+ inString = true;
57
+ stringChar = char;
58
+ result += char; // Keep the quote
59
+ }
60
+ else if (char === stringChar) {
61
+ inString = false;
62
+ stringChar = '';
63
+ result += char; // Keep the quote
64
+ }
65
+ else {
66
+ result += ' '; // Replace with space
67
+ }
68
+ continue;
69
+ }
70
+ // Inside string - replace content with spaces
71
+ if (inString) {
72
+ result += ' ';
73
+ }
74
+ else {
75
+ result += char;
76
+ }
77
+ }
78
+ return result;
79
+ }
80
+ async analyze(input) {
81
+ const result = {
82
+ syntax: { valid: true, errors: [], lineErrors: [] },
83
+ quality: { score: 100, issues: [] },
84
+ performance: { score: 100, suggestions: [] },
85
+ security: { vulnerabilities: [] },
86
+ metrics: { complexity: 1, maintainability: 100, lines: 0, functions: 0 }
87
+ };
88
+ try {
89
+ // CRITICAL (Dec 30, 2025): ALL analysis methods run independently
90
+ // Security checks MUST run even if type errors exist
91
+ // User testing revealed: "Both security AND type errors should be detected simultaneously"
92
+ // Fix: Ensure no early returns skip security analysis
93
+ this.analyzeSyntax(input.code, result);
94
+ this.analyzeQuality(input.code, result);
95
+ this.analyzePerformance(input.code, result);
96
+ // ALWAYS run security analysis, regardless of syntax/type errors
97
+ this.analyzeSecurity(input.code, result);
98
+ this.calculateMetrics(input.code, result);
99
+ // AI-Generated Code Detection (Phase 1.5, Week 5-7)
100
+ const lines = input.code.split('\n');
101
+ result.security.vulnerabilities.push(...(0, ai_generated_code_1.checkAIGeneratedCode)(lines, input.filename));
102
+ }
103
+ catch (error) {
104
+ const errorMessage = error instanceof Error ? error.message : 'Unknown error';
105
+ result.syntax.valid = false;
106
+ result.syntax.errors.push(`TypeScript analysis error: ${errorMessage}`);
107
+ }
108
+ return result;
109
+ }
110
+ async validateSyntax(code) {
111
+ // Basic TypeScript syntax checks
112
+ const lines = code.split('\n');
113
+ for (let i = 0; i < lines.length; i++) {
114
+ const line = lines[i].trim();
115
+ if (!line || line.startsWith('//'))
116
+ continue;
117
+ // Check basic type annotations
118
+ if (line.match(/:\s*[A-Z]\w*\s*=/) && !line.includes('interface') && !line.includes('type')) {
119
+ return true; // Valid TypeScript type annotation
120
+ }
121
+ }
122
+ return true;
123
+ }
124
+ getLanguageInfo() {
125
+ return {
126
+ name: 'TypeScript',
127
+ extensions: ['.ts', '.tsx', '.d.ts'],
128
+ description: 'Typed superset of JavaScript for scalable applications'
129
+ };
130
+ }
131
+ analyzeSyntax(code, result) {
132
+ const errors = [];
133
+ const lineErrors = [];
134
+ // TypeScript-specific advanced detection (16 methods)
135
+ // PHASE 6 WEEK 1 DAY 1: Added duplicate identifier detection
136
+ this.detectTypeErrors(code, lineErrors);
137
+ this.detectTypeAssertions(code, lineErrors);
138
+ this.detectGenericIssues(code, lineErrors);
139
+ this.detectUnionIntersectionIssues(code, lineErrors);
140
+ this.detectClassInterfaceIssues(code, lineErrors);
141
+ this.detectAsyncPromiseIssues(code, lineErrors);
142
+ this.detectModuleIssues(code, lineErrors);
143
+ this.detectDecoratorIssues(code, lineErrors);
144
+ this.detectMappedConditionalTypes(code, lineErrors);
145
+ this.detectStrictModeViolations(code, lineErrors);
146
+ this.detectAnyPropagation(code, lineErrors);
147
+ this.detectPerformanceIssues(code, lineErrors);
148
+ this.detectNamingConventions(code, lineErrors);
149
+ this.detectConfigurationIssues(code, lineErrors);
150
+ this.detectReactTypeScriptIssues(code, lineErrors);
151
+ this.detectDuplicateIdentifiers(code, lineErrors); // PHASE 6: NEW
152
+ // Balance checks
153
+ this.checkBracketBalance(code, errors, lineErrors);
154
+ result.syntax.errors = errors;
155
+ result.syntax.lineErrors = lineErrors;
156
+ result.syntax.valid = errors.length === 0 && lineErrors.filter(e => e.severity === 'error').length === 0;
157
+ if (!result.syntax.valid || lineErrors.length > 0) {
158
+ result.quality.score -= lineErrors.length * 15;
159
+ }
160
+ }
161
+ /**
162
+ * Detect type errors - Type assignability, null/undefined, property access
163
+ */
164
+ detectTypeErrors(code, lineErrors) {
165
+ const lines = code.split('\n');
166
+ lines.forEach((line, index) => {
167
+ const lineNumber = index + 1;
168
+ if (line.trim().startsWith('//'))
169
+ return;
170
+ // Detect unsafe null/undefined access
171
+ if (line.match(/\.\w+/) && !line.includes('?.') && !line.includes('if') && !line.includes('&&')) {
172
+ const prevLines = lines.slice(Math.max(0, index - 3), index);
173
+ const hasNullCheck = prevLines.some(l => l.includes('!= null') || l.includes('!== undefined'));
174
+ if (!hasNullCheck && line.includes('get') && !line.includes('Optional')) {
175
+ lineErrors.push({
176
+ line: lineNumber,
177
+ error: 'Potentially unsafe access: property may be null/undefined',
178
+ suggestion: 'Use optional chaining (?.) or check for null: if (obj != null) { ... }',
179
+ severity: 'warning',
180
+ references: references_1.typescriptStandards['type-errors'] || [],
181
+ securityRelevant: false
182
+ });
183
+ }
184
+ }
185
+ // Detect missing type annotations on function parameters
186
+ if (line.match(/function\s+\w+\s*\([^)]*\w+[^:)]*\)/) || line.match(/\(\s*\w+\s*\)\s*=>/)) {
187
+ const hasTypeAnnotation = line.match(/:\s*\w+/);
188
+ if (!hasTypeAnnotation && !line.includes('any')) {
189
+ lineErrors.push({
190
+ line: lineNumber,
191
+ error: 'Function parameter missing type annotation',
192
+ suggestion: 'Add type to parameter: (param: string) => ...',
193
+ severity: 'info',
194
+ references: references_1.typescriptStandards['type-errors'] || [],
195
+ securityRelevant: false
196
+ });
197
+ }
198
+ }
199
+ // FIX (2025-11-18): Detect assignment in condition (= instead of == or ===)
200
+ // Pattern: if (variable = value) or while (variable = value)
201
+ // This is a critical bug where = (assignment) is used instead of === (comparison)
202
+ const assignmentInCondition = line.match(/\b(if|while|for)\s*\([^)]*[^=!<>]=[^=][^)]*\)/);
203
+ if (assignmentInCondition) {
204
+ // Verify it's not part of an arrow function or initialization (for loops)
205
+ const isForLoopInit = assignmentInCondition[1] === 'for' && (line.includes('let ') || line.includes('var ') || line.includes('const '));
206
+ const isArrowFunction = line.includes('=>');
207
+ if (!isForLoopInit && !isArrowFunction) {
208
+ lineErrors.push({
209
+ line: lineNumber,
210
+ error: 'Assignment in condition - did you mean === or == ?',
211
+ suggestion: 'Use === for comparison. If assignment is intentional, wrap in parentheses: if ((x = getValue()))',
212
+ severity: 'error',
213
+ references: references_1.typescriptStandards['type-errors'] || [],
214
+ securityRelevant: false
215
+ });
216
+ }
217
+ }
218
+ // Detect type compatibility issues with common patterns
219
+ if (line.includes('=') && line.includes(':') && !line.includes('//')) {
220
+ // Check for common type mismatches
221
+ if (line.match(/:\s*string.*=\s*\d+/) || line.match(/:\s*number.*=\s*["']/)) {
222
+ lineErrors.push({
223
+ line: lineNumber,
224
+ error: 'Type incompatibility: value does not match type annotation',
225
+ suggestion: 'Ensure the value matches the declared type',
226
+ severity: 'error',
227
+ references: references_1.typescriptStandards['type-errors'] || [],
228
+ securityRelevant: false
229
+ });
230
+ }
231
+ }
232
+ // FIX (2025-11-18): Detect type guard bypass pattern
233
+ // Pattern: function that returns boolean but should use type predicate
234
+ // Example: function isString(value: unknown): boolean { return typeof value === 'string'; }
235
+ // Should be: function isString(value: unknown): value is string { ... }
236
+ const typeGuardPattern = line.match(/function\s+(\w+)\s*\([^)]*(\w+):\s*(unknown|any)[^)]*\):\s*boolean/);
237
+ if (typeGuardPattern) {
238
+ const functionName = typeGuardPattern[1];
239
+ const paramName = typeGuardPattern[2];
240
+ // Check next 5 lines for typeof checks (function body)
241
+ const nextLines = lines.slice(index, Math.min(index + 6, lines.length));
242
+ const hasTypeOfCheck = nextLines.some(l => l.includes('typeof') && (l.includes("=== 'string'") ||
243
+ l.includes("=== 'number'") ||
244
+ l.includes("=== 'boolean'") ||
245
+ l.includes("=== 'object'") ||
246
+ l.includes('instanceof')));
247
+ if (hasTypeOfCheck) {
248
+ // Determine the type being checked
249
+ let detectedType = 'Type';
250
+ if (nextLines.some(l => l.includes("=== 'string'")))
251
+ detectedType = 'string';
252
+ else if (nextLines.some(l => l.includes("=== 'number'")))
253
+ detectedType = 'number';
254
+ else if (nextLines.some(l => l.includes("=== 'boolean'")))
255
+ detectedType = 'boolean';
256
+ else if (nextLines.some(l => l.includes("=== 'object'")))
257
+ detectedType = 'object';
258
+ lineErrors.push({
259
+ line: lineNumber,
260
+ error: `Type guard function should use type predicate instead of boolean`,
261
+ suggestion: `Change return type to: ${paramName} is ${detectedType}`,
262
+ severity: 'warning',
263
+ references: references_1.typescriptStandards['type-errors'] || [],
264
+ securityRelevant: false
265
+ });
266
+ }
267
+ }
268
+ // AI Hallucination: Check for .push() on strings (Python/list confusion)
269
+ // Strings in TS/JS are immutable, use += or array methods
270
+ // CRITICAL FIX: Remove comments before checking to prevent false positives
271
+ // Example: str += value; // ERROR: Don't use .push() on strings
272
+ // ^^^^^ This would trigger false positive!
273
+ const lineWithoutComments = code_cleaner_1.CodeCleaner.removeLineComments(line, 'javascript'); // TypeScript uses JS comment syntax
274
+ // Check current line for string indicators
275
+ const hasStringIndicator = lineWithoutComments.includes("''") || lineWithoutComments.includes('""') || lineWithoutComments.includes('``') ||
276
+ lineWithoutComments.match(/=\s*['"`]/) || lineWithoutComments.match(/:\s*string/);
277
+ // Check previous lines for string type annotations (multi-line function params)
278
+ let prevLineHasStringType = false;
279
+ if (index > 0) {
280
+ const prevLine = lines[index - 1];
281
+ prevLineHasStringType = prevLine.match(/:\s*string/) !== null;
282
+ }
283
+ if (lineWithoutComments.match(/(['"`].*['"`]|String\(|\.toString\(\)|\.toLowerCase\(\)|\.toUpperCase\(\)).*\.push\(/) ||
284
+ (lineWithoutComments.match(/\w+\.push\(/) && (hasStringIndicator || prevLineHasStringType))) {
285
+ lineErrors.push({
286
+ line: lineNumber,
287
+ error: 'AI Hallucination: .push() does not exist on TypeScript strings',
288
+ suggestion: 'Strings are immutable in TS. Use: str += value, str = str + value, or convert to array: str.split("").push()',
289
+ severity: 'error',
290
+ references: references_1.typescriptStandards['type-errors'] || [],
291
+ securityRelevant: false
292
+ });
293
+ }
294
+ // Assignment in condition (common error: = instead of ===)
295
+ // Pattern: if (x = y) instead of if (x === y)
296
+ if (line.match(/if\s*\([^)]*[^=!<>]=\s*[^=]/) && !line.includes('==')) {
297
+ lineErrors.push({
298
+ line: lineNumber,
299
+ error: 'Assignment in condition detected - likely mistake',
300
+ suggestion: 'Use === or == for comparison, not = for assignment: if (x === y)',
301
+ severity: 'error',
302
+ references: references_1.typescriptStandards['type-errors'] || [],
303
+ securityRelevant: false
304
+ });
305
+ }
306
+ });
307
+ }
308
+ /**
309
+ * Detect type assertions - Unsafe 'as', non-null assertions '!', type predicates
310
+ */
311
+ detectTypeAssertions(code, lineErrors) {
312
+ const lines = code.split('\n');
313
+ lines.forEach((line, index) => {
314
+ const lineNumber = index + 1;
315
+ if (line.trim().startsWith('//'))
316
+ return;
317
+ // Detect 'as any' or 'as unknown' - unsafe type assertions
318
+ if (line.match(/as\s+any\b/) || line.match(/as\s+unknown\b/)) {
319
+ lineErrors.push({
320
+ line: lineNumber,
321
+ error: 'Unsafe type assertion: use of "as any" or "as unknown"',
322
+ suggestion: 'Avoid "as any". Use specific types or type guards for type safety',
323
+ severity: 'error', // Changed from 'warning' to 'error' for Monaco highlighting
324
+ references: references_1.typescriptStandards['type-assertions'] || [],
325
+ securityRelevant: true
326
+ });
327
+ }
328
+ // CRITICAL FIX: Detect type assertions on 'unknown' parameter without validation
329
+ // Pattern: function foo(data: unknown) { return data as SomeType; }
330
+ // This is risky because it bypasses runtime validation
331
+ if (line.match(/\bdata\s+as\s+[A-Z]\w+/) || line.match(/\bvalue\s+as\s+[A-Z]\w+/)) {
332
+ // Look backward to see if the parameter is typed as unknown
333
+ const lookBackLines = lines.slice(Math.max(0, index - 5), index + 1);
334
+ const hasUnknownParam = lookBackLines.some(l => l.includes('data: unknown') || l.includes('value: unknown'));
335
+ if (hasUnknownParam) {
336
+ lineErrors.push({
337
+ line: lineNumber,
338
+ error: 'Type assertion on unknown without runtime validation',
339
+ suggestion: 'Add runtime validation before type assertion: if (typeof data === "object" && data !== null && "requiredField" in data) { ... }',
340
+ severity: 'warning',
341
+ references: references_1.typescriptStandards['type-assertions'] || [],
342
+ securityRelevant: true
343
+ });
344
+ }
345
+ }
346
+ // Detect non-null assertion operator (!)
347
+ // FIX (2025-11-18): Remove string content first to avoid false positives
348
+ // Previous bug: 'MyP@ssw0rd!' was detected as non-null assertion
349
+ // CRITICAL FIX: Added pattern for array access with non-null assertion: array[0]!
350
+ const lineWithoutStrings = this.removeStringLiterals(line);
351
+ if (lineWithoutStrings.match(/\w+!\s*\./) || lineWithoutStrings.match(/\w+!\s*\[/) || lineWithoutStrings.match(/\w+!\s*;/) || lineWithoutStrings.match(/\]\s*!/)) {
352
+ lineErrors.push({
353
+ line: lineNumber,
354
+ error: 'Non-null assertion (!) detected - bypasses null checks',
355
+ suggestion: 'Use optional chaining (?.) or check explicitly: if (value != null) or check array length',
356
+ severity: 'error', // Changed from 'warning' to 'error' for Monaco highlighting
357
+ references: references_1.typescriptStandards['type-assertions'] || [],
358
+ securityRelevant: true
359
+ });
360
+ }
361
+ // Detect empty type assertion (casting empty object to interface/type)
362
+ // Pattern: {} as User, {} as Config, etc.
363
+ if (line.match(/\{\s*\}\s+as\s+[A-Z]\w+/)) {
364
+ lineErrors.push({
365
+ line: lineNumber,
366
+ error: 'Empty type assertion - creating invalid object',
367
+ suggestion: 'Initialize with actual values or use a factory function',
368
+ severity: 'error',
369
+ references: references_1.typescriptStandards['type-assertions'] || [],
370
+ securityRelevant: false
371
+ });
372
+ }
373
+ // Detect double type assertions (as X as Y)
374
+ if (line.match(/as\s+\w+\s+as\s+\w+/)) {
375
+ lineErrors.push({
376
+ line: lineNumber,
377
+ error: 'Double type assertion detected - dangerous practice',
378
+ suggestion: 'Avoid double assertions. Redesign code for correct types',
379
+ severity: 'error',
380
+ references: references_1.typescriptStandards['type-assertions'] || [],
381
+ securityRelevant: true
382
+ });
383
+ }
384
+ // FIX #1 (Dec 16, 2025): Detect general type assertions and classify by security relevance
385
+ // Pattern: something as Type (but not 'as any', 'as unknown', double assertions handled above)
386
+ const typeAssertionPattern = /\s+as\s+([A-Za-z]\w*)/;
387
+ const assertionMatch = line.match(typeAssertionPattern);
388
+ if (assertionMatch &&
389
+ !line.includes('as any') &&
390
+ !line.includes('as unknown') &&
391
+ !line.match(/as\s+\w+\s+as\s+\w+/)) { // Not double assertion
392
+ // Check if this is a security-relevant type assertion
393
+ const isSecurityRelevant = this.isSecurityRelevantAssertion(line);
394
+ if (isSecurityRelevant) {
395
+ // Security-relevant assertions: Medium severity
396
+ lineErrors.push({
397
+ line: lineNumber,
398
+ error: 'Unsafe type assertion with potential security implications',
399
+ suggestion: 'Add runtime validation before type assertion, especially for authentication or authorization contexts',
400
+ severity: 'warning', // Medium severity for security issues
401
+ references: references_1.typescriptStandards['type-assertions'] || [],
402
+ securityRelevant: true
403
+ });
404
+ }
405
+ else {
406
+ // Non-security type assertions (environment variables, config): INFO severity
407
+ lineErrors.push({
408
+ line: lineNumber,
409
+ error: 'Type assertion without runtime validation (code quality)',
410
+ suggestion: 'Consider adding runtime type check or use a type-safe alternative. For environment variables, connection failure will occur if undefined.',
411
+ severity: 'info', // INFO severity for code quality
412
+ references: references_1.typescriptStandards['type-assertions'] || [],
413
+ securityRelevant: false
414
+ });
415
+ }
416
+ }
417
+ });
418
+ }
419
+ /**
420
+ * Determine if a type assertion is security-relevant
421
+ * Security-relevant: authentication, authorization, input validation, cryptography
422
+ * Non-security: environment variables, config values, type conversions
423
+ */
424
+ isSecurityRelevantAssertion(line) {
425
+ const lowerLine = line.toLowerCase();
426
+ // Security-relevant keywords
427
+ const securityKeywords = [
428
+ 'auth', 'token', 'password', 'secret', 'key', 'credential',
429
+ 'session', 'user', 'role', 'permission', 'access',
430
+ 'validate', 'sanitize', 'escape'
431
+ ];
432
+ // Non-security keywords (environment/config)
433
+ const configKeywords = [
434
+ 'process.env', 'config.', 'settings.', 'options.',
435
+ 'port', 'host', 'url', 'path'
436
+ ];
437
+ // Check if line contains config keywords (non-security)
438
+ const hasConfigKeyword = configKeywords.some(keyword => lowerLine.includes(keyword.toLowerCase()));
439
+ if (hasConfigKeyword) {
440
+ return false; // Not security-relevant
441
+ }
442
+ // Check if line contains security keywords
443
+ const hasSecurityKeyword = securityKeywords.some(keyword => lowerLine.includes(keyword));
444
+ if (hasSecurityKeyword) {
445
+ return true; // Security-relevant
446
+ }
447
+ // Default: treat as non-security (INFO) to avoid false positives
448
+ return false;
449
+ }
450
+ /**
451
+ * Detect generic issues - Missing type arguments, constraint violations
452
+ */
453
+ detectGenericIssues(code, lineErrors) {
454
+ const lines = code.split('\n');
455
+ lines.forEach((line, index) => {
456
+ const lineNumber = index + 1;
457
+ if (line.trim().startsWith('//'))
458
+ return;
459
+ // Detect Array without type argument
460
+ if (line.match(/:\s*Array\s*[^<]/) && !line.includes('//')) {
461
+ lineErrors.push({
462
+ line: lineNumber,
463
+ error: 'Array without generic type argument',
464
+ suggestion: 'Specify the type: Array<string> or use string[]',
465
+ severity: 'warning',
466
+ references: references_1.typescriptStandards['generics'] || [],
467
+ securityRelevant: false
468
+ });
469
+ }
470
+ // Detect Promise without type argument
471
+ if (line.match(/:\s*Promise\s*[^<]/) || line.match(/new\s+Promise\s*\(/)) {
472
+ if (!line.includes('<')) {
473
+ lineErrors.push({
474
+ line: lineNumber,
475
+ error: 'Promise without generic type specified',
476
+ suggestion: 'Specify the return type: Promise<string>',
477
+ severity: 'warning',
478
+ references: references_1.typescriptStandards['generics'] || [],
479
+ securityRelevant: false
480
+ });
481
+ }
482
+ }
483
+ // Detect generic constraint violations
484
+ if (line.match(/<T\s+extends\s+\w+>/) && line.includes('=')) {
485
+ const constraintMatch = line.match(/<T\s+extends\s+(\w+)>/);
486
+ if (constraintMatch && line.includes('as')) {
487
+ lineErrors.push({
488
+ line: lineNumber,
489
+ error: 'Possible generic constraint violation',
490
+ suggestion: 'Ensure the type satisfies the specified constraint',
491
+ severity: 'info',
492
+ references: references_1.typescriptStandards['generics'] || [],
493
+ securityRelevant: false
494
+ });
495
+ }
496
+ }
497
+ });
498
+ }
499
+ /**
500
+ * Detect union/intersection issues - Discriminated unions, type narrowing failures
501
+ */
502
+ detectUnionIntersectionIssues(code, lineErrors) {
503
+ const lines = code.split('\n');
504
+ lines.forEach((line, index) => {
505
+ const lineNumber = index + 1;
506
+ if (line.trim().startsWith('//'))
507
+ return;
508
+ // Detect union type without discriminant property
509
+ if (line.match(/type\s+\w+\s*=\s*\{[^}]*\}\s*\|\s*\{[^}]*\}/)) {
510
+ if (!line.includes('kind:') && !line.includes('type:') && !line.includes('tag:')) {
511
+ lineErrors.push({
512
+ line: lineNumber,
513
+ error: 'Union type without discriminant property',
514
+ suggestion: 'Add discriminant property: { kind: "A", ... } | { kind: "B", ... }',
515
+ severity: 'info',
516
+ references: references_1.typescriptStandards['unions-intersections'] || [],
517
+ securityRelevant: false
518
+ });
519
+ }
520
+ }
521
+ // Detect accessing union type property without narrowing
522
+ // FIXED: Only match union type pipe |, not OR operator ||
523
+ // FIXED: Recognize optional chaining ?. as a form of null narrowing
524
+ const hasUnionTypePipe = line.match(/[^|]\|[^|]/) !== null; // Single | not ||
525
+ const hasOptionalChaining = line.includes('?.'); // ?. is null-safe access
526
+ if (line.match(/\.\w+/) && hasUnionTypePipe && !hasOptionalChaining) {
527
+ const prevLines = lines.slice(Math.max(0, index - 3), index);
528
+ const hasNarrowing = prevLines.some(l => l.includes('typeof') || l.includes('instanceof') || l.includes('in '));
529
+ if (!hasNarrowing) {
530
+ lineErrors.push({
531
+ line: lineNumber,
532
+ error: 'Union type property access without narrowing',
533
+ suggestion: 'Use type guard: if (typeof x === "string") or if ("prop" in obj)',
534
+ severity: 'warning',
535
+ references: references_1.typescriptStandards['unions-intersections'] || [],
536
+ securityRelevant: false
537
+ });
538
+ }
539
+ }
540
+ // Detect complex intersection types
541
+ if ((line.match(/&/g) || []).length > 3) {
542
+ lineErrors.push({
543
+ line: lineNumber,
544
+ error: 'Intersection type too complex',
545
+ suggestion: 'Consider using interface or type alias to simplify',
546
+ severity: 'info',
547
+ references: references_1.typescriptStandards['unions-intersections'] || [],
548
+ securityRelevant: false
549
+ });
550
+ }
551
+ });
552
+ }
553
+ /**
554
+ * Detect class/interface issues - Implementation errors, abstract violations
555
+ */
556
+ detectClassInterfaceIssues(code, lineErrors) {
557
+ const lines = code.split('\n');
558
+ lines.forEach((line, index) => {
559
+ const lineNumber = index + 1;
560
+ if (line.trim().startsWith('//'))
561
+ return;
562
+ // Detect class implementing interface without all methods
563
+ if (line.match(/class\s+\w+\s+implements\s+\w+/)) {
564
+ lineErrors.push({
565
+ line: lineNumber,
566
+ error: 'Verify that all interface methods are implemented',
567
+ suggestion: 'Implement all required interface methods',
568
+ severity: 'info',
569
+ references: references_1.typescriptStandards['classes-interfaces'] || [],
570
+ securityRelevant: false
571
+ });
572
+ }
573
+ // Detect abstract method without abstract keyword on class
574
+ if (line.match(/abstract\s+\w+\s*\(/) && !lines.slice(Math.max(0, index - 5), index).some(l => l.includes('abstract class'))) {
575
+ lineErrors.push({
576
+ line: lineNumber,
577
+ error: 'Abstract method in non-abstract class',
578
+ suggestion: 'Declare the class as abstract or implement the method',
579
+ severity: 'error',
580
+ references: references_1.typescriptStandards['classes-interfaces'] || [],
581
+ securityRelevant: false
582
+ });
583
+ }
584
+ // Detect missing access modifiers
585
+ if (line.match(/^\s*\w+\s*\(/) && !line.includes('function') && !line.includes('//')) {
586
+ const prevLine = lines[index - 1]?.trim();
587
+ if (prevLine && prevLine.includes('class')) {
588
+ if (!line.includes('public') && !line.includes('private') && !line.includes('protected')) {
589
+ lineErrors.push({
590
+ line: lineNumber,
591
+ error: 'Class method without explicit access modifier',
592
+ suggestion: 'Add public, private, or protected for clarity',
593
+ severity: 'info',
594
+ references: references_1.typescriptStandards['classes-interfaces'] || [],
595
+ securityRelevant: false
596
+ });
597
+ }
598
+ }
599
+ }
600
+ // Detect interface with 'I' prefix (anti-pattern)
601
+ if (line.match(/interface\s+I[A-Z]\w+/)) {
602
+ lineErrors.push({
603
+ line: lineNumber,
604
+ error: 'Interface with "I" prefix - anti-pattern in TypeScript',
605
+ suggestion: 'Remove the "I" prefix: interface User instead of IUser',
606
+ severity: 'info',
607
+ references: references_1.typescriptStandards['classes-interfaces'] || [],
608
+ securityRelevant: false
609
+ });
610
+ }
611
+ });
612
+ }
613
+ /**
614
+ * Detect async/Promise issues - Untyped Promises, async without await
615
+ */
616
+ detectAsyncPromiseIssues(code, lineErrors) {
617
+ const lines = code.split('\n');
618
+ lines.forEach((line, index) => {
619
+ const lineNumber = index + 1;
620
+ if (line.trim().startsWith('//'))
621
+ return;
622
+ // Detect async function without await
623
+ if (line.includes('async') && line.includes('function')) {
624
+ const nextLines = lines.slice(index + 1, Math.min(index + 20, lines.length));
625
+ const hasAwait = nextLines.some(l => l.includes('await'));
626
+ if (!hasAwait) {
627
+ lineErrors.push({
628
+ line: lineNumber,
629
+ error: 'Async function without await usage',
630
+ suggestion: 'Remove async or use await for asynchronous operations',
631
+ severity: 'warning',
632
+ references: references_1.typescriptStandards['async-promises'] || [],
633
+ securityRelevant: false
634
+ });
635
+ }
636
+ }
637
+ // Detect Promise without error handling
638
+ if (line.includes('.then(') && !line.includes('.catch(')) {
639
+ const nextLines = lines.slice(index + 1, Math.min(index + 5, lines.length));
640
+ const hasCatch = nextLines.some(l => l.includes('.catch('));
641
+ if (!hasCatch) {
642
+ lineErrors.push({
643
+ line: lineNumber,
644
+ error: 'Promise without error handling (.catch)',
645
+ suggestion: 'Add .catch() or use try/catch with async/await',
646
+ severity: 'warning',
647
+ references: references_1.typescriptStandards['async-promises'] || [],
648
+ securityRelevant: false
649
+ });
650
+ }
651
+ }
652
+ // Detect floating Promise (not awaited or returned)
653
+ // FIXED: Recognize .then()/.catch() chaining as valid promise handling
654
+ if (line.match(/^\s*\w+\(/) && !line.includes('await') && !line.includes('return')) {
655
+ if (line.includes('fetch') || line.includes('Promise')) {
656
+ // Check if the next lines have .then() or .catch() (promise chaining)
657
+ const nextLines = lines.slice(index + 1, Math.min(index + 4, lines.length));
658
+ const hasPromiseChaining = line.includes('.then') ||
659
+ nextLines.some(l => l.trim().startsWith('.then') || l.trim().startsWith('.catch'));
660
+ if (!hasPromiseChaining) {
661
+ lineErrors.push({
662
+ line: lineNumber,
663
+ error: 'Promise not awaited - floating Promise',
664
+ suggestion: 'Use await or return to ensure Promise is handled',
665
+ severity: 'error',
666
+ references: references_1.typescriptStandards['async-promises'] || [],
667
+ securityRelevant: false
668
+ });
669
+ }
670
+ }
671
+ }
672
+ });
673
+ }
674
+ /**
675
+ * Detect module issues - Import/export problems, circular dependencies
676
+ */
677
+ detectModuleIssues(code, lineErrors) {
678
+ const lines = code.split('\n');
679
+ const imports = new Set();
680
+ let inMultiLineComment = false;
681
+ lines.forEach((line, index) => {
682
+ const lineNumber = index + 1;
683
+ const trimmed = line.trim();
684
+ // CRITICAL: Track multi-line comment blocks (/* ... */)
685
+ if (trimmed.includes('/*')) {
686
+ inMultiLineComment = true;
687
+ }
688
+ if (trimmed.includes('*/')) {
689
+ inMultiLineComment = false;
690
+ return; // Skip the line with */
691
+ }
692
+ // CRITICAL: Skip all lines inside multi-line comments and single-line comments
693
+ if (!trimmed ||
694
+ inMultiLineComment ||
695
+ trimmed.startsWith('//') ||
696
+ trimmed.startsWith('*')) {
697
+ return;
698
+ }
699
+ // Track imports
700
+ if (line.includes('import')) {
701
+ const importMatch = line.match(/import\s+.*\s+from\s+['"]([^'"]+)['"]/);
702
+ if (importMatch) {
703
+ imports.add(importMatch[1]);
704
+ }
705
+ }
706
+ // Detect import without type-only when importing types
707
+ if (line.match(/import\s+\{[^}]*\}\s+from/) && !line.includes('type ')) {
708
+ if (line.includes('Interface') || line.includes('Type')) {
709
+ lineErrors.push({
710
+ line: lineNumber,
711
+ error: 'Type import without "type" keyword',
712
+ suggestion: 'Use: import type { Interface } from "..." for type-only imports',
713
+ severity: 'info',
714
+ references: references_1.typescriptStandards['modules'] || [],
715
+ securityRelevant: false
716
+ });
717
+ }
718
+ }
719
+ // Detect dynamic imports without proper typing
720
+ if (line.includes('import(') && !line.includes('await')) {
721
+ lineErrors.push({
722
+ line: lineNumber,
723
+ error: 'Dynamic import without await',
724
+ suggestion: 'Use: const module = await import("...")',
725
+ severity: 'warning',
726
+ references: references_1.typescriptStandards['modules'] || [],
727
+ securityRelevant: false
728
+ });
729
+ }
730
+ // Detect potential circular dependency patterns
731
+ if (line.includes('export') && line.includes('*') && line.includes('from')) {
732
+ lineErrors.push({
733
+ line: lineNumber,
734
+ error: 'Export * may cause circular dependencies',
735
+ suggestion: 'Export only what is necessary to avoid circular dependencies',
736
+ severity: 'info',
737
+ references: references_1.typescriptStandards['modules'] || [],
738
+ securityRelevant: false
739
+ });
740
+ }
741
+ });
742
+ }
743
+ /**
744
+ * Detect decorator issues - Experimental decorators usage
745
+ */
746
+ detectDecoratorIssues(code, lineErrors) {
747
+ const lines = code.split('\n');
748
+ lines.forEach((line, index) => {
749
+ const lineNumber = index + 1;
750
+ if (line.trim().startsWith('//'))
751
+ return;
752
+ // Detect decorator usage
753
+ if (line.trim().startsWith('@')) {
754
+ lineErrors.push({
755
+ line: lineNumber,
756
+ error: 'Decorator detected - experimental feature',
757
+ suggestion: 'Enable experimentalDecorators in tsconfig.json',
758
+ severity: 'info',
759
+ references: references_1.typescriptStandards['decorators'] || [],
760
+ securityRelevant: false
761
+ });
762
+ }
763
+ // Detect parameter decorators without reflect-metadata
764
+ if (line.match(/@\w+\s*\([^)]*\)\s*\w+:/)) {
765
+ if (!code.includes('reflect-metadata')) {
766
+ lineErrors.push({
767
+ line: lineNumber,
768
+ error: 'Parameter decorator without reflect-metadata',
769
+ suggestion: 'Install and import reflect-metadata for decorator metadata',
770
+ severity: 'warning',
771
+ references: references_1.typescriptStandards['decorators'] || [],
772
+ securityRelevant: false
773
+ });
774
+ }
775
+ }
776
+ });
777
+ }
778
+ /**
779
+ * Detect mapped/conditional type issues - Complex types, recursive limits
780
+ */
781
+ detectMappedConditionalTypes(code, lineErrors) {
782
+ const lines = code.split('\n');
783
+ lines.forEach((line, index) => {
784
+ const lineNumber = index + 1;
785
+ if (line.trim().startsWith('//'))
786
+ return;
787
+ // Detect conditional types
788
+ if (line.includes('extends') && line.includes('?') && line.includes(':')) {
789
+ if ((line.match(/\?/g) || []).length > 2) {
790
+ lineErrors.push({
791
+ line: lineNumber,
792
+ error: 'Conditional type too complex',
793
+ suggestion: 'Simplify or split into multiple type aliases',
794
+ severity: 'info',
795
+ references: references_1.typescriptStandards['mapped-conditional'] || [],
796
+ securityRelevant: false
797
+ });
798
+ }
799
+ }
800
+ // Detect mapped types with complex transformations
801
+ if (line.match(/\[K\s+in\s+keyof/) && line.includes('?') && line.includes('-')) {
802
+ lineErrors.push({
803
+ line: lineNumber,
804
+ error: 'Mapped type with multiple transformations',
805
+ suggestion: 'Consider breaking into intermediate types for better readability',
806
+ severity: 'info',
807
+ references: references_1.typescriptStandards['mapped-conditional'] || [],
808
+ securityRelevant: false
809
+ });
810
+ }
811
+ // Detect recursive type aliases
812
+ if (line.match(/type\s+(\w+)\s*=/) && line.includes('Array<')) {
813
+ const typeNameMatch = line.match(/type\s+(\w+)\s*=/);
814
+ if (typeNameMatch && line.includes(typeNameMatch[1])) {
815
+ lineErrors.push({
816
+ line: lineNumber,
817
+ error: 'Recursive type alias detected',
818
+ suggestion: 'Beware of infinite recursion. Use interface for recursive types',
819
+ severity: 'warning',
820
+ references: references_1.typescriptStandards['mapped-conditional'] || [],
821
+ securityRelevant: false
822
+ });
823
+ }
824
+ }
825
+ });
826
+ }
827
+ /**
828
+ * Detect strict mode violations - Implicit any, null checks violations
829
+ */
830
+ detectStrictModeViolations(code, lineErrors) {
831
+ const lines = code.split('\n');
832
+ lines.forEach((line, index) => {
833
+ const lineNumber = index + 1;
834
+ if (line.trim().startsWith('//'))
835
+ return;
836
+ // Detect implicit any from function parameters without types
837
+ // CRITICAL FIX: Improved regex to catch more patterns
838
+ // Matches: function foo(a, b) or function foo(param) without type annotations
839
+ const functionMatch = line.match(/function\s+\w+\s*\(([^)]*)\)/);
840
+ if (functionMatch) {
841
+ const params = functionMatch[1].trim();
842
+ // Check if params exist and don't have type annotations (no : character)
843
+ if (params.length > 0 && !params.includes(':')) {
844
+ lineErrors.push({
845
+ line: lineNumber,
846
+ error: 'Implicit any - function parameters without type annotations',
847
+ suggestion: 'Add types to parameters: function calculate(a: number, b: number) { ... }',
848
+ severity: 'error', // Changed from 'warning' to 'error' for Monaco highlighting
849
+ references: references_1.typescriptStandards['strict-mode'] || [],
850
+ securityRelevant: false
851
+ });
852
+ }
853
+ }
854
+ // Detect potential null/undefined without strict null checks
855
+ if (line.match(/\?\s*:/) && !line.includes('null') && !line.includes('undefined')) {
856
+ lineErrors.push({
857
+ line: lineNumber,
858
+ error: 'Optional type may include undefined',
859
+ suggestion: 'Enable strictNullChecks for better type safety',
860
+ severity: 'info',
861
+ references: references_1.typescriptStandards['strict-mode'] || [],
862
+ securityRelevant: false
863
+ });
864
+ }
865
+ // Detect this without explicit typing
866
+ if (line.includes('this.') && !line.includes('function') && !line.includes('class')) {
867
+ if (!code.includes('// @ts-ignore')) {
868
+ lineErrors.push({
869
+ line: lineNumber,
870
+ error: 'Use of "this" without explicit context',
871
+ suggestion: 'Consider adding explicit type or using arrow functions',
872
+ severity: 'info',
873
+ references: references_1.typescriptStandards['strict-mode'] || [],
874
+ securityRelevant: false
875
+ });
876
+ }
877
+ }
878
+ });
879
+ }
880
+ /**
881
+ * Detect any propagation - 'any' type spreading through code
882
+ */
883
+ detectAnyPropagation(code, lineErrors) {
884
+ const lines = code.split('\n');
885
+ lines.forEach((line, index) => {
886
+ const lineNumber = index + 1;
887
+ if (line.trim().startsWith('//'))
888
+ return;
889
+ // Detect explicit 'any' type annotations
890
+ if (line.match(/:\s*any\b/) && !line.includes('// @ts-')) {
891
+ lineErrors.push({
892
+ line: lineNumber,
893
+ error: 'Type "any" detected - eliminates type checking',
894
+ suggestion: 'Use specific type or unknown for type safety',
895
+ severity: 'warning',
896
+ references: references_1.typescriptStandards['any-propagation'] || [],
897
+ securityRelevant: false
898
+ });
899
+ }
900
+ // Detect any[] arrays
901
+ if (line.match(/:\s*any\[\]/) || line.match(/Array<any>/)) {
902
+ lineErrors.push({
903
+ line: lineNumber,
904
+ error: 'Array of any detected',
905
+ suggestion: 'Specify array type: string[] or Array<string>',
906
+ severity: 'warning',
907
+ references: references_1.typescriptStandards['any-propagation'] || [],
908
+ securityRelevant: false
909
+ });
910
+ }
911
+ // Detect functions returning any
912
+ if (line.match(/\):\s*any\b/)) {
913
+ lineErrors.push({
914
+ line: lineNumber,
915
+ error: 'Function returns any - propagates lack of typing',
916
+ suggestion: 'Specify the correct return type',
917
+ severity: 'warning',
918
+ references: references_1.typescriptStandards['any-propagation'] || [],
919
+ securityRelevant: false
920
+ });
921
+ }
922
+ });
923
+ }
924
+ /**
925
+ * Detect performance issues - Type complexity, compilation performance
926
+ */
927
+ detectPerformanceIssues(code, lineErrors) {
928
+ const lines = code.split('\n');
929
+ lines.forEach((line, index) => {
930
+ const lineNumber = index + 1;
931
+ if (line.trim().startsWith('//'))
932
+ return;
933
+ // Detect excessive union types
934
+ const unionCount = (line.match(/\|/g) || []).length;
935
+ if (unionCount > 5) {
936
+ lineErrors.push({
937
+ line: lineNumber,
938
+ error: `Union type too large (${unionCount} types)`,
939
+ suggestion: 'Simplify union or use type narrowing for better performance',
940
+ severity: 'warning',
941
+ references: references_1.typescriptStandards['performance'] || [],
942
+ securityRelevant: false
943
+ });
944
+ }
945
+ // Detect deep nesting of generic types
946
+ const genericDepth = (line.match(/</g) || []).length;
947
+ if (genericDepth > 4) {
948
+ lineErrors.push({
949
+ line: lineNumber,
950
+ error: `Generics nested too deeply (depth ${genericDepth})`,
951
+ suggestion: 'Simplify type structure for better compilation performance',
952
+ severity: 'info',
953
+ references: references_1.typescriptStandards['performance'] || [],
954
+ securityRelevant: false
955
+ });
956
+ }
957
+ // Detect indexed access with complex types
958
+ if (line.match(/\[.*\[.*\]/)) {
959
+ lineErrors.push({
960
+ line: lineNumber,
961
+ error: 'Complex indexed access may affect performance',
962
+ suggestion: 'Consider creating intermediate type aliases',
963
+ severity: 'info',
964
+ references: references_1.typescriptStandards['performance'] || [],
965
+ securityRelevant: false
966
+ });
967
+ }
968
+ });
969
+ }
970
+ /**
971
+ * Detect naming convention violations - TypeScript-specific naming
972
+ */
973
+ detectNamingConventions(code, lineErrors) {
974
+ const lines = code.split('\n');
975
+ lines.forEach((line, index) => {
976
+ const lineNumber = index + 1;
977
+ if (line.trim().startsWith('//'))
978
+ return;
979
+ // Detect interface with 'I' prefix (anti-pattern in TypeScript)
980
+ if (line.match(/interface\s+I[A-Z]\w+/)) {
981
+ const interfaceMatch = line.match(/interface\s+(I[A-Z]\w+)/);
982
+ if (interfaceMatch) {
983
+ const interfaceName = interfaceMatch[1];
984
+ const suggestedName = interfaceName.substring(1);
985
+ lineErrors.push({
986
+ line: lineNumber,
987
+ error: `Interface "${interfaceName}" uses "I" prefix - anti-pattern in TypeScript`,
988
+ suggestion: `Rename to: interface ${suggestedName}`,
989
+ severity: 'info',
990
+ references: references_1.typescriptStandards['classes-interfaces'] || [],
991
+ securityRelevant: false
992
+ });
993
+ }
994
+ }
995
+ // Detect type aliases not in PascalCase
996
+ if (line.match(/type\s+([a-z][a-zA-Z0-9]*)\s*=/)) {
997
+ const typeMatch = line.match(/type\s+([a-z][a-zA-Z0-9]*)\s*=/);
998
+ if (typeMatch) {
999
+ lineErrors.push({
1000
+ line: lineNumber,
1001
+ error: `Type alias should start with uppercase: "${typeMatch[1]}"`,
1002
+ suggestion: `Use PascalCase: ${typeMatch[1].charAt(0).toUpperCase() + typeMatch[1].slice(1)}`,
1003
+ severity: 'info',
1004
+ references: references_1.typescriptStandards['classes-interfaces'] || [],
1005
+ securityRelevant: false
1006
+ });
1007
+ }
1008
+ }
1009
+ // Detect enum members not in UPPER_CASE
1010
+ if (line.match(/enum\s+\w+/)) {
1011
+ const nextLines = lines.slice(index + 1, Math.min(index + 10, lines.length));
1012
+ nextLines.forEach((nextLine, offset) => {
1013
+ if (nextLine.match(/^\s*[a-z]\w*\s*[,=]/) && !nextLine.includes('}')) {
1014
+ lineErrors.push({
1015
+ line: lineNumber + offset + 1,
1016
+ error: 'Enum member should be in PascalCase or UPPER_CASE',
1017
+ suggestion: 'Use: SUCCESS or Success for enum members',
1018
+ severity: 'info',
1019
+ references: references_1.typescriptStandards['classes-interfaces'] || [],
1020
+ securityRelevant: false
1021
+ });
1022
+ }
1023
+ });
1024
+ }
1025
+ });
1026
+ }
1027
+ /**
1028
+ * Detect configuration issues - tsconfig problems, module resolution
1029
+ */
1030
+ detectConfigurationIssues(code, lineErrors) {
1031
+ const lines = code.split('\n');
1032
+ lines.forEach((line, index) => {
1033
+ const lineNumber = index + 1;
1034
+ if (line.trim().startsWith('//'))
1035
+ return;
1036
+ // Detect usage of features requiring specific tsconfig
1037
+ if (line.includes('experimentalDecorators') || line.trim().startsWith('@')) {
1038
+ if (!code.includes('// experimentalDecorators: true')) {
1039
+ lineErrors.push({
1040
+ line: lineNumber,
1041
+ error: 'Decorators require experimentalDecorators in tsconfig',
1042
+ suggestion: 'Add "experimentalDecorators": true in tsconfig.json',
1043
+ severity: 'info',
1044
+ references: references_1.typescriptStandards['decorators'] || [],
1045
+ securityRelevant: false
1046
+ });
1047
+ }
1048
+ }
1049
+ // Detect JSX usage without proper configuration
1050
+ if (line.includes('<') && line.includes('/>') && !line.includes('//')) {
1051
+ if (!code.includes('jsx:')) {
1052
+ lineErrors.push({
1053
+ line: lineNumber,
1054
+ error: 'JSX requires configuration in tsconfig',
1055
+ suggestion: 'Add "jsx": "react" or "jsx": "react-jsx" in tsconfig.json',
1056
+ severity: 'info',
1057
+ references: references_1.typescriptStandards['modules'] || [],
1058
+ securityRelevant: false
1059
+ });
1060
+ }
1061
+ }
1062
+ // Detect module resolution issues
1063
+ if (line.includes('import') && line.includes('"@/')) {
1064
+ lineErrors.push({
1065
+ line: lineNumber,
1066
+ error: 'Path alias "@/" requires paths configuration',
1067
+ suggestion: 'Configure "paths" and "baseUrl" in tsconfig.json',
1068
+ severity: 'info',
1069
+ references: references_1.typescriptStandards['modules'] || [],
1070
+ securityRelevant: false
1071
+ });
1072
+ }
1073
+ });
1074
+ }
1075
+ /**
1076
+ * Detect React + TypeScript specific issues
1077
+ */
1078
+ detectReactTypeScriptIssues(code, lineErrors) {
1079
+ const lines = code.split('\n');
1080
+ const isReactFile = code.includes('React') || code.includes('react');
1081
+ if (!isReactFile)
1082
+ return;
1083
+ lines.forEach((line, index) => {
1084
+ const lineNumber = index + 1;
1085
+ if (line.trim().startsWith('//'))
1086
+ return;
1087
+ // Detect React.FC without props typing
1088
+ if (line.match(/React\.FC\b/) && !line.includes('<')) {
1089
+ lineErrors.push({
1090
+ line: lineNumber,
1091
+ error: 'React.FC without props type',
1092
+ suggestion: 'Specify props: React.FC<Props> or use function component',
1093
+ severity: 'warning',
1094
+ references: references_1.typescriptStandards['generics'] || [],
1095
+ securityRelevant: false
1096
+ });
1097
+ }
1098
+ // Detect event handlers without proper typing
1099
+ if (line.includes('onClick') || line.includes('onChange') || line.includes('onSubmit')) {
1100
+ if (line.match(/\([^)]*\)/) && !line.includes('event:') && !line.includes('e:')) {
1101
+ lineErrors.push({
1102
+ line: lineNumber,
1103
+ error: 'Event handler without event type',
1104
+ suggestion: 'Use: (event: React.MouseEvent) => ... or (e: React.ChangeEvent<HTMLInputElement>)',
1105
+ severity: 'info',
1106
+ references: references_1.typescriptStandards['type-errors'] || [],
1107
+ securityRelevant: false
1108
+ });
1109
+ }
1110
+ }
1111
+ // Detect useState without generic type
1112
+ if (line.includes('useState(') && !line.includes('<')) {
1113
+ if (!line.match(/useState\(\s*[0-9'"]/)) { // Skip primitive initializers
1114
+ lineErrors.push({
1115
+ line: lineNumber,
1116
+ error: 'useState without explicit generic type',
1117
+ suggestion: 'Specify type: useState<Type>(initialValue)',
1118
+ severity: 'info',
1119
+ references: references_1.typescriptStandards['generics'] || [],
1120
+ securityRelevant: false
1121
+ });
1122
+ }
1123
+ }
1124
+ // Detect useRef without type
1125
+ if (line.includes('useRef(') && !line.includes('<')) {
1126
+ lineErrors.push({
1127
+ line: lineNumber,
1128
+ error: 'useRef without generic type',
1129
+ suggestion: 'Specify type: useRef<HTMLDivElement>(null)',
1130
+ severity: 'warning',
1131
+ references: references_1.typescriptStandards['generics'] || [],
1132
+ securityRelevant: false
1133
+ });
1134
+ }
1135
+ // Detect useEffect without proper dependency typing
1136
+ if (line.includes('useEffect(')) {
1137
+ const nextLines = lines.slice(index + 1, Math.min(index + 10, lines.length));
1138
+ const hasDepsArray = nextLines.some(l => l.includes(']'));
1139
+ if (!hasDepsArray) {
1140
+ lineErrors.push({
1141
+ line: lineNumber,
1142
+ error: 'useEffect without dependency array',
1143
+ suggestion: 'Add dependency array: useEffect(() => { ... }, [deps])',
1144
+ severity: 'warning',
1145
+ references: references_1.typescriptStandards['async-promises'] || [],
1146
+ securityRelevant: false
1147
+ });
1148
+ }
1149
+ }
1150
+ });
1151
+ }
1152
+ checkBracketBalance(code, errors, lineErrors) {
1153
+ let parenBalance = 0;
1154
+ let braceBalance = 0;
1155
+ let bracketBalance = 0;
1156
+ let inLineComment = false;
1157
+ let inBlockComment = false; // NEW: Track multi-line /* */ comments
1158
+ let inString = false;
1159
+ let stringChar = '';
1160
+ let stringStartLine = 0; // Track where string started
1161
+ let currentLine = 1;
1162
+ let inTemplateLiteralExpression = false; // FIX (2025-11-18): Track ${ } inside template literals
1163
+ let templateExpressionDepth = 0; // Track nested braces inside ${...}
1164
+ const openBraces = [];
1165
+ for (let i = 0; i < code.length; i++) {
1166
+ const char = code[i];
1167
+ const nextChar = code[i + 1];
1168
+ if (char === '\n') {
1169
+ currentLine++;
1170
+ inLineComment = false;
1171
+ // CRITICAL FIX: If we're still in a string at end of line, report unclosed string
1172
+ // BUT: Allow multi-line template literals (backticks can span multiple lines)
1173
+ if (inString && stringChar !== '`') {
1174
+ lineErrors.push({
1175
+ line: stringStartLine,
1176
+ error: `Unclosed ${stringChar === '"' ? 'double quote' : 'single quote'} string`,
1177
+ suggestion: `Add ${stringChar} to close the string on line ${stringStartLine}`,
1178
+ severity: 'error',
1179
+ securityRelevant: false
1180
+ });
1181
+ // Reset string state
1182
+ inString = false;
1183
+ stringChar = '';
1184
+ stringStartLine = 0;
1185
+ }
1186
+ }
1187
+ // NEW: Detect block comment start /* (but not inside strings)
1188
+ if (!inString && !inLineComment && char === '/' && nextChar === '*') {
1189
+ inBlockComment = true;
1190
+ i++; // Skip the *
1191
+ continue;
1192
+ }
1193
+ // NEW: Detect block comment end */ (but not inside strings)
1194
+ if (!inString && inBlockComment && char === '*' && nextChar === '/') {
1195
+ inBlockComment = false;
1196
+ i++; // Skip the /
1197
+ continue;
1198
+ }
1199
+ if (!inString && char === '/' && nextChar === '/') {
1200
+ inLineComment = true;
1201
+ i++;
1202
+ continue;
1203
+ }
1204
+ // NEW: Skip all processing while in any type of comment
1205
+ if (inLineComment || inBlockComment)
1206
+ continue;
1207
+ // FIX (2025-11-18): Handle template literal expressions ${...}
1208
+ // When inside a template literal (`), check for ${ which starts an expression
1209
+ if (inString && stringChar === '`' && char === '$' && nextChar === '{') {
1210
+ inTemplateLiteralExpression = true;
1211
+ templateExpressionDepth = 1;
1212
+ i++; // Skip the {
1213
+ continue;
1214
+ }
1215
+ // Track braces inside template literal expressions
1216
+ if (inTemplateLiteralExpression) {
1217
+ if (char === '{') {
1218
+ templateExpressionDepth++;
1219
+ }
1220
+ else if (char === '}') {
1221
+ templateExpressionDepth--;
1222
+ if (templateExpressionDepth === 0) {
1223
+ inTemplateLiteralExpression = false; // Exit expression mode
1224
+ }
1225
+ }
1226
+ continue; // Don't process other chars while in expression
1227
+ }
1228
+ if ((char === '"' || char === "'" || char === '`') && code[i - 1] !== '\\') {
1229
+ if (!inString) {
1230
+ inString = true;
1231
+ stringChar = char;
1232
+ stringStartLine = currentLine; // Track line where string opened
1233
+ }
1234
+ else if (char === stringChar) {
1235
+ inString = false;
1236
+ stringChar = '';
1237
+ stringStartLine = 0;
1238
+ }
1239
+ continue;
1240
+ }
1241
+ if (!inLineComment && !inString) {
1242
+ if (char === '(') {
1243
+ parenBalance++;
1244
+ openBraces.push({ line: currentLine, char: '(' });
1245
+ }
1246
+ else if (char === ')') {
1247
+ parenBalance--;
1248
+ for (let j = openBraces.length - 1; j >= 0; j--) {
1249
+ if (openBraces[j].char === '(') {
1250
+ openBraces.splice(j, 1);
1251
+ break;
1252
+ }
1253
+ }
1254
+ }
1255
+ else if (char === '{') {
1256
+ braceBalance++;
1257
+ openBraces.push({ line: currentLine, char: '{' });
1258
+ }
1259
+ else if (char === '}') {
1260
+ braceBalance--;
1261
+ for (let j = openBraces.length - 1; j >= 0; j--) {
1262
+ if (openBraces[j].char === '{') {
1263
+ openBraces.splice(j, 1);
1264
+ break;
1265
+ }
1266
+ }
1267
+ }
1268
+ else if (char === '[') {
1269
+ bracketBalance++;
1270
+ openBraces.push({ line: currentLine, char: '[' });
1271
+ }
1272
+ else if (char === ']') {
1273
+ bracketBalance--;
1274
+ for (let j = openBraces.length - 1; j >= 0; j--) {
1275
+ if (openBraces[j].char === '[') {
1276
+ openBraces.splice(j, 1);
1277
+ break;
1278
+ }
1279
+ }
1280
+ }
1281
+ }
1282
+ }
1283
+ // CRITICAL FIX: Check for unclosed strings at end of file (including template literals)
1284
+ if (inString && stringStartLine > 0) {
1285
+ const stringTypeName = stringChar === '`' ? 'template literal' :
1286
+ stringChar === '"' ? 'double quote string' : 'single quote string';
1287
+ lineErrors.push({
1288
+ line: stringStartLine,
1289
+ error: `Unclosed ${stringTypeName}`,
1290
+ suggestion: `Add ${stringChar} to close the ${stringTypeName}`,
1291
+ severity: 'error',
1292
+ securityRelevant: false
1293
+ });
1294
+ }
1295
+ openBraces.forEach(brace => {
1296
+ const closingChar = brace.char === '{' ? '}' : brace.char === '(' ? ')' : ']';
1297
+ const typeName = brace.char === '{' ? 'brace' : brace.char === '(' ? 'parenthesis' : 'bracket';
1298
+ lineErrors.push({
1299
+ line: brace.line,
1300
+ error: `${typeName.charAt(0).toUpperCase() + typeName.slice(1)} "${brace.char}" was not closed`,
1301
+ suggestion: `Add "${closingChar}" to close the ${typeName} opened on line ${brace.line}`,
1302
+ severity: 'error',
1303
+ securityRelevant: false
1304
+ });
1305
+ });
1306
+ // DON'T add general balance errors - the code above already adds specific line errors
1307
+ // with proper line numbers, enabling Auto-Fix functionality
1308
+ }
1309
+ analyzeQuality(code, result) {
1310
+ const issues = [];
1311
+ // Check for 'any' usage
1312
+ const anyCount = (code.match(/:\s*any\b/g) || []).length;
1313
+ if (anyCount > 0) {
1314
+ issues.push({
1315
+ type: 'warning',
1316
+ message: `${anyCount} use(s) of "any" found - compromises type safety`,
1317
+ severity: 'medium'
1318
+ });
1319
+ result.quality.score -= anyCount * 5;
1320
+ }
1321
+ // Check for missing return types
1322
+ const functionsWithoutReturnType = (code.match(/function\s+\w+\s*\([^)]*\)\s*\{/g) || []).length;
1323
+ if (functionsWithoutReturnType > 0) {
1324
+ issues.push({
1325
+ type: 'info',
1326
+ message: 'Functions without explicit return type found',
1327
+ severity: 'low'
1328
+ });
1329
+ result.quality.score -= functionsWithoutReturnType * 3;
1330
+ }
1331
+ // Check for interface I-prefix
1332
+ const iPrefixCount = (code.match(/interface\s+I[A-Z]\w+/g) || []).length;
1333
+ if (iPrefixCount > 0) {
1334
+ issues.push({
1335
+ type: 'info',
1336
+ message: 'Interfaces with "I" prefix - anti-pattern in TypeScript',
1337
+ severity: 'low'
1338
+ });
1339
+ result.quality.score -= iPrefixCount * 2;
1340
+ }
1341
+ result.quality.issues = issues;
1342
+ result.quality.score = Math.max(0, result.quality.score);
1343
+ }
1344
+ analyzePerformance(code, result) {
1345
+ const suggestions = [];
1346
+ // Check for excessive union types
1347
+ const lines = code.split('\n');
1348
+ lines.forEach(line => {
1349
+ const unionCount = (line.match(/\|/g) || []).length;
1350
+ if (unionCount > 5) {
1351
+ suggestions.push('Simplify large union types for better compilation performance');
1352
+ result.performance.score -= 10;
1353
+ }
1354
+ });
1355
+ // Check for deep generic nesting
1356
+ const deepGenerics = code.match(/<<<</g);
1357
+ if (deepGenerics) {
1358
+ suggestions.push('Reduce generic nesting for better performance');
1359
+ result.performance.score -= 15;
1360
+ }
1361
+ result.performance.suggestions = suggestions;
1362
+ result.performance.score = Math.max(0, result.performance.score);
1363
+ }
1364
+ analyzeSecurity(code, result) {
1365
+ const lines = code.split('\n');
1366
+ const vulnerabilities = [];
1367
+ // MODULAR SECURITY CHECKS (2025-12-01)
1368
+ // All security checks extracted to focused modules for better maintainability
1369
+ // Injection Attacks (Checks #1-7)
1370
+ vulnerabilities.push(...(0, injection_attacks_1.checkInjectionAttacks)(lines));
1371
+ // Credentials & Cryptography (Checks #8-10)
1372
+ vulnerabilities.push(...(0, credentials_crypto_1.checkCredentialsAndCrypto)(lines));
1373
+ // Code Injection (Checks #11-14)
1374
+ vulnerabilities.push(...(0, code_injection_1.checkCodeInjection)(lines));
1375
+ // Code Quality (Checks #15-18)
1376
+ vulnerabilities.push(...(0, code_quality_1.checkCodeQuality)(code, lines));
1377
+ // TypeScript Type Security (Checks #19-20)
1378
+ vulnerabilities.push(...(0, type_security_1.checkTypeSecurity)(lines));
1379
+ // OWASP A02:2025 - Security Misconfiguration (NEW - Phase 7B)
1380
+ vulnerabilities.push(...(0, security_misconfiguration_1.checkSecurityMisconfiguration)(lines));
1381
+ // OWASP A10:2025 - Mishandling of Exceptional Conditions (NEW - Phase 7B)
1382
+ vulnerabilities.push(...(0, exception_handling_1.checkExceptionHandling)(lines));
1383
+ // OWASP A03:2025 - Software Supply Chain Failures (Enhanced - Phase 7B)
1384
+ vulnerabilities.push(...(0, enhanced_supply_chain_1.checkEnhancedSupplyChain)(lines));
1385
+ // OWASP A01:2021 - Broken Access Control (Check #85 - Dec 16, 2025)
1386
+ vulnerabilities.push(...(0, access_control_1.checkAccessControl)(lines));
1387
+ // OWASP A05:2021 - Security Misconfiguration - Information Disclosure (Check #86 - Dec 16, 2025)
1388
+ vulnerabilities.push(...(0, information_disclosure_1.checkInformationDisclosure)(lines));
1389
+ // OWASP A07:2021 - Identification and Authentication Failures (Checks #88, #89, #90, #91 - Dec 31, 2025)
1390
+ vulnerabilities.push(...(0, authentication_1.checkAuthentication)(lines));
1391
+ // OWASP A09:2025 - Security Logging and Monitoring Failures (Checks #92, #93 - Dec 31, 2025)
1392
+ vulnerabilities.push(...(0, logging_failures_1.checkLoggingFailures)(lines));
1393
+ // NEW: TypeScript Compiler API Type Checking (2025-12-02)
1394
+ // This adds comprehensive type error detection (95%+ coverage)
1395
+ try {
1396
+ const diagnostics = (0, type_checker_1.getTypeScriptDiagnostics)(code, 'temp.ts');
1397
+ const typeIssues = (0, type_checker_1.convertDiagnosticsToIssues)(diagnostics);
1398
+ // Convert SecurityIssue[] to SecurityVulnerability[]
1399
+ const typeVulnerabilities = typeIssues.map(issue => ({
1400
+ severity: issue.severity,
1401
+ message: issue.message,
1402
+ line: issue.line,
1403
+ suggestion: issue.suggestion,
1404
+ category: 'type-checking',
1405
+ cvssScore: issue.cvssScore,
1406
+ exploitLikelihood: issue.exploitLikelihood,
1407
+ impact: issue.impact,
1408
+ owasp: issue.owasp,
1409
+ cwe: issue.cwe
1410
+ }));
1411
+ vulnerabilities.push(...typeVulnerabilities);
1412
+ }
1413
+ catch (error) {
1414
+ // Gracefully degrade - if type checking fails, continue with pattern-based checks
1415
+ console.error('TypeScript type checking error:', error);
1416
+ }
1417
+ // Secrets Detection (Phase 1.5, Week 1)
1418
+ const secretsAnalyzer = (0, secrets_analyzer_1.createSecretsAnalyzer)();
1419
+ vulnerabilities.push(...secretsAnalyzer.analyzeCode(code, 'unknown.ts', 'typescript'));
1420
+ // P1-5: Deduplicate vulnerabilities on same line (Dec 30, 2025)
1421
+ // Fix for Beta Testing Issue: Same vulnerability detected multiple times on same line
1422
+ result.security.vulnerabilities = this.deduplicateVulnerabilities(vulnerabilities);
1423
+ }
1424
+ /**
1425
+ * P1-5: Generic deduplication for ALL vulnerability types (Dec 30, 2025)
1426
+ * Prevents same vulnerability from being reported multiple times on the same line
1427
+ *
1428
+ * Strategy: Use line + category as unique key, keep highest CVSS score
1429
+ */
1430
+ deduplicateVulnerabilities(vulnerabilities) {
1431
+ const getCategory = (message) => {
1432
+ const lower = message.toLowerCase();
1433
+ if (lower.includes('hardcoded credential'))
1434
+ return 'hardcoded-credential';
1435
+ if (lower.includes('sql injection'))
1436
+ return 'sql-injection';
1437
+ if (lower.includes('nosql injection'))
1438
+ return 'nosql-injection';
1439
+ if (lower.includes('command injection'))
1440
+ return 'command-injection';
1441
+ if (lower.includes('ldap injection'))
1442
+ return 'ldap-injection';
1443
+ if (lower.includes('xss') || lower.includes('cross-site scripting'))
1444
+ return 'xss';
1445
+ if (lower.includes('ssrf'))
1446
+ return 'ssrf';
1447
+ if (lower.includes('xxe') || lower.includes('xml external entity'))
1448
+ return 'xxe';
1449
+ if (lower.includes('deserialization'))
1450
+ return 'deserialization';
1451
+ if (lower.includes('prototype pollution'))
1452
+ return 'prototype-pollution';
1453
+ if (lower.includes('weak hash') || lower.includes('md5') || lower.includes('sha1'))
1454
+ return 'weak-hash';
1455
+ if (lower.includes('insecure random'))
1456
+ return 'insecure-random';
1457
+ if (lower.includes('missing helmet'))
1458
+ return 'missing-helmet';
1459
+ if (lower.includes('missing csrf'))
1460
+ return 'missing-csrf';
1461
+ if (lower.includes('eval'))
1462
+ return 'eval';
1463
+ if (lower.includes('path traversal'))
1464
+ return 'path-traversal';
1465
+ if (lower.includes('open redirect'))
1466
+ return 'open-redirect';
1467
+ if (lower.includes('jwt'))
1468
+ return 'jwt';
1469
+ if (lower.includes('cors'))
1470
+ return 'cors';
1471
+ if (lower.includes('insecure tls') || lower.includes('reject unauthorized'))
1472
+ return 'insecure-tls';
1473
+ // Fallback: use first 30 chars as category
1474
+ return message.substring(0, 30);
1475
+ };
1476
+ const uniqueMap = new Map();
1477
+ vulnerabilities.forEach(vuln => {
1478
+ const line = vuln.line || 0;
1479
+ const category = getCategory(vuln.message || '');
1480
+ const key = `${line}:${category}`;
1481
+ const existing = uniqueMap.get(key);
1482
+ if (!existing) {
1483
+ uniqueMap.set(key, vuln);
1484
+ }
1485
+ else {
1486
+ // Keep higher CVSS score
1487
+ const existingScore = existing.cvssScore || 0;
1488
+ const currentScore = vuln.cvssScore || 0;
1489
+ if (currentScore > existingScore) {
1490
+ uniqueMap.set(key, vuln);
1491
+ }
1492
+ }
1493
+ });
1494
+ return Array.from(uniqueMap.values());
1495
+ }
1496
+ /**
1497
+ * PHASE 6 WEEK 1 DAY 1: Detect duplicate identifier declarations
1498
+ *
1499
+ * Detects when variables, functions, classes, interfaces, or types are declared
1500
+ * multiple times in the same scope, which causes TypeScript compilation errors.
1501
+ *
1502
+ * Examples:
1503
+ * - const API_KEY = 'key1'; const API_KEY = 'key2'; → Duplicate
1504
+ * - function foo() {} function foo() {} → Duplicate
1505
+ * - interface User {} interface User {} → Duplicate (unless extending)
1506
+ *
1507
+ * Note: This is a simplified implementation that tracks identifiers at file scope.
1508
+ * Full scope tracking (block scope, function scope) would require AST parsing.
1509
+ */
1510
+ detectDuplicateIdentifiers(code, lineErrors) {
1511
+ const lines = code.split('\n');
1512
+ const declaredIdentifiers = new Map();
1513
+ lines.forEach((line, index) => {
1514
+ const lineNumber = index + 1;
1515
+ const trimmed = line.trim();
1516
+ // Skip comments and empty lines
1517
+ if (!trimmed || trimmed.startsWith('//') || trimmed.startsWith('/*') || trimmed.startsWith('*')) {
1518
+ return;
1519
+ }
1520
+ // Pattern 1: const/let/var declarations (with optional export)
1521
+ const varMatch = trimmed.match(/^\s*(?:export\s+)?(const|let|var)\s+([a-zA-Z_$][a-zA-Z0-9_$]*)/);
1522
+ if (varMatch) {
1523
+ const identifierType = varMatch[1]; // const, let, or var
1524
+ const identifierName = varMatch[2];
1525
+ if (declaredIdentifiers.has(identifierName)) {
1526
+ const previous = declaredIdentifiers.get(identifierName);
1527
+ lineErrors.push({
1528
+ line: lineNumber,
1529
+ error: `Duplicate identifier: '${identifierName}' was already declared on line ${previous.line}`,
1530
+ suggestion: `Rename this ${identifierType} or remove the duplicate declaration`,
1531
+ severity: 'error',
1532
+ references: references_1.typescriptStandards['type-errors'] || [],
1533
+ securityRelevant: false
1534
+ });
1535
+ }
1536
+ else {
1537
+ declaredIdentifiers.set(identifierName, { line: lineNumber, type: identifierType });
1538
+ }
1539
+ }
1540
+ // Pattern 2: Function declarations
1541
+ const funcMatch = trimmed.match(/^\s*function\s+([a-zA-Z_$][a-zA-Z0-9_$]*)/);
1542
+ if (funcMatch) {
1543
+ const identifierName = funcMatch[1];
1544
+ if (declaredIdentifiers.has(identifierName)) {
1545
+ const previous = declaredIdentifiers.get(identifierName);
1546
+ lineErrors.push({
1547
+ line: lineNumber,
1548
+ error: `Duplicate function declaration: '${identifierName}' was already declared on line ${previous.line}`,
1549
+ suggestion: `Rename this function or remove the duplicate declaration`,
1550
+ severity: 'error',
1551
+ references: references_1.typescriptStandards['type-errors'] || [],
1552
+ securityRelevant: false
1553
+ });
1554
+ }
1555
+ else {
1556
+ declaredIdentifiers.set(identifierName, { line: lineNumber, type: 'function' });
1557
+ }
1558
+ }
1559
+ // Pattern 3: Class declarations
1560
+ const classMatch = trimmed.match(/^\s*(?:export\s+)?class\s+([a-zA-Z_$][a-zA-Z0-9_$]*)/);
1561
+ if (classMatch) {
1562
+ const identifierName = classMatch[1];
1563
+ if (declaredIdentifiers.has(identifierName)) {
1564
+ const previous = declaredIdentifiers.get(identifierName);
1565
+ lineErrors.push({
1566
+ line: lineNumber,
1567
+ error: `Duplicate class declaration: '${identifierName}' was already declared on line ${previous.line}`,
1568
+ suggestion: `Rename this class or remove the duplicate declaration`,
1569
+ severity: 'error',
1570
+ references: references_1.typescriptStandards['type-errors'] || [],
1571
+ securityRelevant: false
1572
+ });
1573
+ }
1574
+ else {
1575
+ declaredIdentifiers.set(identifierName, { line: lineNumber, type: 'class' });
1576
+ }
1577
+ }
1578
+ // Pattern 4: Interface declarations (allow interface merging - only warn if suspicious)
1579
+ const interfaceMatch = trimmed.match(/^\s*(?:export\s+)?interface\s+([a-zA-Z_$][a-zA-Z0-9_$]*)/);
1580
+ if (interfaceMatch) {
1581
+ const identifierName = interfaceMatch[1];
1582
+ if (declaredIdentifiers.has(identifierName)) {
1583
+ const previous = declaredIdentifiers.get(identifierName);
1584
+ // Interface merging is allowed in TypeScript, but warn if it might be unintentional
1585
+ if (previous.type === 'interface') {
1586
+ lineErrors.push({
1587
+ line: lineNumber,
1588
+ error: `Duplicate interface declaration: '${identifierName}' was already declared on line ${previous.line} (interface merging may be intentional)`,
1589
+ suggestion: `If intentional (interface merging), this is OK. Otherwise, rename one of the interfaces.`,
1590
+ severity: 'warning', // Warning, not error, because interface merging is valid
1591
+ references: references_1.typescriptStandards['class-interface'] || [],
1592
+ securityRelevant: false
1593
+ });
1594
+ }
1595
+ }
1596
+ else {
1597
+ declaredIdentifiers.set(identifierName, { line: lineNumber, type: 'interface' });
1598
+ }
1599
+ }
1600
+ // Pattern 5: Type alias declarations
1601
+ const typeMatch = trimmed.match(/^\s*(?:export\s+)?type\s+([a-zA-Z_$][a-zA-Z0-9_$]*)/);
1602
+ if (typeMatch) {
1603
+ const identifierName = typeMatch[1];
1604
+ if (declaredIdentifiers.has(identifierName)) {
1605
+ const previous = declaredIdentifiers.get(identifierName);
1606
+ lineErrors.push({
1607
+ line: lineNumber,
1608
+ error: `Duplicate type alias: '${identifierName}' was already declared on line ${previous.line}`,
1609
+ suggestion: `Rename this type or remove the duplicate declaration`,
1610
+ severity: 'error',
1611
+ references: references_1.typescriptStandards['type-errors'] || [],
1612
+ securityRelevant: false
1613
+ });
1614
+ }
1615
+ else {
1616
+ declaredIdentifiers.set(identifierName, { line: lineNumber, type: 'type' });
1617
+ }
1618
+ }
1619
+ // Pattern 6: Enum declarations
1620
+ const enumMatch = trimmed.match(/^\s*(?:export\s+)?enum\s+([a-zA-Z_$][a-zA-Z0-9_$]*)/);
1621
+ if (enumMatch) {
1622
+ const identifierName = enumMatch[1];
1623
+ if (declaredIdentifiers.has(identifierName)) {
1624
+ const previous = declaredIdentifiers.get(identifierName);
1625
+ lineErrors.push({
1626
+ line: lineNumber,
1627
+ error: `Duplicate enum declaration: '${identifierName}' was already declared on line ${previous.line}`,
1628
+ suggestion: `Rename this enum or remove the duplicate declaration`,
1629
+ severity: 'error',
1630
+ references: references_1.typescriptStandards['type-errors'] || [],
1631
+ securityRelevant: false
1632
+ });
1633
+ }
1634
+ else {
1635
+ declaredIdentifiers.set(identifierName, { line: lineNumber, type: 'enum' });
1636
+ }
1637
+ }
1638
+ });
1639
+ }
1640
+ calculateMetrics(code, result) {
1641
+ const lines = code.split('\n');
1642
+ result.metrics.lines = lines.length;
1643
+ const functions = (code.match(/function\s+\w+/g) || []).length;
1644
+ const arrowFunctions = (code.match(/=>\s*\{/g) || []).length;
1645
+ result.metrics.functions = functions + arrowFunctions;
1646
+ let complexity = 1;
1647
+ const keywords = ['if', 'else', 'for', 'while', 'switch', 'case', 'catch', '&&', '||', '?'];
1648
+ keywords.forEach(keyword => {
1649
+ // Escape special regex characters
1650
+ const escapedKeyword = keyword.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
1651
+ const matches = code.match(new RegExp(`\\b${escapedKeyword}\\b`, 'g'));
1652
+ if (matches)
1653
+ complexity += matches.length;
1654
+ });
1655
+ result.metrics.complexity = complexity;
1656
+ result.metrics.maintainability = Math.max(0, 100 - complexity * 3);
1657
+ }
1658
+ }
1659
+ exports.TypeScriptAnalyzer = TypeScriptAnalyzer;
1660
+ //# sourceMappingURL=typescript-analyzer.js.map