@agentic-qe/v3 3.0.0-alpha.6 → 3.0.0-alpha.8

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 (612) hide show
  1. package/assets/agents/v3/subagents/v3-qe-code-reviewer.md +339 -0
  2. package/assets/agents/v3/subagents/v3-qe-integration-reviewer.md +344 -0
  3. package/assets/agents/v3/subagents/v3-qe-performance-reviewer.md +351 -0
  4. package/assets/agents/v3/subagents/v3-qe-security-reviewer.md +374 -0
  5. package/assets/agents/v3/subagents/v3-qe-tdd-green.md +334 -0
  6. package/assets/agents/v3/subagents/v3-qe-tdd-red.md +329 -0
  7. package/assets/agents/v3/subagents/v3-qe-tdd-refactor.md +361 -0
  8. package/assets/agents/v3/v3-qe-accessibility-auditor.md +266 -0
  9. package/assets/agents/v3/v3-qe-bdd-generator.md +279 -0
  10. package/assets/agents/v3/v3-qe-chaos-engineer.md +265 -0
  11. package/assets/agents/v3/v3-qe-code-complexity.md +298 -0
  12. package/assets/agents/v3/v3-qe-code-intelligence.md +262 -0
  13. package/assets/agents/v3/v3-qe-contract-validator.md +267 -0
  14. package/assets/agents/v3/v3-qe-coverage-specialist.md +227 -0
  15. package/assets/agents/v3/v3-qe-defect-predictor.md +251 -0
  16. package/assets/agents/v3/v3-qe-dependency-mapper.md +277 -0
  17. package/assets/agents/v3/v3-qe-deployment-advisor.md +275 -0
  18. package/assets/agents/v3/v3-qe-flaky-hunter.md +248 -0
  19. package/assets/agents/v3/v3-qe-fleet-commander.md +293 -0
  20. package/assets/agents/v3/v3-qe-gap-detector.md +260 -0
  21. package/assets/agents/v3/v3-qe-graphql-tester.md +308 -0
  22. package/assets/agents/v3/v3-qe-impact-analyzer.md +299 -0
  23. package/assets/agents/v3/v3-qe-integration-tester.md +238 -0
  24. package/assets/agents/v3/v3-qe-kg-builder.md +273 -0
  25. package/assets/agents/v3/v3-qe-learning-coordinator.md +226 -0
  26. package/assets/agents/v3/v3-qe-load-tester.md +280 -0
  27. package/assets/agents/v3/v3-qe-metrics-optimizer.md +300 -0
  28. package/assets/agents/v3/v3-qe-mutation-tester.md +301 -0
  29. package/assets/agents/v3/v3-qe-parallel-executor.md +240 -0
  30. package/assets/agents/v3/v3-qe-pattern-learner.md +271 -0
  31. package/assets/agents/v3/v3-qe-performance-tester.md +262 -0
  32. package/assets/agents/v3/v3-qe-property-tester.md +247 -0
  33. package/assets/agents/v3/v3-qe-quality-gate.md +218 -0
  34. package/assets/agents/v3/v3-qe-queen-coordinator.md +214 -0
  35. package/assets/agents/v3/v3-qe-qx-partner.md +313 -0
  36. package/assets/agents/v3/v3-qe-regression-analyzer.md +322 -0
  37. package/assets/agents/v3/v3-qe-requirements-validator.md +360 -0
  38. package/assets/agents/v3/v3-qe-responsive-tester.md +311 -0
  39. package/assets/agents/v3/v3-qe-retry-handler.md +256 -0
  40. package/assets/agents/v3/v3-qe-risk-assessor.md +273 -0
  41. package/assets/agents/v3/v3-qe-root-cause-analyzer.md +286 -0
  42. package/assets/agents/v3/v3-qe-security-auditor.md +299 -0
  43. package/assets/agents/v3/v3-qe-security-scanner.md +235 -0
  44. package/assets/agents/v3/v3-qe-tdd-specialist.md +239 -0
  45. package/assets/agents/v3/v3-qe-test-architect.md +233 -0
  46. package/assets/agents/v3/v3-qe-transfer-specialist.md +295 -0
  47. package/assets/agents/v3/v3-qe-visual-tester.md +232 -0
  48. package/assets/skills/accessibility-testing/SKILL.md +216 -0
  49. package/assets/skills/agentdb-advanced/SKILL.md +550 -0
  50. package/assets/skills/agentdb-learning/SKILL.md +545 -0
  51. package/assets/skills/agentdb-memory-patterns/SKILL.md +339 -0
  52. package/assets/skills/agentdb-optimization/SKILL.md +509 -0
  53. package/assets/skills/agentdb-vector-search/SKILL.md +339 -0
  54. package/assets/skills/agentic-jujutsu/SKILL.md +645 -0
  55. package/assets/skills/agentic-quality-engineering/SKILL.md +335 -0
  56. package/assets/skills/api-testing-patterns/SKILL.md +294 -0
  57. package/assets/skills/aqe-v2-v3-migration/skill.md +322 -0
  58. package/assets/skills/brutal-honesty-review/README.md +218 -0
  59. package/assets/skills/brutal-honesty-review/SKILL.md +235 -0
  60. package/assets/skills/brutal-honesty-review/resources/assessment-rubrics.md +295 -0
  61. package/assets/skills/brutal-honesty-review/resources/review-template.md +102 -0
  62. package/assets/skills/brutal-honesty-review/scripts/assess-code.sh +179 -0
  63. package/assets/skills/brutal-honesty-review/scripts/assess-tests.sh +223 -0
  64. package/assets/skills/bug-reporting-excellence/SKILL.md +225 -0
  65. package/assets/skills/chaos-engineering-resilience/SKILL.md +158 -0
  66. package/assets/skills/cicd-pipeline-qe-orchestrator/README.md +304 -0
  67. package/assets/skills/cicd-pipeline-qe-orchestrator/SKILL.md +315 -0
  68. package/assets/skills/cicd-pipeline-qe-orchestrator/resources/workflows/microservice-pipeline.md +239 -0
  69. package/assets/skills/cicd-pipeline-qe-orchestrator/resources/workflows/mobile-pipeline.md +375 -0
  70. package/assets/skills/cicd-pipeline-qe-orchestrator/resources/workflows/monolith-pipeline.md +268 -0
  71. package/assets/skills/code-review-quality/SKILL.md +227 -0
  72. package/assets/skills/compatibility-testing/SKILL.md +205 -0
  73. package/assets/skills/compliance-testing/SKILL.md +225 -0
  74. package/assets/skills/consultancy-practices/SKILL.md +202 -0
  75. package/assets/skills/context-driven-testing/SKILL.md +196 -0
  76. package/assets/skills/contract-testing/SKILL.md +222 -0
  77. package/assets/skills/database-testing/SKILL.md +244 -0
  78. package/assets/skills/exploratory-testing-advanced/SKILL.md +201 -0
  79. package/assets/skills/flow-nexus-neural/SKILL.md +738 -0
  80. package/assets/skills/flow-nexus-platform/SKILL.md +1157 -0
  81. package/assets/skills/flow-nexus-swarm/SKILL.md +610 -0
  82. package/assets/skills/github-code-review/SKILL.md +1140 -0
  83. package/assets/skills/github-multi-repo/SKILL.md +874 -0
  84. package/assets/skills/github-project-management/SKILL.md +1277 -0
  85. package/assets/skills/github-release-management/SKILL.md +1081 -0
  86. package/assets/skills/github-workflow-automation/SKILL.md +1065 -0
  87. package/assets/skills/hive-mind-advanced/SKILL.md +712 -0
  88. package/assets/skills/holistic-testing-pact/SKILL.md +171 -0
  89. package/assets/skills/hooks-automation/SKILL.md +1201 -0
  90. package/assets/skills/localization-testing/SKILL.md +221 -0
  91. package/assets/skills/mobile-testing/SKILL.md +219 -0
  92. package/assets/skills/mutation-testing/SKILL.md +229 -0
  93. package/assets/skills/n8n-expression-testing/SKILL.md +434 -0
  94. package/assets/skills/n8n-integration-testing-patterns/SKILL.md +540 -0
  95. package/assets/skills/n8n-security-testing/SKILL.md +599 -0
  96. package/assets/skills/n8n-trigger-testing-strategies/SKILL.md +541 -0
  97. package/assets/skills/n8n-workflow-testing-fundamentals/SKILL.md +447 -0
  98. package/assets/skills/pair-programming/SKILL.md +1202 -0
  99. package/assets/skills/performance-analysis/SKILL.md +563 -0
  100. package/assets/skills/performance-testing/SKILL.md +310 -0
  101. package/assets/skills/quality-metrics/SKILL.md +225 -0
  102. package/assets/skills/reasoningbank-agentdb/SKILL.md +446 -0
  103. package/assets/skills/reasoningbank-intelligence/SKILL.md +201 -0
  104. package/assets/skills/refactoring-patterns/SKILL.md +205 -0
  105. package/assets/skills/regression-testing/SKILL.md +227 -0
  106. package/assets/skills/risk-based-testing/SKILL.md +206 -0
  107. package/assets/skills/security-testing/SKILL.md +306 -0
  108. package/assets/skills/sherlock-review/SKILL.md +250 -0
  109. package/assets/skills/shift-left-testing/SKILL.md +225 -0
  110. package/assets/skills/shift-right-testing/SKILL.md +227 -0
  111. package/assets/skills/six-thinking-hats/README.md +190 -0
  112. package/assets/skills/six-thinking-hats/SKILL.md +280 -0
  113. package/assets/skills/six-thinking-hats/resources/examples/api-testing-example.md +345 -0
  114. package/assets/skills/six-thinking-hats/resources/templates/solo-session-template.md +167 -0
  115. package/assets/skills/six-thinking-hats/resources/templates/team-session-template.md +336 -0
  116. package/assets/skills/skill-builder/SKILL.md +910 -0
  117. package/assets/skills/sparc-methodology/SKILL.md +1115 -0
  118. package/assets/skills/stream-chain/SKILL.md +563 -0
  119. package/assets/skills/swarm-advanced/SKILL.md +973 -0
  120. package/assets/skills/swarm-orchestration/SKILL.md +179 -0
  121. package/assets/skills/tdd-london-chicago/SKILL.md +244 -0
  122. package/assets/skills/technical-writing/SKILL.md +178 -0
  123. package/assets/skills/test-automation-strategy/SKILL.md +230 -0
  124. package/assets/skills/test-data-management/SKILL.md +270 -0
  125. package/assets/skills/test-design-techniques/SKILL.md +244 -0
  126. package/assets/skills/test-environment-management/SKILL.md +243 -0
  127. package/assets/skills/test-reporting-analytics/SKILL.md +214 -0
  128. package/assets/skills/testability-scoring/README.md +71 -0
  129. package/assets/skills/testability-scoring/SKILL.md +346 -0
  130. package/assets/skills/testability-scoring/resources/templates/config.template.js +84 -0
  131. package/assets/skills/testability-scoring/resources/templates/testability-scoring.spec.template.js +532 -0
  132. package/assets/skills/testability-scoring/scripts/generate-html-report.js +1007 -0
  133. package/assets/skills/testability-scoring/scripts/run-assessment.sh +70 -0
  134. package/assets/skills/v3-qe-chaos-resilience/SKILL.md +238 -0
  135. package/assets/skills/v3-qe-code-intelligence/SKILL.md +209 -0
  136. package/assets/skills/v3-qe-contract-testing/SKILL.md +218 -0
  137. package/assets/skills/v3-qe-coverage-analysis/SKILL.md +187 -0
  138. package/assets/skills/v3-qe-defect-intelligence/SKILL.md +205 -0
  139. package/assets/skills/v3-qe-learning-optimization/SKILL.md +238 -0
  140. package/assets/skills/v3-qe-quality-assessment/SKILL.md +213 -0
  141. package/assets/skills/v3-qe-requirements-validation/SKILL.md +248 -0
  142. package/assets/skills/v3-qe-test-execution/SKILL.md +182 -0
  143. package/assets/skills/v3-qe-test-generation/SKILL.md +141 -0
  144. package/assets/skills/v3-qe-visual-accessibility/SKILL.md +242 -0
  145. package/assets/skills/verification-quality/SKILL.md +649 -0
  146. package/assets/skills/visual-testing-advanced/SKILL.md +219 -0
  147. package/assets/skills/xp-practices/SKILL.md +229 -0
  148. package/dist/cli/bundle.js +23 -13
  149. package/dist/init/agents-installer.js +4 -4
  150. package/dist/init/agents-installer.js.map +1 -1
  151. package/dist/init/init-wizard.d.ts.map +1 -1
  152. package/dist/init/init-wizard.js +15 -5
  153. package/dist/init/init-wizard.js.map +1 -1
  154. package/dist/init/skills-installer.js +4 -4
  155. package/dist/init/skills-installer.js.map +1 -1
  156. package/package.json +7 -1
  157. package/docs/analysis/V3-INIT-REQUIREMENTS-ANALYSIS.md +0 -352
  158. package/implementation/README.md +0 -90
  159. package/implementation/adrs/ADR-030-coherence-gated-quality-gates.md +0 -312
  160. package/implementation/adrs/ADR-031-strange-loop-self-awareness.md +0 -484
  161. package/implementation/adrs/ADR-032-time-crystal-scheduling.md +0 -530
  162. package/implementation/adrs/ADR-033-early-exit-testing.md +0 -634
  163. package/implementation/adrs/ADR-034-neural-topology-optimizer.md +0 -589
  164. package/implementation/adrs/ADR-035-causal-discovery.md +0 -610
  165. package/implementation/adrs/ADR-036-result-persistence.md +0 -326
  166. package/implementation/adrs/ADR-037-v3-qe-agent-naming.md +0 -105
  167. package/implementation/adrs/ADR-038-v3-qe-memory-unification.md +0 -154
  168. package/implementation/adrs/ADR-039-v3-qe-mcp-optimization.md +0 -179
  169. package/implementation/adrs/ADR-040-v3-qe-agentic-flow-integration.md +0 -240
  170. package/implementation/adrs/ADR-041-v3-qe-cli-enhancement.md +0 -296
  171. package/implementation/adrs/ADR-042-v3-qe-token-tracking-integration.md +0 -517
  172. package/implementation/adrs/v3-adrs.md +0 -2783
  173. package/implementation/planning/AQE-V3-MASTER-PLAN.md +0 -815
  174. package/security-scan-report-2026-01-11.md +0 -410
  175. package/security-verification-report-2026-01-11.md +0 -278
  176. package/src/benchmarks/performance-benchmarks.ts +0 -646
  177. package/src/benchmarks/run-benchmarks.ts +0 -324
  178. package/src/causal-discovery/causal-graph.ts +0 -450
  179. package/src/causal-discovery/discovery-engine.ts +0 -438
  180. package/src/causal-discovery/index.ts +0 -117
  181. package/src/causal-discovery/types.ts +0 -456
  182. package/src/causal-discovery/weight-matrix.ts +0 -453
  183. package/src/cli/commands/qe-tools.ts +0 -634
  184. package/src/cli/index.ts +0 -1976
  185. package/src/compatibility/agent-mapper.ts +0 -291
  186. package/src/compatibility/cli-adapter.ts +0 -277
  187. package/src/compatibility/config-migrator.ts +0 -334
  188. package/src/compatibility/index.ts +0 -112
  189. package/src/compatibility/mcp-adapter.ts +0 -248
  190. package/src/compatibility/types.ts +0 -156
  191. package/src/coordination/claims/claim-repository.ts +0 -636
  192. package/src/coordination/claims/claim-service.ts +0 -675
  193. package/src/coordination/claims/handoff-manager.ts +0 -535
  194. package/src/coordination/claims/index.ts +0 -276
  195. package/src/coordination/claims/interfaces.ts +0 -687
  196. package/src/coordination/claims/work-stealing.ts +0 -436
  197. package/src/coordination/cross-domain-router.ts +0 -492
  198. package/src/coordination/index.ts +0 -127
  199. package/src/coordination/interfaces.ts +0 -691
  200. package/src/coordination/protocol-executor.ts +0 -760
  201. package/src/coordination/protocols/code-intelligence-index.ts +0 -855
  202. package/src/coordination/protocols/defect-investigation.ts +0 -1184
  203. package/src/coordination/protocols/index.ts +0 -11
  204. package/src/coordination/protocols/learning-consolidation.ts +0 -1181
  205. package/src/coordination/protocols/morning-sync.ts +0 -1055
  206. package/src/coordination/protocols/quality-gate.ts +0 -1566
  207. package/src/coordination/protocols/security-audit.ts +0 -1587
  208. package/src/coordination/queen-coordinator.ts +0 -1176
  209. package/src/coordination/result-saver.ts +0 -780
  210. package/src/coordination/task-executor.ts +0 -1146
  211. package/src/coordination/workflow-orchestrator.ts +0 -1917
  212. package/src/domains/chaos-resilience/coordinator.ts +0 -1032
  213. package/src/domains/chaos-resilience/index.ts +0 -143
  214. package/src/domains/chaos-resilience/interfaces.ts +0 -659
  215. package/src/domains/chaos-resilience/plugin.ts +0 -691
  216. package/src/domains/chaos-resilience/services/chaos-engineer.ts +0 -1097
  217. package/src/domains/chaos-resilience/services/index.ts +0 -19
  218. package/src/domains/chaos-resilience/services/load-tester.ts +0 -799
  219. package/src/domains/chaos-resilience/services/performance-profiler.ts +0 -792
  220. package/src/domains/code-intelligence/coordinator.ts +0 -631
  221. package/src/domains/code-intelligence/index.ts +0 -86
  222. package/src/domains/code-intelligence/interfaces.ts +0 -162
  223. package/src/domains/code-intelligence/plugin.ts +0 -451
  224. package/src/domains/code-intelligence/services/impact-analyzer.ts +0 -567
  225. package/src/domains/code-intelligence/services/index.ts +0 -26
  226. package/src/domains/code-intelligence/services/knowledge-graph.ts +0 -1067
  227. package/src/domains/code-intelligence/services/semantic-analyzer.ts +0 -901
  228. package/src/domains/contract-testing/coordinator.ts +0 -1038
  229. package/src/domains/contract-testing/index.ts +0 -122
  230. package/src/domains/contract-testing/interfaces.ts +0 -458
  231. package/src/domains/contract-testing/plugin.ts +0 -746
  232. package/src/domains/contract-testing/services/api-compatibility.ts +0 -748
  233. package/src/domains/contract-testing/services/contract-validator.ts +0 -1700
  234. package/src/domains/contract-testing/services/index.ts +0 -19
  235. package/src/domains/contract-testing/services/schema-validator.ts +0 -1102
  236. package/src/domains/coverage-analysis/coordinator.ts +0 -485
  237. package/src/domains/coverage-analysis/index.ts +0 -114
  238. package/src/domains/coverage-analysis/interfaces.ts +0 -142
  239. package/src/domains/coverage-analysis/plugin.ts +0 -172
  240. package/src/domains/coverage-analysis/services/coverage-analyzer.ts +0 -449
  241. package/src/domains/coverage-analysis/services/coverage-embedder.ts +0 -733
  242. package/src/domains/coverage-analysis/services/coverage-parser.ts +0 -753
  243. package/src/domains/coverage-analysis/services/gap-detector.ts +0 -592
  244. package/src/domains/coverage-analysis/services/hnsw-index.ts +0 -728
  245. package/src/domains/coverage-analysis/services/index.ts +0 -61
  246. package/src/domains/coverage-analysis/services/risk-scorer.ts +0 -540
  247. package/src/domains/coverage-analysis/services/sublinear-analyzer.ts +0 -747
  248. package/src/domains/defect-intelligence/coordinator.ts +0 -635
  249. package/src/domains/defect-intelligence/index.ts +0 -83
  250. package/src/domains/defect-intelligence/interfaces.ts +0 -152
  251. package/src/domains/defect-intelligence/plugin.ts +0 -483
  252. package/src/domains/defect-intelligence/services/causal-root-cause-analyzer.ts +0 -494
  253. package/src/domains/defect-intelligence/services/defect-predictor.ts +0 -852
  254. package/src/domains/defect-intelligence/services/index.ts +0 -37
  255. package/src/domains/defect-intelligence/services/pattern-learner.ts +0 -738
  256. package/src/domains/defect-intelligence/services/root-cause-analyzer.ts +0 -637
  257. package/src/domains/domain-interface.ts +0 -77
  258. package/src/domains/index.ts +0 -23
  259. package/src/domains/learning-optimization/coordinator.ts +0 -1215
  260. package/src/domains/learning-optimization/index.ts +0 -127
  261. package/src/domains/learning-optimization/interfaces.ts +0 -570
  262. package/src/domains/learning-optimization/plugin.ts +0 -851
  263. package/src/domains/learning-optimization/services/index.ts +0 -29
  264. package/src/domains/learning-optimization/services/learning-coordinator.ts +0 -972
  265. package/src/domains/learning-optimization/services/metrics-optimizer.ts +0 -915
  266. package/src/domains/learning-optimization/services/production-intel.ts +0 -971
  267. package/src/domains/learning-optimization/services/transfer-specialist.ts +0 -723
  268. package/src/domains/quality-assessment/coherence/gate-controller.ts +0 -549
  269. package/src/domains/quality-assessment/coherence/index.ts +0 -211
  270. package/src/domains/quality-assessment/coherence/lambda-calculator.ts +0 -384
  271. package/src/domains/quality-assessment/coherence/partition-detector.ts +0 -469
  272. package/src/domains/quality-assessment/coherence/types.ts +0 -384
  273. package/src/domains/quality-assessment/coordinator.ts +0 -605
  274. package/src/domains/quality-assessment/index.ts +0 -97
  275. package/src/domains/quality-assessment/interfaces.ts +0 -152
  276. package/src/domains/quality-assessment/plugin.ts +0 -496
  277. package/src/domains/quality-assessment/services/coherence-gate.ts +0 -358
  278. package/src/domains/quality-assessment/services/deployment-advisor.ts +0 -571
  279. package/src/domains/quality-assessment/services/index.ts +0 -34
  280. package/src/domains/quality-assessment/services/quality-analyzer.ts +0 -670
  281. package/src/domains/quality-assessment/services/quality-gate.ts +0 -384
  282. package/src/domains/requirements-validation/coordinator.ts +0 -812
  283. package/src/domains/requirements-validation/index.ts +0 -92
  284. package/src/domains/requirements-validation/interfaces.ts +0 -303
  285. package/src/domains/requirements-validation/plugin.ts +0 -576
  286. package/src/domains/requirements-validation/services/bdd-scenario-writer.ts +0 -676
  287. package/src/domains/requirements-validation/services/index.ts +0 -20
  288. package/src/domains/requirements-validation/services/requirements-validator.ts +0 -559
  289. package/src/domains/requirements-validation/services/testability-scorer.ts +0 -639
  290. package/src/domains/security-compliance/coordinator.ts +0 -757
  291. package/src/domains/security-compliance/index.ts +0 -120
  292. package/src/domains/security-compliance/interfaces.ts +0 -434
  293. package/src/domains/security-compliance/plugin.ts +0 -509
  294. package/src/domains/security-compliance/services/compliance-validator.ts +0 -1226
  295. package/src/domains/security-compliance/services/index.ts +0 -31
  296. package/src/domains/security-compliance/services/security-auditor.ts +0 -2227
  297. package/src/domains/security-compliance/services/security-scanner.ts +0 -2354
  298. package/src/domains/security-compliance/services/semgrep-integration.ts +0 -289
  299. package/src/domains/test-execution/coordinator.ts +0 -426
  300. package/src/domains/test-execution/index.ts +0 -76
  301. package/src/domains/test-execution/interfaces.ts +0 -119
  302. package/src/domains/test-execution/plugin.ts +0 -208
  303. package/src/domains/test-execution/services/flaky-detector.ts +0 -1240
  304. package/src/domains/test-execution/services/index.ts +0 -8
  305. package/src/domains/test-execution/services/retry-handler.ts +0 -820
  306. package/src/domains/test-execution/services/test-executor.ts +0 -885
  307. package/src/domains/test-generation/coordinator.ts +0 -656
  308. package/src/domains/test-generation/index.ts +0 -77
  309. package/src/domains/test-generation/interfaces.ts +0 -118
  310. package/src/domains/test-generation/plugin.ts +0 -397
  311. package/src/domains/test-generation/services/index.ts +0 -23
  312. package/src/domains/test-generation/services/pattern-matcher.ts +0 -1725
  313. package/src/domains/test-generation/services/test-generator.ts +0 -2750
  314. package/src/domains/visual-accessibility/coordinator.ts +0 -860
  315. package/src/domains/visual-accessibility/index.ts +0 -116
  316. package/src/domains/visual-accessibility/interfaces.ts +0 -435
  317. package/src/domains/visual-accessibility/plugin.ts +0 -568
  318. package/src/domains/visual-accessibility/services/accessibility-tester.ts +0 -982
  319. package/src/domains/visual-accessibility/services/axe-core-audit.ts +0 -630
  320. package/src/domains/visual-accessibility/services/index.ts +0 -28
  321. package/src/domains/visual-accessibility/services/responsive-tester.ts +0 -934
  322. package/src/domains/visual-accessibility/services/visual-tester.ts +0 -458
  323. package/src/early-exit/early-exit-controller.ts +0 -490
  324. package/src/early-exit/early-exit-decision.ts +0 -391
  325. package/src/early-exit/index.ts +0 -115
  326. package/src/early-exit/quality-signal.ts +0 -389
  327. package/src/early-exit/speculative-executor.ts +0 -505
  328. package/src/early-exit/types.ts +0 -407
  329. package/src/feedback/coverage-learner.ts +0 -456
  330. package/src/feedback/feedback-loop.ts +0 -426
  331. package/src/feedback/index.ts +0 -72
  332. package/src/feedback/pattern-promotion.ts +0 -373
  333. package/src/feedback/quality-score-calculator.ts +0 -334
  334. package/src/feedback/test-outcome-tracker.ts +0 -450
  335. package/src/feedback/types.ts +0 -497
  336. package/src/index.ts +0 -224
  337. package/src/init/agents-installer.ts +0 -536
  338. package/src/init/index.ts +0 -80
  339. package/src/init/init-wizard.ts +0 -1061
  340. package/src/init/project-analyzer.ts +0 -696
  341. package/src/init/self-configurator.ts +0 -488
  342. package/src/init/skills-installer.ts +0 -467
  343. package/src/init/types.ts +0 -432
  344. package/src/integrations/ruvector/ast-complexity.ts +0 -470
  345. package/src/integrations/ruvector/coverage-router.ts +0 -594
  346. package/src/integrations/ruvector/diff-risk-classifier.ts +0 -759
  347. package/src/integrations/ruvector/fallback.ts +0 -942
  348. package/src/integrations/ruvector/graph-boundaries.ts +0 -809
  349. package/src/integrations/ruvector/index.ts +0 -363
  350. package/src/integrations/ruvector/interfaces.ts +0 -609
  351. package/src/integrations/ruvector/q-learning-router.ts +0 -550
  352. package/src/kernel/agent-coordinator.ts +0 -165
  353. package/src/kernel/agentdb-backend.ts +0 -504
  354. package/src/kernel/event-bus.ts +0 -129
  355. package/src/kernel/hybrid-backend.ts +0 -538
  356. package/src/kernel/index.ts +0 -28
  357. package/src/kernel/interfaces.ts +0 -257
  358. package/src/kernel/kernel.ts +0 -285
  359. package/src/kernel/memory-backend.ts +0 -169
  360. package/src/kernel/memory-factory.ts +0 -293
  361. package/src/kernel/plugin-loader.ts +0 -179
  362. package/src/learning/index.ts +0 -219
  363. package/src/learning/pattern-store.ts +0 -990
  364. package/src/learning/qe-guidance.ts +0 -832
  365. package/src/learning/qe-hooks.ts +0 -644
  366. package/src/learning/qe-patterns.ts +0 -449
  367. package/src/learning/qe-reasoning-bank.ts +0 -951
  368. package/src/learning/real-embeddings.ts +0 -277
  369. package/src/learning/real-qe-reasoning-bank.ts +0 -833
  370. package/src/learning/sqlite-persistence.ts +0 -554
  371. package/src/mcp/entry.ts +0 -59
  372. package/src/mcp/handlers/agent-handlers.ts +0 -285
  373. package/src/mcp/handlers/core-handlers.ts +0 -317
  374. package/src/mcp/handlers/domain-handlers.ts +0 -1444
  375. package/src/mcp/handlers/index.ts +0 -57
  376. package/src/mcp/handlers/memory-handlers.ts +0 -338
  377. package/src/mcp/handlers/task-handlers.ts +0 -363
  378. package/src/mcp/index.ts +0 -30
  379. package/src/mcp/metrics/index.ts +0 -14
  380. package/src/mcp/metrics/metrics-collector.ts +0 -503
  381. package/src/mcp/protocol-server.ts +0 -752
  382. package/src/mcp/security/cve-prevention.ts +0 -742
  383. package/src/mcp/security/index.ts +0 -356
  384. package/src/mcp/security/oauth21-provider.ts +0 -821
  385. package/src/mcp/security/rate-limiter.ts +0 -615
  386. package/src/mcp/security/sampling-server.ts +0 -662
  387. package/src/mcp/security/schema-validator.ts +0 -855
  388. package/src/mcp/server.ts +0 -657
  389. package/src/mcp/tool-registry.ts +0 -391
  390. package/src/mcp/tools/base.ts +0 -399
  391. package/src/mcp/tools/chaos-resilience/inject.ts +0 -699
  392. package/src/mcp/tools/code-intelligence/analyze.ts +0 -745
  393. package/src/mcp/tools/contract-testing/validate.ts +0 -708
  394. package/src/mcp/tools/coverage-analysis/index.ts +0 -770
  395. package/src/mcp/tools/defect-intelligence/predict.ts +0 -466
  396. package/src/mcp/tools/index.ts +0 -214
  397. package/src/mcp/tools/learning-optimization/optimize.ts +0 -772
  398. package/src/mcp/tools/quality-assessment/evaluate.ts +0 -385
  399. package/src/mcp/tools/registry.ts +0 -248
  400. package/src/mcp/tools/requirements-validation/validate.ts +0 -394
  401. package/src/mcp/tools/security-compliance/scan.ts +0 -365
  402. package/src/mcp/tools/test-execution/execute.ts +0 -291
  403. package/src/mcp/tools/test-generation/generate.ts +0 -544
  404. package/src/mcp/tools/visual-accessibility/index.ts +0 -791
  405. package/src/mcp/transport/index.ts +0 -31
  406. package/src/mcp/transport/stdio.ts +0 -318
  407. package/src/mcp/types.ts +0 -543
  408. package/src/neural-optimizer/index.ts +0 -111
  409. package/src/neural-optimizer/replay-buffer.ts +0 -455
  410. package/src/neural-optimizer/swarm-topology.ts +0 -508
  411. package/src/neural-optimizer/topology-optimizer.ts +0 -828
  412. package/src/neural-optimizer/types.ts +0 -481
  413. package/src/neural-optimizer/value-network.ts +0 -351
  414. package/src/optimization/auto-tuner.ts +0 -817
  415. package/src/optimization/index.ts +0 -77
  416. package/src/optimization/metric-collectors.ts +0 -474
  417. package/src/optimization/qe-workers.ts +0 -704
  418. package/src/optimization/tuning-algorithm.ts +0 -401
  419. package/src/optimization/types.ts +0 -314
  420. package/src/routing/index.ts +0 -51
  421. package/src/routing/qe-agent-registry.ts +0 -963
  422. package/src/routing/qe-task-router.ts +0 -564
  423. package/src/routing/routing-feedback.ts +0 -365
  424. package/src/routing/types.ts +0 -406
  425. package/src/shared/embeddings/embedding-cache.ts +0 -157
  426. package/src/shared/embeddings/index.ts +0 -50
  427. package/src/shared/embeddings/nomic-embedder.ts +0 -404
  428. package/src/shared/embeddings/ollama-client.ts +0 -195
  429. package/src/shared/embeddings/types.ts +0 -147
  430. package/src/shared/entities/agent.ts +0 -141
  431. package/src/shared/entities/base-entity.ts +0 -79
  432. package/src/shared/entities/index.ts +0 -6
  433. package/src/shared/events/domain-events.ts +0 -259
  434. package/src/shared/events/index.ts +0 -5
  435. package/src/shared/git/git-analyzer.ts +0 -656
  436. package/src/shared/git/index.ts +0 -11
  437. package/src/shared/http/http-client.ts +0 -420
  438. package/src/shared/http/index.ts +0 -13
  439. package/src/shared/index.ts +0 -41
  440. package/src/shared/io/file-reader.ts +0 -525
  441. package/src/shared/io/index.ts +0 -25
  442. package/src/shared/llm/cache.ts +0 -473
  443. package/src/shared/llm/circuit-breaker.ts +0 -369
  444. package/src/shared/llm/cost-tracker.ts +0 -460
  445. package/src/shared/llm/index.ts +0 -140
  446. package/src/shared/llm/interfaces.ts +0 -629
  447. package/src/shared/llm/provider-manager.ts +0 -685
  448. package/src/shared/llm/providers/claude.ts +0 -524
  449. package/src/shared/llm/providers/index.ts +0 -8
  450. package/src/shared/llm/providers/ollama.ts +0 -575
  451. package/src/shared/llm/providers/openai.ts +0 -609
  452. package/src/shared/metrics/code-metrics.ts +0 -520
  453. package/src/shared/metrics/index.ts +0 -23
  454. package/src/shared/metrics/system-metrics.ts +0 -353
  455. package/src/shared/parsers/index.ts +0 -6
  456. package/src/shared/parsers/typescript-parser.ts +0 -841
  457. package/src/shared/security/compliance-patterns.ts +0 -666
  458. package/src/shared/security/index.ts +0 -30
  459. package/src/shared/security/osv-client.ts +0 -468
  460. package/src/shared/types/index.ts +0 -150
  461. package/src/shared/value-objects/index.ts +0 -273
  462. package/src/strange-loop/healing-controller.ts +0 -833
  463. package/src/strange-loop/index.ts +0 -104
  464. package/src/strange-loop/self-model.ts +0 -494
  465. package/src/strange-loop/strange-loop.ts +0 -446
  466. package/src/strange-loop/swarm-observer.ts +0 -448
  467. package/src/strange-loop/topology-analyzer.ts +0 -565
  468. package/src/strange-loop/types.ts +0 -640
  469. package/src/time-crystal/default-phases.ts +0 -520
  470. package/src/time-crystal/index.ts +0 -164
  471. package/src/time-crystal/oscillator.ts +0 -425
  472. package/src/time-crystal/phase-executor.ts +0 -521
  473. package/src/time-crystal/scheduler.ts +0 -1025
  474. package/src/time-crystal/test-runner.ts +0 -787
  475. package/src/time-crystal/types.ts +0 -421
  476. package/src/workers/base-worker.ts +0 -304
  477. package/src/workers/daemon.ts +0 -264
  478. package/src/workers/index.ts +0 -119
  479. package/src/workers/interfaces.ts +0 -393
  480. package/src/workers/worker-manager.ts +0 -424
  481. package/src/workers/workers/compliance-checker.ts +0 -445
  482. package/src/workers/workers/coverage-tracker.ts +0 -344
  483. package/src/workers/workers/defect-predictor.ts +0 -375
  484. package/src/workers/workers/flaky-detector.ts +0 -390
  485. package/src/workers/workers/index.ts +0 -17
  486. package/src/workers/workers/learning-consolidation.ts +0 -442
  487. package/src/workers/workers/performance-baseline.ts +0 -434
  488. package/src/workers/workers/quality-gate.ts +0 -419
  489. package/src/workers/workers/regression-monitor.ts +0 -357
  490. package/src/workers/workers/security-scan.ts +0 -349
  491. package/src/workers/workers/test-health.ts +0 -359
  492. package/tests/integration/code-intelligence/knowledge-graph-real.test.ts +0 -540
  493. package/tests/integration/coordination/cross-domain-router.test.ts +0 -403
  494. package/tests/integration/coordination/protocol-executor.test.ts +0 -454
  495. package/tests/integration/coordination/workflow-orchestrator.test.ts +0 -418
  496. package/tests/integration/feedback/feedback-loop-integration.test.ts +0 -560
  497. package/tests/integration/migration/v2-to-v3-migration.test.ts +0 -471
  498. package/tests/integration/parsers/typescript-parser.test.ts +0 -463
  499. package/tests/integration/security/vulnerability-detection.test.ts +0 -628
  500. package/tests/integration/test-execution/coordinator.test.ts +0 -410
  501. package/tests/integration/test-generation/coordinator.test.ts +0 -361
  502. package/tests/mocks/index.ts +0 -228
  503. package/tests/time-crystal/default-phases.test.ts +0 -476
  504. package/tests/time-crystal/oscillator.test.ts +0 -541
  505. package/tests/time-crystal/phase-executor.test.ts +0 -653
  506. package/tests/time-crystal/scheduler.test.ts +0 -626
  507. package/tests/time-crystal/test-runner.test.ts +0 -594
  508. package/tests/unit/causal-discovery/causal-graph.test.ts +0 -504
  509. package/tests/unit/causal-discovery/causal-root-cause-analyzer.test.ts +0 -347
  510. package/tests/unit/causal-discovery/discovery-engine.test.ts +0 -435
  511. package/tests/unit/causal-discovery/weight-matrix.test.ts +0 -328
  512. package/tests/unit/cli/cli.test.ts +0 -341
  513. package/tests/unit/cli/commands.test.ts +0 -414
  514. package/tests/unit/cli/init-command.test.ts +0 -274
  515. package/tests/unit/cli/migrate-command.test.ts +0 -396
  516. package/tests/unit/coordination/claims/claim-service.test.ts +0 -949
  517. package/tests/unit/coordination/claims/handoff-manager.test.ts +0 -773
  518. package/tests/unit/coordination/claims/work-stealing.test.ts +0 -492
  519. package/tests/unit/coordination/queen-coordinator.test.ts +0 -966
  520. package/tests/unit/coordination/result-saver.test.ts +0 -653
  521. package/tests/unit/coordination/task-executor.test.ts +0 -810
  522. package/tests/unit/domains/chaos-resilience/chaos-engineer.test.ts +0 -484
  523. package/tests/unit/domains/chaos-resilience/load-tester.test.ts +0 -559
  524. package/tests/unit/domains/chaos-resilience/performance-profiler.test.ts +0 -490
  525. package/tests/unit/domains/code-intelligence/impact-analyzer.test.ts +0 -560
  526. package/tests/unit/domains/code-intelligence/knowledge-graph.test.ts +0 -460
  527. package/tests/unit/domains/code-intelligence/semantic-analyzer.test.ts +0 -584
  528. package/tests/unit/domains/contract-testing/api-compatibility.test.ts +0 -483
  529. package/tests/unit/domains/contract-testing/contract-validator.test.ts +0 -370
  530. package/tests/unit/domains/contract-testing/schema-validator.test.ts +0 -610
  531. package/tests/unit/domains/coverage-analysis/coverage-embedder.test.ts +0 -298
  532. package/tests/unit/domains/coverage-analysis/hnsw-index.test.ts +0 -292
  533. package/tests/unit/domains/coverage-analysis/sublinear-analyzer.test.ts +0 -506
  534. package/tests/unit/domains/defect-intelligence/defect-predictor.test.ts +0 -370
  535. package/tests/unit/domains/defect-intelligence/pattern-learner.test.ts +0 -546
  536. package/tests/unit/domains/defect-intelligence/root-cause-analyzer.test.ts +0 -534
  537. package/tests/unit/domains/learning-optimization/learning-coordinator.test.ts +0 -541
  538. package/tests/unit/domains/learning-optimization/metrics-optimizer.test.ts +0 -552
  539. package/tests/unit/domains/learning-optimization/production-intel.test.ts +0 -589
  540. package/tests/unit/domains/learning-optimization/transfer-specialist.test.ts +0 -453
  541. package/tests/unit/domains/quality-assessment/coherence-gate.test.ts +0 -1006
  542. package/tests/unit/domains/quality-assessment/deployment-advisor.test.ts +0 -515
  543. package/tests/unit/domains/quality-assessment/quality-analyzer.test.ts +0 -401
  544. package/tests/unit/domains/quality-assessment/quality-gate.test.ts +0 -324
  545. package/tests/unit/domains/requirements-validation/bdd-scenario-writer.test.ts +0 -479
  546. package/tests/unit/domains/requirements-validation/requirements-validator.test.ts +0 -452
  547. package/tests/unit/domains/requirements-validation/testability-scorer.test.ts +0 -505
  548. package/tests/unit/domains/security-compliance/compliance-validator.test.ts +0 -500
  549. package/tests/unit/domains/security-compliance/security-auditor.test.ts +0 -498
  550. package/tests/unit/domains/security-compliance/security-scanner.test.ts +0 -412
  551. package/tests/unit/domains/visual-accessibility/accessibility-tester.test.ts +0 -432
  552. package/tests/unit/domains/visual-accessibility/responsive-tester.test.ts +0 -506
  553. package/tests/unit/domains/visual-accessibility/visual-tester.test.ts +0 -412
  554. package/tests/unit/early-exit/early-exit-controller.test.ts +0 -548
  555. package/tests/unit/early-exit/early-exit-decision.test.ts +0 -617
  556. package/tests/unit/early-exit/index.test.ts +0 -254
  557. package/tests/unit/early-exit/quality-signal.test.ts +0 -589
  558. package/tests/unit/early-exit/speculative-executor.test.ts +0 -453
  559. package/tests/unit/feedback/coverage-learner.test.ts +0 -288
  560. package/tests/unit/feedback/feedback-loop.test.ts +0 -458
  561. package/tests/unit/feedback/pattern-promotion.test.ts +0 -390
  562. package/tests/unit/feedback/quality-score-calculator.test.ts +0 -364
  563. package/tests/unit/feedback/test-outcome-tracker.test.ts +0 -243
  564. package/tests/unit/init/init-wizard.test.ts +0 -881
  565. package/tests/unit/init/project-analyzer.test.ts +0 -807
  566. package/tests/unit/init/self-configurator.test.ts +0 -493
  567. package/tests/unit/integrations/ruvector/ast-complexity.test.ts +0 -240
  568. package/tests/unit/integrations/ruvector/coverage-router.test.ts +0 -366
  569. package/tests/unit/integrations/ruvector/diff-risk-classifier.test.ts +0 -340
  570. package/tests/unit/integrations/ruvector/graph-boundaries.test.ts +0 -355
  571. package/tests/unit/integrations/ruvector/q-learning-router.test.ts +0 -314
  572. package/tests/unit/kernel/agent-coordinator.test.ts +0 -220
  573. package/tests/unit/kernel/event-bus.test.ts +0 -197
  574. package/tests/unit/learning/qe-reasoning-bank.test.ts +0 -666
  575. package/tests/unit/learning/real-qe-reasoning-bank.benchmark.test.ts +0 -415
  576. package/tests/unit/mcp/mcp-server.test.ts +0 -544
  577. package/tests/unit/mcp/metrics/metrics-collector.test.ts +0 -340
  578. package/tests/unit/mcp/security/cve-prevention.test.ts +0 -512
  579. package/tests/unit/mcp/security/oauth21-provider.test.ts +0 -624
  580. package/tests/unit/mcp/security/rate-limiter.test.ts +0 -410
  581. package/tests/unit/mcp/security/sampling-server.test.ts +0 -420
  582. package/tests/unit/mcp/security/schema-validator.test.ts +0 -494
  583. package/tests/unit/mcp/tools/base.test.ts +0 -336
  584. package/tests/unit/mcp/tools/domain-tools.test.ts +0 -759
  585. package/tests/unit/mcp/tools/registry.test.ts +0 -240
  586. package/tests/unit/neural-optimizer/replay-buffer.test.ts +0 -403
  587. package/tests/unit/neural-optimizer/swarm-topology.test.ts +0 -473
  588. package/tests/unit/neural-optimizer/topology-optimizer.test.ts +0 -595
  589. package/tests/unit/neural-optimizer/value-network.test.ts +0 -343
  590. package/tests/unit/optimization/auto-tuner.test.ts +0 -506
  591. package/tests/unit/optimization/metric-collectors.test.ts +0 -352
  592. package/tests/unit/optimization/qe-workers.test.ts +0 -407
  593. package/tests/unit/optimization/tuning-algorithm.test.ts +0 -467
  594. package/tests/unit/routing/qe-agent-registry.test.ts +0 -229
  595. package/tests/unit/routing/qe-task-router.test.ts +0 -390
  596. package/tests/unit/routing/routing-feedback.test.ts +0 -339
  597. package/tests/unit/shared/embeddings/nomic-embedder.test.ts +0 -419
  598. package/tests/unit/shared/http/http-client.test.ts +0 -719
  599. package/tests/unit/shared/io/file-reader.test.ts +0 -511
  600. package/tests/unit/shared/llm/cache.test.ts +0 -391
  601. package/tests/unit/shared/llm/circuit-breaker.test.ts +0 -293
  602. package/tests/unit/shared/llm/cost-tracker.test.ts +0 -431
  603. package/tests/unit/shared/llm/provider-manager.test.ts +0 -550
  604. package/tests/unit/shared/llm/providers.test.ts +0 -532
  605. package/tests/unit/shared/parsers/typescript-parser.test.ts +0 -693
  606. package/tests/unit/shared/value-objects.test.ts +0 -184
  607. package/tests/unit/strange-loop/strange-loop.test.ts +0 -1170
  608. package/tests/unit/workers/base-worker.test.ts +0 -341
  609. package/tests/unit/workers/daemon.test.ts +0 -291
  610. package/tests/unit/workers/worker-manager.test.ts +0 -284
  611. package/tsconfig.json +0 -32
  612. package/vitest.config.ts +0 -27
@@ -1,2227 +0,0 @@
1
- /**
2
- * Agentic QE v3 - Security Auditor Service
3
- * Provides comprehensive security audit functionality
4
- */
5
-
6
- import { v4 as uuidv4 } from 'uuid';
7
- import * as fs from 'fs/promises';
8
- import * as path from 'path';
9
- import { Result, ok, err } from '../../../shared/types/index.js';
10
- import type { MemoryBackend } from '../../../kernel/interfaces.js';
11
- import type { FilePath, RiskScore } from '../../../shared/value-objects/index.js';
12
-
13
- // ============================================================================
14
- // Package.json Types
15
- // ============================================================================
16
-
17
- interface PackageJson {
18
- name?: string;
19
- version?: string;
20
- dependencies?: Record<string, string>;
21
- devDependencies?: Record<string, string>;
22
- peerDependencies?: Record<string, string>;
23
- optionalDependencies?: Record<string, string>;
24
- }
25
-
26
- // ============================================================================
27
- // OSV (Open Source Vulnerabilities) API Types
28
- // ============================================================================
29
-
30
- interface OSVQueryRequest {
31
- package: {
32
- name: string;
33
- ecosystem: string;
34
- };
35
- version: string;
36
- }
37
-
38
- interface OSVVulnerability {
39
- id: string;
40
- summary?: string;
41
- details?: string;
42
- aliases?: string[];
43
- severity?: Array<{
44
- type: string;
45
- score: string;
46
- }>;
47
- affected?: Array<{
48
- package?: {
49
- name: string;
50
- ecosystem: string;
51
- };
52
- ranges?: Array<{
53
- type: string;
54
- events?: Array<{
55
- introduced?: string;
56
- fixed?: string;
57
- }>;
58
- }>;
59
- versions?: string[];
60
- }>;
61
- references?: Array<{
62
- type: string;
63
- url: string;
64
- }>;
65
- }
66
-
67
- interface OSVQueryResponse {
68
- vulns?: OSVVulnerability[];
69
- }
70
-
71
- // ============================================================================
72
- // HTTP Client for API calls
73
- // ============================================================================
74
-
75
- interface HttpResponse<T> {
76
- ok: boolean;
77
- status: number;
78
- data: T;
79
- }
80
-
81
- async function httpPost<T, R>(url: string, body: T): Promise<HttpResponse<R>> {
82
- const response = await fetch(url, {
83
- method: 'POST',
84
- headers: {
85
- 'Content-Type': 'application/json',
86
- },
87
- body: JSON.stringify(body),
88
- });
89
-
90
- const data = await response.json() as R;
91
- return {
92
- ok: response.ok,
93
- status: response.status,
94
- data,
95
- };
96
- }
97
-
98
- async function httpGet<R>(url: string): Promise<HttpResponse<R>> {
99
- const response = await fetch(url, {
100
- method: 'GET',
101
- headers: {
102
- 'Accept': 'application/json',
103
- },
104
- });
105
-
106
- const data = await response.json() as R;
107
- return {
108
- ok: response.ok,
109
- status: response.status,
110
- data,
111
- };
112
- }
113
- import type {
114
- IDependencySecurityService,
115
- DependencyScanResult,
116
- PackageSecurityInfo,
117
- UpgradeRecommendation,
118
- Vulnerability,
119
- VulnerabilitySeverity,
120
- VulnerabilityCategory,
121
- VulnerabilityLocation,
122
- DependencyInfo,
123
- OutdatedPackage,
124
- RemediationAdvice,
125
- ScanSummary,
126
- DetectedSecret,
127
- SecretScanResult,
128
- SecurityAuditOptions,
129
- SecurityAuditReport,
130
- SASTResult,
131
- DASTResult,
132
- } from '../interfaces.js';
133
-
134
- // ============================================================================
135
- // Service Interface
136
- // ============================================================================
137
-
138
- export interface ISecurityAuditorService extends IDependencySecurityService {
139
- /**
140
- * Run comprehensive security audit
141
- */
142
- runAudit(options: SecurityAuditOptions): Promise<Result<SecurityAuditReport>>;
143
-
144
- /**
145
- * Scan for secrets/credentials in code
146
- */
147
- scanSecrets(files: FilePath[]): Promise<Result<SecretScanResult>>;
148
-
149
- /**
150
- * Get security posture summary
151
- */
152
- getSecurityPosture(): Promise<Result<SecurityPostureSummary>>;
153
-
154
- /**
155
- * Triage vulnerabilities by priority
156
- */
157
- triageVulnerabilities(
158
- vulnerabilities: Vulnerability[]
159
- ): Promise<Result<TriagedVulnerabilities>>;
160
- }
161
-
162
- export interface SecurityPostureSummary {
163
- overallScore: number;
164
- trend: 'improving' | 'stable' | 'declining';
165
- criticalIssues: number;
166
- highIssues: number;
167
- openVulnerabilities: number;
168
- resolvedLastWeek: number;
169
- averageResolutionTime: number;
170
- lastAuditDate: Date;
171
- recommendations: string[];
172
- }
173
-
174
- export interface TriagedVulnerabilities {
175
- immediate: Vulnerability[];
176
- shortTerm: Vulnerability[];
177
- mediumTerm: Vulnerability[];
178
- longTerm: Vulnerability[];
179
- accepted: Vulnerability[];
180
- }
181
-
182
- // ============================================================================
183
- // Configuration
184
- // ============================================================================
185
-
186
- export interface SecurityAuditorConfig {
187
- secretPatterns: RegExp[];
188
- excludePatterns: string[];
189
- maxFileSizeKb: number;
190
- enableHistoricalAnalysis: boolean;
191
- riskThreshold: number;
192
- }
193
-
194
- const DEFAULT_CONFIG: SecurityAuditorConfig = {
195
- secretPatterns: [
196
- /(?:api[_-]?key|apikey)['":\s]*['"=]?\s*['"]?([a-zA-Z0-9_\-]{20,})['"]?/gi,
197
- /(?:password|passwd|pwd)['":\s]*['"=]?\s*['"]?([^\s'"]{8,})['"]?/gi,
198
- /(?:secret|token)['":\s]*['"=]?\s*['"]?([a-zA-Z0-9_\-]{16,})['"]?/gi,
199
- /(?:aws[_-]?access[_-]?key|aws[_-]?secret)['":\s]*['"=]?\s*['"]?([A-Z0-9]{20,})['"]?/gi,
200
- /-----BEGIN\s+(?:RSA\s+)?PRIVATE\s+KEY-----/gi,
201
- /ghp_[a-zA-Z0-9]{36}/g, // GitHub personal access token
202
- /gho_[a-zA-Z0-9]{36}/g, // GitHub OAuth access token
203
- /sk-[a-zA-Z0-9]{48}/g, // OpenAI API key
204
- ],
205
- excludePatterns: ['node_modules', 'dist', 'build', '.git', '*.test.*', '*.spec.*'],
206
- maxFileSizeKb: 1024,
207
- enableHistoricalAnalysis: true,
208
- riskThreshold: 0.7,
209
- };
210
-
211
- // ============================================================================
212
- // Security Auditor Service Implementation
213
- // ============================================================================
214
-
215
- export class SecurityAuditorService implements ISecurityAuditorService {
216
- private readonly config: SecurityAuditorConfig;
217
-
218
- constructor(
219
- private readonly memory: MemoryBackend,
220
- config: Partial<SecurityAuditorConfig> = {}
221
- ) {
222
- this.config = { ...DEFAULT_CONFIG, ...config };
223
- }
224
-
225
- // ==========================================================================
226
- // IDependencySecurityService Implementation
227
- // ==========================================================================
228
-
229
- /**
230
- * Scan dependencies for vulnerabilities
231
- */
232
- async scanDependencies(manifestPath: FilePath): Promise<Result<DependencyScanResult>> {
233
- try {
234
- const manifest = manifestPath.value;
235
- const ecosystem = this.detectEcosystem(manifest);
236
-
237
- if (!ecosystem) {
238
- return err(new Error(`Unknown manifest format: ${manifest}`));
239
- }
240
-
241
- const vulnerabilities: Vulnerability[] = [];
242
- const outdatedPackages: OutdatedPackage[] = [];
243
-
244
- // Parse dependencies from manifest file
245
- const dependencies = await this.parseDependencies(manifest, ecosystem);
246
-
247
- for (const dep of dependencies) {
248
- // Check for known vulnerabilities
249
- const vulns = await this.checkDependencyVulnerabilities(dep, ecosystem);
250
- vulnerabilities.push(...vulns);
251
-
252
- // Check for outdated packages
253
- const outdated = await this.checkOutdated(dep);
254
- if (outdated) {
255
- outdatedPackages.push(outdated);
256
- }
257
- }
258
-
259
- const summary = this.createDependencySummary(vulnerabilities, dependencies.length);
260
-
261
- // Store results
262
- await this.memory.set(
263
- `security:deps:${manifestPath.filename}`,
264
- { vulnerabilities, outdatedPackages, summary },
265
- { namespace: 'security-compliance', ttl: 86400 } // 24 hours
266
- );
267
-
268
- return ok({
269
- vulnerabilities,
270
- outdatedPackages,
271
- summary,
272
- });
273
- } catch (error) {
274
- return err(error instanceof Error ? error : new Error(String(error)));
275
- }
276
- }
277
-
278
- /**
279
- * Check specific package for security issues
280
- */
281
- async checkPackage(
282
- name: string,
283
- version: string,
284
- ecosystem: DependencyInfo['ecosystem']
285
- ): Promise<Result<PackageSecurityInfo>> {
286
- try {
287
- // Query OSV vulnerability database
288
- const vulnerabilities = await this.queryVulnerabilityDatabase(
289
- name,
290
- version,
291
- ecosystem
292
- );
293
-
294
- const latestVersion = await this.getLatestVersion(name, ecosystem);
295
- const isDeprecated = await this.checkDeprecation(name, ecosystem);
296
-
297
- return ok({
298
- name,
299
- version,
300
- vulnerabilities,
301
- latestVersion,
302
- isDeprecated,
303
- });
304
- } catch (error) {
305
- return err(error instanceof Error ? error : new Error(String(error)));
306
- }
307
- }
308
-
309
- /**
310
- * Get upgrade recommendations for vulnerabilities
311
- */
312
- async getUpgradeRecommendations(
313
- vulnerabilities: Vulnerability[]
314
- ): Promise<Result<UpgradeRecommendation[]>> {
315
- try {
316
- const recommendations: UpgradeRecommendation[] = [];
317
-
318
- // Group vulnerabilities by package
319
- const byPackage = new Map<string, Vulnerability[]>();
320
- for (const vuln of vulnerabilities) {
321
- const dep = vuln.location.dependency;
322
- if (dep) {
323
- const key = `${dep.ecosystem}:${dep.name}`;
324
- const existing = byPackage.get(key) || [];
325
- existing.push(vuln);
326
- byPackage.set(key, existing);
327
- }
328
- }
329
-
330
- // Generate recommendations for each package
331
- for (const [key, vulns] of byPackage) {
332
- const [ecosystem, name] = key.split(':');
333
- const currentVersion = vulns[0].location.dependency?.version || 'unknown';
334
-
335
- const latestVersion = await this.getLatestVersion(
336
- name,
337
- ecosystem as DependencyInfo['ecosystem']
338
- );
339
-
340
- const fixedVersions = vulns
341
- .filter((v) => v.id)
342
- .map((v) => v.id);
343
-
344
- recommendations.push({
345
- package: name,
346
- fromVersion: currentVersion,
347
- toVersion: latestVersion,
348
- fixesVulnerabilities: fixedVersions,
349
- breakingChanges: this.hasBreakingChanges(currentVersion, latestVersion),
350
- });
351
- }
352
-
353
- // Sort by number of vulnerabilities fixed
354
- recommendations.sort(
355
- (a, b) => b.fixesVulnerabilities.length - a.fixesVulnerabilities.length
356
- );
357
-
358
- return ok(recommendations);
359
- } catch (error) {
360
- return err(error instanceof Error ? error : new Error(String(error)));
361
- }
362
- }
363
-
364
- // ==========================================================================
365
- // Audit Functionality
366
- // ==========================================================================
367
-
368
- /**
369
- * Run comprehensive security audit
370
- */
371
- async runAudit(options: SecurityAuditOptions): Promise<Result<SecurityAuditReport>> {
372
- const auditId = uuidv4();
373
- const timestamp = new Date();
374
-
375
- try {
376
- let sastResults: SASTResult | undefined;
377
- let dastResults: DASTResult | undefined;
378
- let dependencyResults: DependencyScanResult | undefined;
379
- let secretScanResults: SecretScanResult | undefined;
380
-
381
- // Note: Actual SAST/DAST scanning would be delegated to SecurityScannerService
382
- // This is orchestration-level code that combines results
383
-
384
- if (options.includeSAST) {
385
- // SAST scanning delegated to SecurityScannerService
386
- sastResults = await this.performSASTScan();
387
- }
388
-
389
- if (options.includeDAST && options.targetUrl) {
390
- // DAST scanning delegated to SecurityScannerService
391
- dastResults = await this.performDASTScan(options.targetUrl);
392
- }
393
-
394
- if (options.includeDependencies) {
395
- // Scan package manifests for vulnerabilities
396
- dependencyResults = await this.performDependencyScan();
397
- }
398
-
399
- if (options.includeSecrets) {
400
- // Scan source files for secrets
401
- secretScanResults = await this.performSecretScan();
402
- }
403
-
404
- // Calculate overall risk score
405
- const overallRiskScore = this.calculateOverallRisk(
406
- sastResults,
407
- dastResults,
408
- dependencyResults,
409
- secretScanResults
410
- );
411
-
412
- // Generate recommendations
413
- const recommendations = this.generateRecommendations(
414
- sastResults,
415
- dastResults,
416
- dependencyResults,
417
- secretScanResults
418
- );
419
-
420
- const report: SecurityAuditReport = {
421
- auditId,
422
- timestamp,
423
- sastResults,
424
- dastResults,
425
- dependencyResults,
426
- secretScanResults,
427
- overallRiskScore,
428
- recommendations,
429
- };
430
-
431
- // Store audit report
432
- await this.memory.set(
433
- `security:audit:${auditId}`,
434
- report,
435
- { namespace: 'security-compliance', persist: true }
436
- );
437
-
438
- return ok(report);
439
- } catch (error) {
440
- return err(error instanceof Error ? error : new Error(String(error)));
441
- }
442
- }
443
-
444
- /**
445
- * Scan for secrets in code
446
- */
447
- async scanSecrets(files: FilePath[]): Promise<Result<SecretScanResult>> {
448
- try {
449
- const secretsFound: DetectedSecret[] = [];
450
- let filesScanned = 0;
451
-
452
- for (const file of files) {
453
- // Skip excluded patterns
454
- if (this.shouldExclude(file.value)) {
455
- continue;
456
- }
457
-
458
- filesScanned++;
459
-
460
- // Read and scan file for secrets using regex patterns
461
- const secrets = await this.scanFileForSecrets(file);
462
- secretsFound.push(...secrets);
463
- }
464
-
465
- return ok({
466
- secretsFound,
467
- filesScanned,
468
- });
469
- } catch (error) {
470
- return err(error instanceof Error ? error : new Error(String(error)));
471
- }
472
- }
473
-
474
- /**
475
- * Get security posture summary
476
- */
477
- async getSecurityPosture(): Promise<Result<SecurityPostureSummary>> {
478
- try {
479
- // Get historical audit data
480
- const audits = await this.getRecentAudits();
481
-
482
- // Calculate metrics
483
- const latestAudit = audits[0];
484
- const previousAudit = audits[1];
485
-
486
- const criticalIssues = this.countBySeverity(latestAudit, 'critical');
487
- const highIssues = this.countBySeverity(latestAudit, 'high');
488
- const openVulnerabilities = this.countOpenVulnerabilities(latestAudit);
489
-
490
- // Calculate trend
491
- const trend = this.calculateTrend(latestAudit, previousAudit);
492
-
493
- // Calculate overall score (0-100)
494
- const overallScore = this.calculatePostureScore(
495
- criticalIssues,
496
- highIssues,
497
- openVulnerabilities
498
- );
499
-
500
- // Generate recommendations
501
- const recommendations = this.generatePostureRecommendations(
502
- criticalIssues,
503
- highIssues,
504
- overallScore
505
- );
506
-
507
- return ok({
508
- overallScore,
509
- trend,
510
- criticalIssues,
511
- highIssues,
512
- openVulnerabilities,
513
- resolvedLastWeek: await this.countResolvedLastWeek(),
514
- averageResolutionTime: await this.calculateAverageResolutionTime(),
515
- lastAuditDate: latestAudit?.timestamp ?? new Date(),
516
- recommendations,
517
- });
518
- } catch (error) {
519
- return err(error instanceof Error ? error : new Error(String(error)));
520
- }
521
- }
522
-
523
- /**
524
- * Triage vulnerabilities by priority
525
- */
526
- async triageVulnerabilities(
527
- vulnerabilities: Vulnerability[]
528
- ): Promise<Result<TriagedVulnerabilities>> {
529
- try {
530
- const triaged: TriagedVulnerabilities = {
531
- immediate: [],
532
- shortTerm: [],
533
- mediumTerm: [],
534
- longTerm: [],
535
- accepted: [],
536
- };
537
-
538
- for (const vuln of vulnerabilities) {
539
- const bucket = this.determinePriorityBucket(vuln);
540
- triaged[bucket].push(vuln);
541
- }
542
-
543
- // Sort each bucket by severity
544
- const severityOrder = ['critical', 'high', 'medium', 'low', 'informational'];
545
- for (const bucket of Object.values(triaged)) {
546
- bucket.sort(
547
- (a: Vulnerability, b: Vulnerability) =>
548
- severityOrder.indexOf(a.severity) - severityOrder.indexOf(b.severity)
549
- );
550
- }
551
-
552
- return ok(triaged);
553
- } catch (error) {
554
- return err(error instanceof Error ? error : new Error(String(error)));
555
- }
556
- }
557
-
558
- // ==========================================================================
559
- // Private Helper Methods
560
- // ==========================================================================
561
-
562
- private detectEcosystem(manifest: string): DependencyInfo['ecosystem'] | null {
563
- if (manifest.includes('package.json')) return 'npm';
564
- if (manifest.includes('requirements.txt') || manifest.includes('Pipfile')) return 'pip';
565
- if (manifest.includes('pom.xml') || manifest.includes('build.gradle')) return 'maven';
566
- if (manifest.includes('Cargo.toml')) return 'cargo';
567
- if (manifest.includes('.csproj') || manifest.includes('packages.config')) return 'nuget';
568
- return null;
569
- }
570
-
571
- private async parseDependencies(
572
- manifest: string,
573
- ecosystem: DependencyInfo['ecosystem']
574
- ): Promise<DependencyInfo[]> {
575
- const dependencies: DependencyInfo[] = [];
576
-
577
- try {
578
- if (ecosystem === 'npm') {
579
- // Read and parse package.json
580
- const content = await fs.readFile(manifest, 'utf-8');
581
- const packageJson: PackageJson = JSON.parse(content);
582
-
583
- // Collect all dependency types
584
- const allDeps: Record<string, string> = {
585
- ...packageJson.dependencies,
586
- ...packageJson.devDependencies,
587
- ...packageJson.peerDependencies,
588
- ...packageJson.optionalDependencies,
589
- };
590
-
591
- // Convert to DependencyInfo array
592
- for (const [name, versionSpec] of Object.entries(allDeps)) {
593
- // Clean version specifiers (^, ~, >=, etc.)
594
- const version = this.cleanVersionSpec(versionSpec);
595
- dependencies.push({ name, version, ecosystem: 'npm' });
596
- }
597
- } else if (ecosystem === 'pip') {
598
- // Parse requirements.txt or Pipfile
599
- const content = await fs.readFile(manifest, 'utf-8');
600
- const lines = content.split('\n');
601
-
602
- for (const line of lines) {
603
- const trimmed = line.trim();
604
- // Skip comments and empty lines
605
- if (!trimmed || trimmed.startsWith('#')) continue;
606
-
607
- // Parse package==version or package>=version patterns
608
- const match = trimmed.match(/^([a-zA-Z0-9_-]+)(?:[=<>~!]+(.+))?$/);
609
- if (match) {
610
- dependencies.push({
611
- name: match[1],
612
- version: match[2] || 'latest',
613
- ecosystem: 'pip',
614
- });
615
- }
616
- }
617
- }
618
- // Additional ecosystems (maven, cargo, nuget) would be implemented similarly
619
- } catch (error) {
620
- // If file reading fails, return empty array rather than throwing
621
- console.error(`Failed to parse dependencies from ${manifest}:`, error);
622
- }
623
-
624
- return dependencies;
625
- }
626
-
627
- /**
628
- * Clean version specifier to extract actual version
629
- */
630
- private cleanVersionSpec(versionSpec: string): string {
631
- // Remove leading specifiers like ^, ~, >=, <=, >, <, =
632
- return versionSpec.replace(/^[\^~>=<]+/, '').trim();
633
- }
634
-
635
- private async checkDependencyVulnerabilities(
636
- dep: DependencyInfo,
637
- ecosystem: DependencyInfo['ecosystem']
638
- ): Promise<Vulnerability[]> {
639
- const vulnerabilities: Vulnerability[] = [];
640
-
641
- try {
642
- // Map ecosystem to OSV ecosystem name
643
- const osvEcosystem = this.mapToOSVEcosystem(ecosystem);
644
-
645
- // Query OSV API for vulnerabilities
646
- const osvQuery: OSVQueryRequest = {
647
- package: {
648
- name: dep.name,
649
- ecosystem: osvEcosystem,
650
- },
651
- version: dep.version,
652
- };
653
-
654
- const response = await httpPost<OSVQueryRequest, OSVQueryResponse>(
655
- 'https://api.osv.dev/v1/query',
656
- osvQuery
657
- );
658
-
659
- if (response.ok && response.data.vulns && response.data.vulns.length > 0) {
660
- for (const osvVuln of response.data.vulns) {
661
- const vulnerability = this.mapOSVVulnerability(osvVuln, dep);
662
- vulnerabilities.push(vulnerability);
663
- }
664
- }
665
- } catch (error) {
666
- // Log error but don't fail the entire scan
667
- console.error(`Failed to check vulnerabilities for ${dep.name}@${dep.version}:`, error);
668
- }
669
-
670
- return vulnerabilities;
671
- }
672
-
673
- /**
674
- * Map internal ecosystem to OSV ecosystem name
675
- */
676
- private mapToOSVEcosystem(ecosystem: DependencyInfo['ecosystem']): string {
677
- const ecosystemMap: Record<DependencyInfo['ecosystem'], string> = {
678
- npm: 'npm',
679
- pip: 'PyPI',
680
- maven: 'Maven',
681
- nuget: 'NuGet',
682
- cargo: 'crates.io',
683
- };
684
- return ecosystemMap[ecosystem];
685
- }
686
-
687
- /**
688
- * Map OSV vulnerability to our Vulnerability type
689
- */
690
- private mapOSVVulnerability(osvVuln: OSVVulnerability, dep: DependencyInfo): Vulnerability {
691
- // Extract CVE ID from aliases
692
- const cveId = osvVuln.aliases?.find((alias) => alias.startsWith('CVE-'));
693
-
694
- // Determine severity from OSV severity scores
695
- const severity = this.mapOSVSeverity(osvVuln.severity);
696
-
697
- // Extract fixed version from affected ranges
698
- const fixedVersion = this.extractFixedVersion(osvVuln);
699
-
700
- // Build references list
701
- const references = osvVuln.references?.map((ref) => ref.url) || [];
702
-
703
- const location: VulnerabilityLocation = {
704
- file: 'package.json',
705
- dependency: dep,
706
- };
707
-
708
- const remediation: RemediationAdvice = {
709
- description: fixedVersion
710
- ? `Upgrade ${dep.name} to version ${fixedVersion} or higher`
711
- : `Review and address vulnerability in ${dep.name}`,
712
- fixExample: fixedVersion ? `"${dep.name}": "^${fixedVersion}"` : undefined,
713
- estimatedEffort: fixedVersion ? 'trivial' : 'moderate',
714
- automatable: !!fixedVersion,
715
- };
716
-
717
- return {
718
- id: uuidv4(),
719
- cveId,
720
- title: osvVuln.summary || `Vulnerability in ${dep.name}`,
721
- description: osvVuln.details || osvVuln.summary || 'No description available',
722
- severity,
723
- category: this.categorizeVulnerability(osvVuln),
724
- location,
725
- remediation,
726
- references,
727
- };
728
- }
729
-
730
- /**
731
- * Map OSV severity to our severity levels
732
- */
733
- private mapOSVSeverity(
734
- severityScores?: OSVVulnerability['severity']
735
- ): VulnerabilitySeverity {
736
- if (!severityScores || severityScores.length === 0) {
737
- return 'medium'; // Default to medium if no severity info
738
- }
739
-
740
- // Find CVSS score
741
- const cvssScore = severityScores.find(
742
- (s) => s.type === 'CVSS_V3' || s.type === 'CVSS_V2'
743
- );
744
-
745
- if (cvssScore) {
746
- const score = parseFloat(cvssScore.score);
747
- if (score >= 9.0) return 'critical';
748
- if (score >= 7.0) return 'high';
749
- if (score >= 4.0) return 'medium';
750
- if (score > 0) return 'low';
751
- }
752
-
753
- return 'medium';
754
- }
755
-
756
- /**
757
- * Extract fixed version from OSV vulnerability data
758
- */
759
- private extractFixedVersion(osvVuln: OSVVulnerability): string | undefined {
760
- if (!osvVuln.affected) return undefined;
761
-
762
- for (const affected of osvVuln.affected) {
763
- if (affected.ranges) {
764
- for (const range of affected.ranges) {
765
- if (range.events) {
766
- const fixedEvent = range.events.find((event) => event.fixed);
767
- if (fixedEvent?.fixed) {
768
- return fixedEvent.fixed;
769
- }
770
- }
771
- }
772
- }
773
- }
774
-
775
- return undefined;
776
- }
777
-
778
- /**
779
- * Categorize vulnerability based on OSV data
780
- */
781
- private categorizeVulnerability(osvVuln: OSVVulnerability): VulnerabilityCategory {
782
- const summary = (osvVuln.summary || '').toLowerCase();
783
- const details = (osvVuln.details || '').toLowerCase();
784
- const combined = `${summary} ${details}`;
785
-
786
- // Check for common vulnerability patterns
787
- if (combined.includes('injection') || combined.includes('sql')) {
788
- return 'injection';
789
- }
790
- if (combined.includes('xss') || combined.includes('cross-site scripting')) {
791
- return 'xss';
792
- }
793
- if (combined.includes('authentication') || combined.includes('auth bypass')) {
794
- return 'broken-auth';
795
- }
796
- if (combined.includes('sensitive data') || combined.includes('exposure')) {
797
- return 'sensitive-data';
798
- }
799
- if (combined.includes('xxe') || combined.includes('xml external')) {
800
- return 'xxe';
801
- }
802
- if (combined.includes('access control') || combined.includes('authorization')) {
803
- return 'access-control';
804
- }
805
- if (combined.includes('deseriali')) {
806
- return 'insecure-deserialization';
807
- }
808
- if (combined.includes('prototype pollution') || combined.includes('dependency')) {
809
- return 'vulnerable-components';
810
- }
811
-
812
- // Default to vulnerable-components for dependency vulnerabilities
813
- return 'vulnerable-components';
814
- }
815
-
816
- private async checkOutdated(dep: DependencyInfo): Promise<OutdatedPackage | null> {
817
- // Check if package is outdated by comparing with latest version from registry
818
- const latestVersion = await this.getLatestVersion(dep.name, dep.ecosystem);
819
-
820
- if (latestVersion !== dep.version) {
821
- return {
822
- name: dep.name,
823
- currentVersion: dep.version,
824
- latestVersion,
825
- updateType: this.determineUpdateType(dep.version, latestVersion),
826
- };
827
- }
828
-
829
- return null;
830
- }
831
-
832
- private async queryVulnerabilityDatabase(
833
- name: string,
834
- version: string,
835
- ecosystem: DependencyInfo['ecosystem']
836
- ): Promise<Vulnerability[]> {
837
- // Query OSV API for vulnerabilities
838
- const dep: DependencyInfo = { name, version, ecosystem };
839
- return this.checkDependencyVulnerabilities(dep, ecosystem);
840
- }
841
-
842
- private async getLatestVersion(
843
- name: string,
844
- ecosystem: DependencyInfo['ecosystem']
845
- ): Promise<string> {
846
- try {
847
- if (ecosystem === 'npm') {
848
- // Query npm registry for latest version
849
- const response = await httpGet<{ 'dist-tags'?: { latest?: string }; version?: string }>(
850
- `https://registry.npmjs.org/${encodeURIComponent(name)}/latest`
851
- );
852
-
853
- if (response.ok && response.data.version) {
854
- return response.data.version;
855
- }
856
- } else if (ecosystem === 'pip') {
857
- // Query PyPI for latest version
858
- const response = await httpGet<{ info?: { version?: string } }>(
859
- `https://pypi.org/pypi/${encodeURIComponent(name)}/json`
860
- );
861
-
862
- if (response.ok && response.data.info?.version) {
863
- return response.data.info.version;
864
- }
865
- }
866
- // Additional registries (Maven, NuGet, Cargo) would be implemented similarly
867
- } catch (error) {
868
- console.error(`Failed to get latest version for ${name}:`, error);
869
- }
870
-
871
- return 'unknown';
872
- }
873
-
874
- private async checkDeprecation(
875
- name: string,
876
- ecosystem: DependencyInfo['ecosystem']
877
- ): Promise<boolean> {
878
- try {
879
- if (ecosystem === 'npm') {
880
- // Query npm registry for deprecation notice
881
- const response = await httpGet<{ deprecated?: string }>(
882
- `https://registry.npmjs.org/${encodeURIComponent(name)}/latest`
883
- );
884
-
885
- if (response.ok && response.data.deprecated) {
886
- return true;
887
- }
888
- }
889
- // Additional registries would be implemented similarly
890
- } catch (error) {
891
- console.error(`Failed to check deprecation for ${name}:`, error);
892
- }
893
-
894
- return false;
895
- }
896
-
897
- private determineUpdateType(
898
- current: string,
899
- latest: string
900
- ): 'major' | 'minor' | 'patch' {
901
- const currentParts = current.split('.').map(Number);
902
- const latestParts = latest.split('.').map(Number);
903
-
904
- if (latestParts[0] > currentParts[0]) return 'major';
905
- if (latestParts[1] > currentParts[1]) return 'minor';
906
- return 'patch';
907
- }
908
-
909
- private hasBreakingChanges(current: string, latest: string): boolean {
910
- const currentMajor = parseInt(current.split('.')[0]);
911
- const latestMajor = parseInt(latest.split('.')[0]);
912
- return latestMajor > currentMajor;
913
- }
914
-
915
- private createDependencySummary(
916
- vulnerabilities: Vulnerability[],
917
- totalDeps: number
918
- ): ScanSummary {
919
- // Count vulnerabilities by severity
920
- let critical = 0;
921
- let high = 0;
922
- let medium = 0;
923
- let low = 0;
924
- let informational = 0;
925
-
926
- for (const vuln of vulnerabilities) {
927
- switch (vuln.severity) {
928
- case 'critical':
929
- critical++;
930
- break;
931
- case 'high':
932
- high++;
933
- break;
934
- case 'medium':
935
- medium++;
936
- break;
937
- case 'low':
938
- low++;
939
- break;
940
- case 'informational':
941
- informational++;
942
- break;
943
- }
944
- }
945
-
946
- return {
947
- critical,
948
- high,
949
- medium,
950
- low,
951
- informational,
952
- totalFiles: totalDeps,
953
- scanDurationMs: 0,
954
- };
955
- }
956
-
957
- private shouldExclude(filePath: string): boolean {
958
- return this.config.excludePatterns.some((pattern) => {
959
- if (pattern.startsWith('*')) {
960
- return filePath.endsWith(pattern.slice(1));
961
- }
962
- return filePath.includes(pattern);
963
- });
964
- }
965
-
966
- private async scanFileForSecrets(file: FilePath): Promise<DetectedSecret[]> {
967
- const secrets: DetectedSecret[] = [];
968
-
969
- try {
970
- // Read the file content
971
- const content = await fs.readFile(file.value, 'utf-8');
972
- const lines = content.split('\n');
973
-
974
- // Comprehensive secret detection patterns
975
- const secretPatterns: Array<{
976
- name: string;
977
- type: DetectedSecret['type'];
978
- regex: RegExp;
979
- entropyThreshold?: number;
980
- }> = [
981
- // AWS Keys
982
- {
983
- name: 'AWS Access Key ID',
984
- type: 'api-key',
985
- regex: /AKIA[0-9A-Z]{16}/g,
986
- },
987
- {
988
- name: 'AWS Secret Access Key',
989
- type: 'api-key',
990
- regex: /(?:aws[_-]?secret[_-]?access[_-]?key|AWS_SECRET_ACCESS_KEY)['"]?\s*[:=]\s*['"]?([A-Za-z0-9/+=]{40})['"]?/gi,
991
- entropyThreshold: 4.0,
992
- },
993
- // GitHub Tokens
994
- {
995
- name: 'GitHub Personal Access Token',
996
- type: 'token',
997
- regex: /ghp_[A-Za-z0-9]{36}/g,
998
- },
999
- {
1000
- name: 'GitHub OAuth Access Token',
1001
- type: 'token',
1002
- regex: /gho_[A-Za-z0-9]{36}/g,
1003
- },
1004
- {
1005
- name: 'GitHub App Token',
1006
- type: 'token',
1007
- regex: /(?:ghu|ghs)_[A-Za-z0-9]{36}/g,
1008
- },
1009
- // Generic API Keys
1010
- {
1011
- name: 'Generic API Key',
1012
- type: 'api-key',
1013
- regex: /(?:api[_-]?key|apikey|api_secret)['"]?\s*[:=]\s*['"]([A-Za-z0-9_\-]{20,})['"]?/gi,
1014
- entropyThreshold: 3.5,
1015
- },
1016
- // OpenAI API Key
1017
- {
1018
- name: 'OpenAI API Key',
1019
- type: 'api-key',
1020
- regex: /sk-[A-Za-z0-9]{48}/g,
1021
- },
1022
- // Stripe Keys
1023
- {
1024
- name: 'Stripe Secret Key',
1025
- type: 'api-key',
1026
- regex: /sk_live_[A-Za-z0-9]{24,}/g,
1027
- },
1028
- {
1029
- name: 'Stripe Publishable Key',
1030
- type: 'api-key',
1031
- regex: /pk_live_[A-Za-z0-9]{24,}/g,
1032
- },
1033
- // Private Keys
1034
- {
1035
- name: 'RSA Private Key',
1036
- type: 'private-key',
1037
- regex: /-----BEGIN\s+(?:RSA\s+)?PRIVATE\s+KEY-----/gi,
1038
- },
1039
- {
1040
- name: 'PGP Private Key',
1041
- type: 'private-key',
1042
- regex: /-----BEGIN\s+PGP\s+PRIVATE\s+KEY\s+BLOCK-----/gi,
1043
- },
1044
- {
1045
- name: 'SSH Private Key',
1046
- type: 'private-key',
1047
- regex: /-----BEGIN\s+(?:OPENSSH|DSA|EC)?\s*PRIVATE\s+KEY-----/gi,
1048
- },
1049
- // Passwords
1050
- {
1051
- name: 'Password Assignment',
1052
- type: 'password',
1053
- regex: /(?:password|passwd|pwd|secret)['"]?\s*[:=]\s*['"]([^'"\s]{8,})['"]?/gi,
1054
- entropyThreshold: 3.0,
1055
- },
1056
- // Database Connection Strings
1057
- {
1058
- name: 'Database Connection String',
1059
- type: 'password',
1060
- regex: /(?:mongodb|postgres|mysql|redis):\/\/[^:]+:[^@]+@[^\s'"]+/gi,
1061
- },
1062
- // JWT Tokens
1063
- {
1064
- name: 'JWT Token',
1065
- type: 'token',
1066
- regex: /eyJ[A-Za-z0-9_-]*\.eyJ[A-Za-z0-9_-]*\.[A-Za-z0-9_-]*/g,
1067
- entropyThreshold: 4.0,
1068
- },
1069
- // Slack Tokens
1070
- {
1071
- name: 'Slack Token',
1072
- type: 'token',
1073
- regex: /xox[baprs]-[A-Za-z0-9-]{10,}/g,
1074
- },
1075
- // Google API Key
1076
- {
1077
- name: 'Google API Key',
1078
- type: 'api-key',
1079
- regex: /AIza[A-Za-z0-9_-]{35}/g,
1080
- },
1081
- // Twilio
1082
- {
1083
- name: 'Twilio API Key',
1084
- type: 'api-key',
1085
- regex: /SK[A-Za-z0-9]{32}/g,
1086
- },
1087
- // SendGrid
1088
- {
1089
- name: 'SendGrid API Key',
1090
- type: 'api-key',
1091
- regex: /SG\.[A-Za-z0-9_-]{22}\.[A-Za-z0-9_-]{43}/g,
1092
- },
1093
- // Certificates
1094
- {
1095
- name: 'X.509 Certificate',
1096
- type: 'certificate',
1097
- regex: /-----BEGIN\s+CERTIFICATE-----/gi,
1098
- },
1099
- ];
1100
-
1101
- // Scan each line for secrets
1102
- for (let lineIndex = 0; lineIndex < lines.length; lineIndex++) {
1103
- const line = lines[lineIndex];
1104
- const lineNumber = lineIndex + 1;
1105
-
1106
- for (const pattern of secretPatterns) {
1107
- // Reset regex lastIndex for global patterns
1108
- pattern.regex.lastIndex = 0;
1109
-
1110
- let match: RegExpExecArray | null;
1111
- while ((match = pattern.regex.exec(line)) !== null) {
1112
- const matchedValue = match[1] || match[0];
1113
-
1114
- // Calculate entropy if threshold is specified
1115
- const entropy = this.calculateEntropy(matchedValue);
1116
-
1117
- // Skip low-entropy matches if threshold is specified
1118
- if (pattern.entropyThreshold && entropy < pattern.entropyThreshold) {
1119
- continue;
1120
- }
1121
-
1122
- // Create masked snippet (show context but mask the actual secret)
1123
- const snippet = this.createMaskedSnippet(line, match.index, matchedValue.length);
1124
-
1125
- const location: VulnerabilityLocation = {
1126
- file: file.value,
1127
- line: lineNumber,
1128
- column: match.index + 1,
1129
- snippet,
1130
- };
1131
-
1132
- secrets.push({
1133
- type: pattern.type,
1134
- location,
1135
- entropy,
1136
- isValid: this.validateSecret(pattern.type, matchedValue),
1137
- });
1138
- }
1139
- }
1140
- }
1141
- } catch (error) {
1142
- // File reading error - skip this file
1143
- console.error(`Failed to scan file for secrets: ${file.value}`, error);
1144
- }
1145
-
1146
- return secrets;
1147
- }
1148
-
1149
- /**
1150
- * Calculate Shannon entropy of a string
1151
- */
1152
- private calculateEntropy(str: string): number {
1153
- if (!str || str.length === 0) return 0;
1154
-
1155
- const charFrequency: Record<string, number> = {};
1156
-
1157
- for (const char of str) {
1158
- charFrequency[char] = (charFrequency[char] || 0) + 1;
1159
- }
1160
-
1161
- let entropy = 0;
1162
- const len = str.length;
1163
-
1164
- for (const char in charFrequency) {
1165
- const probability = charFrequency[char] / len;
1166
- entropy -= probability * Math.log2(probability);
1167
- }
1168
-
1169
- return entropy;
1170
- }
1171
-
1172
- /**
1173
- * Create a masked snippet for display
1174
- */
1175
- private createMaskedSnippet(line: string, matchIndex: number, matchLength: number): string {
1176
- const contextBefore = 20;
1177
- const contextAfter = 10;
1178
-
1179
- const start = Math.max(0, matchIndex - contextBefore);
1180
- const end = Math.min(line.length, matchIndex + matchLength + contextAfter);
1181
-
1182
- let snippet = line.substring(start, end);
1183
-
1184
- // Mask the secret value (show first 4 and last 4 characters)
1185
- const secretStart = matchIndex - start;
1186
- const secretInSnippet = snippet.substring(secretStart, secretStart + matchLength);
1187
-
1188
- if (secretInSnippet.length > 8) {
1189
- const masked = secretInSnippet.substring(0, 4) + '...' + secretInSnippet.substring(secretInSnippet.length - 4);
1190
- snippet = snippet.substring(0, secretStart) + masked + snippet.substring(secretStart + matchLength);
1191
- }
1192
-
1193
- if (start > 0) snippet = '...' + snippet;
1194
- if (end < line.length) snippet = snippet + '...';
1195
-
1196
- return snippet;
1197
- }
1198
-
1199
- /**
1200
- * Validate if a detected secret is likely valid (basic validation)
1201
- */
1202
- private validateSecret(type: DetectedSecret['type'], value: string): boolean {
1203
- // Basic validation - in production, could do more sophisticated checks
1204
- switch (type) {
1205
- case 'api-key':
1206
- // Check minimum length and character variety
1207
- return value.length >= 20 && /[a-z]/.test(value) && /[A-Z0-9]/.test(value);
1208
- case 'token':
1209
- return value.length >= 20;
1210
- case 'password':
1211
- // Likely not a placeholder password
1212
- return !['password', 'secret', 'changeme', '12345678', 'qwerty'].includes(value.toLowerCase());
1213
- case 'private-key':
1214
- return true; // Private key headers are already specific
1215
- case 'certificate':
1216
- return true;
1217
- default:
1218
- return true;
1219
- }
1220
- }
1221
-
1222
- /**
1223
- * Perform SAST scan using AST-based analysis for JavaScript/TypeScript
1224
- * Scans for common vulnerability patterns: XSS, SQL injection, command injection, path traversal
1225
- */
1226
- private async performSASTScan(): Promise<SASTResult> {
1227
- const scanId = uuidv4();
1228
- const startTime = Date.now();
1229
- const vulnerabilities: Vulnerability[] = [];
1230
- let filesScanned = 0;
1231
- let linesScanned = 0;
1232
-
1233
- try {
1234
- // Find source files to scan
1235
- const sourceFiles = await this.findSourceFiles(process.cwd());
1236
-
1237
- // Define vulnerability patterns for AST-like analysis
1238
- const vulnerabilityPatterns: Array<{
1239
- id: string;
1240
- pattern: RegExp;
1241
- title: string;
1242
- description: string;
1243
- severity: VulnerabilitySeverity;
1244
- category: VulnerabilityCategory;
1245
- remediation: string;
1246
- fixExample?: string;
1247
- cweId: string;
1248
- }> = [
1249
- // SQL Injection patterns
1250
- {
1251
- id: 'sqli-concat',
1252
- pattern: /(?:query|execute|exec|run)\s*\(\s*(?:['"`].*?\s*\+|`[^`]*\$\{)/gi,
1253
- title: 'SQL Injection via String Concatenation',
1254
- description: 'SQL query constructed using string concatenation with potentially untrusted input',
1255
- severity: 'critical',
1256
- category: 'injection',
1257
- remediation: 'Use parameterized queries or prepared statements',
1258
- fixExample: 'db.query("SELECT * FROM users WHERE id = $1", [userId])',
1259
- cweId: 'CWE-89',
1260
- },
1261
- // XSS patterns
1262
- {
1263
- id: 'xss-innerhtml',
1264
- pattern: /\.innerHTML\s*=\s*(?!['"`])/g,
1265
- title: 'XSS via innerHTML Assignment',
1266
- description: 'Direct innerHTML assignment with potentially unsanitized content',
1267
- severity: 'high',
1268
- category: 'xss',
1269
- remediation: 'Use textContent for text, or sanitize HTML with DOMPurify',
1270
- fixExample: 'element.textContent = userInput;',
1271
- cweId: 'CWE-79',
1272
- },
1273
- {
1274
- id: 'xss-document-write',
1275
- pattern: /document\.write\s*\([^)]+\)/g,
1276
- title: 'XSS via document.write',
1277
- description: 'document.write() can execute scripts from untrusted data',
1278
- severity: 'high',
1279
- category: 'xss',
1280
- remediation: 'Avoid document.write(); use DOM manipulation methods',
1281
- cweId: 'CWE-79',
1282
- },
1283
- {
1284
- id: 'xss-eval',
1285
- pattern: /(?<!\.)\beval\s*\([^)]+\)/g,
1286
- title: 'Code Injection via eval()',
1287
- description: 'eval() executes arbitrary code and is a major security risk',
1288
- severity: 'critical',
1289
- category: 'xss',
1290
- remediation: 'Never use eval(); use JSON.parse() for JSON data',
1291
- fixExample: 'JSON.parse(jsonString)',
1292
- cweId: 'CWE-95',
1293
- },
1294
- {
1295
- id: 'xss-dangerous-react',
1296
- pattern: /dangerouslySetInnerHTML\s*=\s*\{/g,
1297
- title: 'React dangerouslySetInnerHTML Usage',
1298
- description: 'dangerouslySetInnerHTML bypasses React XSS protections',
1299
- severity: 'medium',
1300
- category: 'xss',
1301
- remediation: 'Sanitize HTML content with DOMPurify before use',
1302
- fixExample: 'dangerouslySetInnerHTML={{ __html: DOMPurify.sanitize(content) }}',
1303
- cweId: 'CWE-79',
1304
- },
1305
- // Command Injection patterns
1306
- {
1307
- id: 'cmd-injection-exec',
1308
- pattern: /(?:child_process\.)?exec\s*\(\s*(?:[^,)]*\s*\+|`[^`]*\$\{)/g,
1309
- title: 'Command Injection via exec()',
1310
- description: 'Shell command execution with unsanitized input',
1311
- severity: 'critical',
1312
- category: 'injection',
1313
- remediation: 'Use execFile() with argument array instead of exec()',
1314
- fixExample: 'execFile("command", [arg1, arg2], callback)',
1315
- cweId: 'CWE-78',
1316
- },
1317
- {
1318
- id: 'cmd-injection-spawn-shell',
1319
- pattern: /spawn\s*\([^)]+,\s*\{[^}]*shell\s*:\s*true/g,
1320
- title: 'Dangerous Shell Option in spawn()',
1321
- description: 'spawn() with shell: true can enable command injection',
1322
- severity: 'high',
1323
- category: 'injection',
1324
- remediation: 'Avoid shell: true option; use direct command execution',
1325
- cweId: 'CWE-78',
1326
- },
1327
- // Path Traversal patterns
1328
- {
1329
- id: 'path-traversal-readfile',
1330
- pattern: /(?:readFile|readFileSync)\s*\([^)]*\+/g,
1331
- title: 'Path Traversal via File Read',
1332
- description: 'File read operation with concatenated path may allow directory traversal',
1333
- severity: 'high',
1334
- category: 'access-control',
1335
- remediation: 'Validate and sanitize file paths; use path.resolve() and check against base directory',
1336
- fixExample: 'const safePath = path.resolve(baseDir, path.basename(userInput))',
1337
- cweId: 'CWE-22',
1338
- },
1339
- {
1340
- id: 'path-traversal-writefile',
1341
- pattern: /(?:writeFile|writeFileSync)\s*\([^)]*\+/g,
1342
- title: 'Path Traversal via File Write',
1343
- description: 'File write operation with concatenated path may allow directory traversal',
1344
- severity: 'high',
1345
- category: 'access-control',
1346
- remediation: 'Validate file paths before writing; ensure path is within allowed directory',
1347
- cweId: 'CWE-22',
1348
- },
1349
- // Hardcoded secrets
1350
- {
1351
- id: 'secret-private-key',
1352
- pattern: /-----BEGIN\s+(?:RSA\s+)?PRIVATE\s+KEY-----/g,
1353
- title: 'Private Key Detected in Source',
1354
- description: 'Private key found in source code',
1355
- severity: 'critical',
1356
- category: 'sensitive-data',
1357
- remediation: 'Store private keys in secure key management systems, not in code',
1358
- cweId: 'CWE-798',
1359
- },
1360
- // Insecure configurations
1361
- {
1362
- id: 'config-tls-disabled',
1363
- pattern: /rejectUnauthorized\s*:\s*false/g,
1364
- title: 'TLS Certificate Validation Disabled',
1365
- description: 'Disabling TLS certificate validation exposes to MITM attacks',
1366
- severity: 'high',
1367
- category: 'security-misconfiguration',
1368
- remediation: 'Always enable TLS certificate validation in production',
1369
- cweId: 'CWE-295',
1370
- },
1371
- {
1372
- id: 'config-cors-wildcard',
1373
- pattern: /cors\s*\(\s*\{[^}]*origin\s*:\s*['"]\*['"]/gi,
1374
- title: 'Permissive CORS Configuration',
1375
- description: 'CORS allows all origins (*) which may expose sensitive data',
1376
- severity: 'medium',
1377
- category: 'security-misconfiguration',
1378
- remediation: 'Restrict CORS to specific trusted origins',
1379
- fixExample: 'cors({ origin: ["https://trusted-domain.com"] })',
1380
- cweId: 'CWE-942',
1381
- },
1382
- ];
1383
-
1384
- for (const filePath of sourceFiles) {
1385
- if (this.shouldExclude(filePath)) {
1386
- continue;
1387
- }
1388
-
1389
- // Only scan JS/TS files
1390
- const ext = path.extname(filePath).toLowerCase();
1391
- if (!['.ts', '.tsx', '.js', '.jsx', '.mjs', '.cjs'].includes(ext)) {
1392
- continue;
1393
- }
1394
-
1395
- try {
1396
- const content = await fs.readFile(filePath, 'utf-8');
1397
- const lines = content.split('\n');
1398
- filesScanned++;
1399
- linesScanned += lines.length;
1400
-
1401
- // Check each vulnerability pattern
1402
- for (const vulnPattern of vulnerabilityPatterns) {
1403
- // Reset regex state
1404
- vulnPattern.pattern.lastIndex = 0;
1405
- let match: RegExpExecArray | null;
1406
-
1407
- while ((match = vulnPattern.pattern.exec(content)) !== null) {
1408
- // Calculate line and column
1409
- const beforeMatch = content.substring(0, match.index);
1410
- const linesBefore = beforeMatch.split('\n');
1411
- const lineNumber = linesBefore.length;
1412
- const column = linesBefore[linesBefore.length - 1].length + 1;
1413
-
1414
- // Check if in comment
1415
- const currentLine = lines[lineNumber - 1] || '';
1416
- if (currentLine.trimStart().startsWith('//') || currentLine.trimStart().startsWith('*')) {
1417
- continue;
1418
- }
1419
-
1420
- // Check for nosec annotation
1421
- if (currentLine.includes('// nosec') || currentLine.includes('// security-ignore')) {
1422
- continue;
1423
- }
1424
-
1425
- // Extract snippet with context
1426
- const startLine = Math.max(0, lineNumber - 2);
1427
- const endLine = Math.min(lines.length, lineNumber + 1);
1428
- const snippet = lines.slice(startLine, endLine).join('\n');
1429
-
1430
- const location: VulnerabilityLocation = {
1431
- file: filePath,
1432
- line: lineNumber,
1433
- column,
1434
- snippet,
1435
- };
1436
-
1437
- const remediation: RemediationAdvice = {
1438
- description: vulnPattern.remediation,
1439
- fixExample: vulnPattern.fixExample,
1440
- estimatedEffort: vulnPattern.severity === 'critical' ? 'moderate' : 'minor',
1441
- automatable: vulnPattern.severity === 'low' || vulnPattern.severity === 'medium',
1442
- };
1443
-
1444
- vulnerabilities.push({
1445
- id: uuidv4(),
1446
- cveId: undefined,
1447
- title: vulnPattern.title,
1448
- description: `${vulnPattern.description} [${vulnPattern.cweId}]`,
1449
- severity: vulnPattern.severity,
1450
- category: vulnPattern.category,
1451
- location,
1452
- remediation,
1453
- references: [
1454
- `https://cwe.mitre.org/data/definitions/${vulnPattern.cweId.replace('CWE-', '')}.html`,
1455
- ],
1456
- });
1457
- }
1458
- }
1459
- } catch {
1460
- // Skip files that can't be read
1461
- }
1462
- }
1463
- } catch (error) {
1464
- console.error('SAST scan failed:', error);
1465
- }
1466
-
1467
- const scanDurationMs = Date.now() - startTime;
1468
-
1469
- // Calculate summary
1470
- let critical = 0, high = 0, medium = 0, low = 0, informational = 0;
1471
- for (const vuln of vulnerabilities) {
1472
- switch (vuln.severity) {
1473
- case 'critical': critical++; break;
1474
- case 'high': high++; break;
1475
- case 'medium': medium++; break;
1476
- case 'low': low++; break;
1477
- case 'informational': informational++; break;
1478
- }
1479
- }
1480
-
1481
- return {
1482
- scanId,
1483
- vulnerabilities,
1484
- summary: {
1485
- critical,
1486
- high,
1487
- medium,
1488
- low,
1489
- informational,
1490
- totalFiles: filesScanned,
1491
- scanDurationMs,
1492
- },
1493
- coverage: {
1494
- filesScanned,
1495
- linesScanned,
1496
- rulesApplied: 12, // Number of vulnerability patterns
1497
- },
1498
- };
1499
- }
1500
-
1501
- /**
1502
- * Perform DAST scan using HTTP requests to test for vulnerabilities
1503
- * Tests for common web vulnerabilities: XSS, SQL injection, security headers, etc.
1504
- */
1505
- private async performDASTScan(targetUrl: string): Promise<DASTResult> {
1506
- const scanId = uuidv4();
1507
- const startTime = Date.now();
1508
- const vulnerabilities: Vulnerability[] = [];
1509
- let crawledUrls = 0;
1510
-
1511
- try {
1512
- // Validate URL
1513
- let parsedUrl: URL;
1514
- try {
1515
- parsedUrl = new URL(targetUrl);
1516
- } catch {
1517
- return {
1518
- scanId,
1519
- targetUrl,
1520
- vulnerabilities: [{
1521
- id: uuidv4(),
1522
- title: 'Invalid Target URL',
1523
- description: 'The provided target URL is not valid',
1524
- severity: 'informational',
1525
- category: 'security-misconfiguration',
1526
- location: { file: targetUrl },
1527
- remediation: { description: 'Provide a valid URL', estimatedEffort: 'trivial', automatable: false },
1528
- references: [],
1529
- }],
1530
- summary: { critical: 0, high: 0, medium: 0, low: 0, informational: 1, totalFiles: 0, scanDurationMs: Date.now() - startTime },
1531
- crawledUrls: 0,
1532
- };
1533
- }
1534
-
1535
- // Perform HTTP request to check security headers and response characteristics
1536
- const controller = new AbortController();
1537
- const timeoutId = setTimeout(() => controller.abort(), 30000); // 30s timeout
1538
-
1539
- try {
1540
- const response = await fetch(targetUrl, {
1541
- method: 'GET',
1542
- headers: {
1543
- 'User-Agent': 'AgenticQE-SecurityScanner/3.0',
1544
- 'Accept': 'text/html,application/json,*/*',
1545
- },
1546
- signal: controller.signal,
1547
- redirect: 'follow',
1548
- });
1549
-
1550
- clearTimeout(timeoutId);
1551
- crawledUrls = 1;
1552
-
1553
- // Check security headers
1554
- const headers = response.headers;
1555
-
1556
- // Check for missing security headers
1557
- const securityHeaderChecks: Array<{
1558
- header: string;
1559
- title: string;
1560
- description: string;
1561
- severity: VulnerabilitySeverity;
1562
- remediation: string;
1563
- }> = [
1564
- {
1565
- header: 'strict-transport-security',
1566
- title: 'Missing HTTP Strict Transport Security (HSTS)',
1567
- description: 'HSTS header is missing, allowing downgrade attacks',
1568
- severity: 'medium',
1569
- remediation: 'Add Strict-Transport-Security header with appropriate max-age',
1570
- },
1571
- {
1572
- header: 'x-content-type-options',
1573
- title: 'Missing X-Content-Type-Options Header',
1574
- description: 'X-Content-Type-Options header is missing, allowing MIME sniffing attacks',
1575
- severity: 'low',
1576
- remediation: 'Add X-Content-Type-Options: nosniff header',
1577
- },
1578
- {
1579
- header: 'x-frame-options',
1580
- title: 'Missing X-Frame-Options Header',
1581
- description: 'X-Frame-Options header is missing, allowing clickjacking attacks',
1582
- severity: 'medium',
1583
- remediation: 'Add X-Frame-Options: DENY or SAMEORIGIN header',
1584
- },
1585
- {
1586
- header: 'content-security-policy',
1587
- title: 'Missing Content Security Policy',
1588
- description: 'CSP header is missing, increasing XSS attack surface',
1589
- severity: 'medium',
1590
- remediation: 'Implement a Content-Security-Policy header',
1591
- },
1592
- {
1593
- header: 'x-xss-protection',
1594
- title: 'Missing X-XSS-Protection Header',
1595
- description: 'X-XSS-Protection header is missing (legacy XSS filter)',
1596
- severity: 'low',
1597
- remediation: 'Add X-XSS-Protection: 1; mode=block header',
1598
- },
1599
- ];
1600
-
1601
- for (const check of securityHeaderChecks) {
1602
- if (!headers.get(check.header)) {
1603
- vulnerabilities.push({
1604
- id: uuidv4(),
1605
- title: check.title,
1606
- description: check.description,
1607
- severity: check.severity,
1608
- category: 'security-misconfiguration',
1609
- location: {
1610
- file: targetUrl,
1611
- snippet: `Response Headers: ${check.header} not present`,
1612
- },
1613
- remediation: {
1614
- description: check.remediation,
1615
- estimatedEffort: 'minor',
1616
- automatable: true,
1617
- },
1618
- references: [
1619
- 'https://owasp.org/www-project-secure-headers/',
1620
- ],
1621
- });
1622
- }
1623
- }
1624
-
1625
- // Check for insecure cookies
1626
- const cookies = headers.get('set-cookie');
1627
- if (cookies) {
1628
- if (!cookies.toLowerCase().includes('secure')) {
1629
- vulnerabilities.push({
1630
- id: uuidv4(),
1631
- title: 'Cookie Without Secure Flag',
1632
- description: 'Session cookie is set without the Secure flag',
1633
- severity: 'medium',
1634
- category: 'sensitive-data',
1635
- location: { file: targetUrl, snippet: `Set-Cookie: ${cookies.substring(0, 50)}...` },
1636
- remediation: { description: 'Add Secure flag to cookies', estimatedEffort: 'trivial', automatable: true },
1637
- references: ['https://owasp.org/www-community/controls/SecureCookieAttribute'],
1638
- });
1639
- }
1640
- if (!cookies.toLowerCase().includes('httponly')) {
1641
- vulnerabilities.push({
1642
- id: uuidv4(),
1643
- title: 'Cookie Without HttpOnly Flag',
1644
- description: 'Session cookie is set without the HttpOnly flag, making it accessible to JavaScript',
1645
- severity: 'medium',
1646
- category: 'sensitive-data',
1647
- location: { file: targetUrl, snippet: `Set-Cookie: ${cookies.substring(0, 50)}...` },
1648
- remediation: { description: 'Add HttpOnly flag to session cookies', estimatedEffort: 'trivial', automatable: true },
1649
- references: ['https://owasp.org/www-community/HttpOnly'],
1650
- });
1651
- }
1652
- if (!cookies.toLowerCase().includes('samesite')) {
1653
- vulnerabilities.push({
1654
- id: uuidv4(),
1655
- title: 'Cookie Without SameSite Attribute',
1656
- description: 'Cookie is set without the SameSite attribute, potentially vulnerable to CSRF',
1657
- severity: 'low',
1658
- category: 'broken-auth',
1659
- location: { file: targetUrl, snippet: `Set-Cookie: ${cookies.substring(0, 50)}...` },
1660
- remediation: { description: 'Add SameSite=Strict or SameSite=Lax to cookies', estimatedEffort: 'trivial', automatable: true },
1661
- references: ['https://owasp.org/www-community/SameSite'],
1662
- });
1663
- }
1664
- }
1665
-
1666
- // Check for server information disclosure
1667
- const server = headers.get('server');
1668
- if (server && /[0-9]+\.[0-9]+/.test(server)) {
1669
- vulnerabilities.push({
1670
- id: uuidv4(),
1671
- title: 'Server Version Disclosure',
1672
- description: `Server header reveals version information: ${server}`,
1673
- severity: 'low',
1674
- category: 'security-misconfiguration',
1675
- location: { file: targetUrl, snippet: `Server: ${server}` },
1676
- remediation: { description: 'Remove or obfuscate server version information', estimatedEffort: 'trivial', automatable: true },
1677
- references: ['https://owasp.org/www-project-web-security-testing-guide/'],
1678
- });
1679
- }
1680
-
1681
- // Check for HTTPS
1682
- if (parsedUrl.protocol === 'http:') {
1683
- vulnerabilities.push({
1684
- id: uuidv4(),
1685
- title: 'Insecure HTTP Protocol',
1686
- description: 'Target is using HTTP instead of HTTPS, exposing data in transit',
1687
- severity: 'high',
1688
- category: 'sensitive-data',
1689
- location: { file: targetUrl },
1690
- remediation: { description: 'Use HTTPS with valid TLS certificate', estimatedEffort: 'moderate', automatable: false },
1691
- references: ['https://owasp.org/www-project-web-security-testing-guide/'],
1692
- });
1693
- }
1694
-
1695
- // Try common test endpoints for additional checks
1696
- const testEndpoints = [
1697
- { path: '/.git/config', vuln: 'Git Repository Exposed', severity: 'high' as VulnerabilitySeverity },
1698
- { path: '/.env', vuln: 'Environment File Exposed', severity: 'critical' as VulnerabilitySeverity },
1699
- { path: '/phpinfo.php', vuln: 'PHP Info Exposed', severity: 'medium' as VulnerabilitySeverity },
1700
- { path: '/wp-config.php.bak', vuln: 'WordPress Config Backup Exposed', severity: 'critical' as VulnerabilitySeverity },
1701
- ];
1702
-
1703
- for (const endpoint of testEndpoints) {
1704
- try {
1705
- const testUrl = new URL(endpoint.path, parsedUrl.origin).toString();
1706
- const testResponse = await fetch(testUrl, {
1707
- method: 'GET',
1708
- signal: AbortSignal.timeout(5000),
1709
- });
1710
-
1711
- if (testResponse.ok && testResponse.status === 200) {
1712
- const text = await testResponse.text();
1713
- // Verify it's actually the sensitive content, not a custom 404
1714
- if (text.length > 10 && !text.toLowerCase().includes('not found')) {
1715
- crawledUrls++;
1716
- vulnerabilities.push({
1717
- id: uuidv4(),
1718
- title: endpoint.vuln,
1719
- description: `Sensitive file found at ${endpoint.path}`,
1720
- severity: endpoint.severity,
1721
- category: 'sensitive-data',
1722
- location: { file: testUrl },
1723
- remediation: { description: 'Remove or restrict access to sensitive files', estimatedEffort: 'trivial', automatable: true },
1724
- references: ['https://owasp.org/www-project-web-security-testing-guide/'],
1725
- });
1726
- }
1727
- }
1728
- } catch {
1729
- // Endpoint not accessible, which is expected/good
1730
- }
1731
- }
1732
-
1733
- } catch (fetchError) {
1734
- clearTimeout(timeoutId);
1735
- const errorMessage = fetchError instanceof Error ? fetchError.message : String(fetchError);
1736
-
1737
- // Network errors might indicate issues
1738
- if (errorMessage.includes('certificate') || errorMessage.includes('SSL') || errorMessage.includes('TLS')) {
1739
- vulnerabilities.push({
1740
- id: uuidv4(),
1741
- title: 'TLS/SSL Certificate Issue',
1742
- description: `Certificate error: ${errorMessage}`,
1743
- severity: 'high',
1744
- category: 'security-misconfiguration',
1745
- location: { file: targetUrl },
1746
- remediation: { description: 'Fix TLS certificate configuration', estimatedEffort: 'moderate', automatable: false },
1747
- references: ['https://owasp.org/www-project-web-security-testing-guide/'],
1748
- });
1749
- }
1750
- }
1751
-
1752
- } catch (error) {
1753
- console.error('DAST scan failed:', error);
1754
- }
1755
-
1756
- const scanDurationMs = Date.now() - startTime;
1757
-
1758
- // Calculate summary
1759
- let critical = 0, high = 0, medium = 0, low = 0, informational = 0;
1760
- for (const vuln of vulnerabilities) {
1761
- switch (vuln.severity) {
1762
- case 'critical': critical++; break;
1763
- case 'high': high++; break;
1764
- case 'medium': medium++; break;
1765
- case 'low': low++; break;
1766
- case 'informational': informational++; break;
1767
- }
1768
- }
1769
-
1770
- return {
1771
- scanId,
1772
- targetUrl,
1773
- vulnerabilities,
1774
- summary: {
1775
- critical,
1776
- high,
1777
- medium,
1778
- low,
1779
- informational,
1780
- totalFiles: 1,
1781
- scanDurationMs,
1782
- },
1783
- crawledUrls,
1784
- };
1785
- }
1786
-
1787
- /**
1788
- * Perform dependency scan using OSV API
1789
- */
1790
- private async performDependencyScan(): Promise<DependencyScanResult> {
1791
- const startTime = Date.now();
1792
- const vulnerabilities: Vulnerability[] = [];
1793
- const outdatedPackages: OutdatedPackage[] = [];
1794
-
1795
- try {
1796
- // Look for package.json in current working directory
1797
- const manifestPath = path.join(process.cwd(), 'package.json');
1798
- const dependencies = await this.parseDependencies(manifestPath, 'npm');
1799
-
1800
- for (const dep of dependencies) {
1801
- // Check for vulnerabilities via OSV API
1802
- const vulns = await this.checkDependencyVulnerabilities(dep, dep.ecosystem);
1803
- vulnerabilities.push(...vulns);
1804
-
1805
- // Check for outdated packages
1806
- const outdated = await this.checkOutdated(dep);
1807
- if (outdated) {
1808
- outdatedPackages.push(outdated);
1809
- }
1810
- }
1811
-
1812
- const scanDurationMs = Date.now() - startTime;
1813
- const baseSummary = this.createDependencySummary(vulnerabilities, dependencies.length);
1814
-
1815
- return {
1816
- vulnerabilities,
1817
- outdatedPackages,
1818
- summary: {
1819
- ...baseSummary,
1820
- scanDurationMs,
1821
- },
1822
- };
1823
- } catch (error) {
1824
- console.error('Dependency scan failed:', error);
1825
- return {
1826
- vulnerabilities: [],
1827
- outdatedPackages: [],
1828
- summary: {
1829
- critical: 0,
1830
- high: 0,
1831
- medium: 0,
1832
- low: 0,
1833
- informational: 0,
1834
- totalFiles: 0,
1835
- scanDurationMs: Date.now() - startTime,
1836
- },
1837
- };
1838
- }
1839
- }
1840
-
1841
- /**
1842
- * Perform secret scan on source files
1843
- */
1844
- private async performSecretScan(): Promise<SecretScanResult> {
1845
- const secretsFound: DetectedSecret[] = [];
1846
- let filesScanned = 0;
1847
-
1848
- try {
1849
- // Get list of source files to scan
1850
- const sourceFiles = await this.findSourceFiles(process.cwd());
1851
-
1852
- for (const filePath of sourceFiles) {
1853
- if (this.shouldExclude(filePath)) {
1854
- continue;
1855
- }
1856
-
1857
- filesScanned++;
1858
- const filePathObj = { value: filePath } as FilePath;
1859
- const secrets = await this.scanFileForSecrets(filePathObj);
1860
- secretsFound.push(...secrets);
1861
- }
1862
- } catch (error) {
1863
- console.error('Secret scan failed:', error);
1864
- }
1865
-
1866
- return {
1867
- secretsFound,
1868
- filesScanned,
1869
- };
1870
- }
1871
-
1872
- /**
1873
- * Find source files in a directory (recursively)
1874
- */
1875
- private async findSourceFiles(dir: string, files: string[] = []): Promise<string[]> {
1876
- const sourceExtensions = ['.ts', '.js', '.tsx', '.jsx', '.json', '.env', '.yaml', '.yml', '.config'];
1877
-
1878
- try {
1879
- const entries = await fs.readdir(dir, { withFileTypes: true });
1880
-
1881
- for (const entry of entries) {
1882
- const fullPath = path.join(dir, entry.name);
1883
-
1884
- // Skip excluded directories
1885
- if (this.shouldExclude(fullPath)) {
1886
- continue;
1887
- }
1888
-
1889
- if (entry.isDirectory()) {
1890
- await this.findSourceFiles(fullPath, files);
1891
- } else if (entry.isFile()) {
1892
- const ext = path.extname(entry.name).toLowerCase();
1893
- if (sourceExtensions.includes(ext) || entry.name.startsWith('.env')) {
1894
- files.push(fullPath);
1895
- }
1896
- }
1897
- }
1898
- } catch (error) {
1899
- // Silently skip directories we can't read
1900
- }
1901
-
1902
- return files;
1903
- }
1904
-
1905
- private calculateOverallRisk(
1906
- sast?: SASTResult,
1907
- dast?: DASTResult,
1908
- deps?: DependencyScanResult,
1909
- secrets?: SecretScanResult
1910
- ): RiskScore {
1911
- let riskValue = 0;
1912
- let weights = 0;
1913
-
1914
- if (sast) {
1915
- riskValue +=
1916
- this.calculateScanRisk(sast.summary) * 0.35;
1917
- weights += 0.35;
1918
- }
1919
-
1920
- if (dast) {
1921
- riskValue +=
1922
- this.calculateScanRisk(dast.summary) * 0.25;
1923
- weights += 0.25;
1924
- }
1925
-
1926
- if (deps) {
1927
- riskValue +=
1928
- this.calculateScanRisk(deps.summary) * 0.25;
1929
- weights += 0.25;
1930
- }
1931
-
1932
- if (secrets) {
1933
- const secretRisk = secrets.secretsFound.length > 0 ? 0.9 : 0.1;
1934
- riskValue += secretRisk * 0.15;
1935
- weights += 0.15;
1936
- }
1937
-
1938
- const normalizedRisk = weights > 0 ? riskValue / weights : 0;
1939
-
1940
- // Return RiskScore-compatible object
1941
- return {
1942
- value: Math.min(1, normalizedRisk),
1943
- percentage: normalizedRisk * 100,
1944
- level: normalizedRisk >= 0.8 ? 'critical' :
1945
- normalizedRisk >= 0.6 ? 'high' :
1946
- normalizedRisk >= 0.3 ? 'medium' : 'low',
1947
- } as unknown as RiskScore;
1948
- }
1949
-
1950
- private calculateScanRisk(summary: ScanSummary): number {
1951
- const weights = {
1952
- critical: 1.0,
1953
- high: 0.7,
1954
- medium: 0.4,
1955
- low: 0.1,
1956
- informational: 0.02,
1957
- };
1958
-
1959
- const totalIssues =
1960
- summary.critical +
1961
- summary.high +
1962
- summary.medium +
1963
- summary.low +
1964
- summary.informational;
1965
-
1966
- if (totalIssues === 0) return 0;
1967
-
1968
- const weightedSum =
1969
- summary.critical * weights.critical +
1970
- summary.high * weights.high +
1971
- summary.medium * weights.medium +
1972
- summary.low * weights.low +
1973
- summary.informational * weights.informational;
1974
-
1975
- return Math.min(1, weightedSum / 10);
1976
- }
1977
-
1978
- private generateRecommendations(
1979
- sast?: SASTResult,
1980
- dast?: DASTResult,
1981
- deps?: DependencyScanResult,
1982
- secrets?: SecretScanResult
1983
- ): string[] {
1984
- const recommendations: string[] = [];
1985
-
1986
- if (sast && sast.summary.critical > 0) {
1987
- recommendations.push(
1988
- `Address ${sast.summary.critical} critical vulnerabilities found in static analysis`
1989
- );
1990
- }
1991
-
1992
- if (dast && dast.summary.high > 0) {
1993
- recommendations.push(
1994
- `Fix ${dast.summary.high} high-severity issues found in dynamic testing`
1995
- );
1996
- }
1997
-
1998
- if (deps && deps.outdatedPackages.length > 5) {
1999
- recommendations.push(
2000
- `Update ${deps.outdatedPackages.length} outdated dependencies`
2001
- );
2002
- }
2003
-
2004
- if (secrets && secrets.secretsFound.length > 0) {
2005
- recommendations.push(
2006
- `Remove ${secrets.secretsFound.length} exposed secrets and rotate credentials`
2007
- );
2008
- }
2009
-
2010
- if (recommendations.length === 0) {
2011
- recommendations.push('Security posture is good. Continue regular scanning.');
2012
- }
2013
-
2014
- return recommendations;
2015
- }
2016
-
2017
- private async getRecentAudits(): Promise<SecurityAuditReport[]> {
2018
- // Query recent audits from memory storage
2019
- const keys = await this.memory.search('security:audit:*', 10);
2020
- const audits: SecurityAuditReport[] = [];
2021
-
2022
- for (const key of keys) {
2023
- const audit = await this.memory.get<SecurityAuditReport>(key);
2024
- if (audit) {
2025
- audits.push(audit);
2026
- }
2027
- }
2028
-
2029
- return audits.sort(
2030
- (a, b) => new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime()
2031
- );
2032
- }
2033
-
2034
- private countBySeverity(
2035
- audit: SecurityAuditReport | undefined,
2036
- severity: 'critical' | 'high'
2037
- ): number {
2038
- if (!audit) return 0;
2039
-
2040
- let count = 0;
2041
- if (audit.sastResults) count += audit.sastResults.summary[severity];
2042
- if (audit.dastResults) count += audit.dastResults.summary[severity];
2043
- if (audit.dependencyResults) count += audit.dependencyResults.summary[severity];
2044
-
2045
- return count;
2046
- }
2047
-
2048
- private countOpenVulnerabilities(audit: SecurityAuditReport | undefined): number {
2049
- if (!audit) return 0;
2050
-
2051
- let count = 0;
2052
- if (audit.sastResults) count += audit.sastResults.vulnerabilities.length;
2053
- if (audit.dastResults) count += audit.dastResults.vulnerabilities.length;
2054
- if (audit.dependencyResults) count += audit.dependencyResults.vulnerabilities.length;
2055
-
2056
- return count;
2057
- }
2058
-
2059
- private calculateTrend(
2060
- latest: SecurityAuditReport | undefined,
2061
- previous: SecurityAuditReport | undefined
2062
- ): 'improving' | 'stable' | 'declining' {
2063
- if (!latest || !previous) return 'stable';
2064
-
2065
- const latestScore = this.countOpenVulnerabilities(latest);
2066
- const previousScore = this.countOpenVulnerabilities(previous);
2067
-
2068
- if (latestScore < previousScore * 0.9) return 'improving';
2069
- if (latestScore > previousScore * 1.1) return 'declining';
2070
- return 'stable';
2071
- }
2072
-
2073
- private calculatePostureScore(
2074
- critical: number,
2075
- high: number,
2076
- open: number
2077
- ): number {
2078
- // Start at 100, deduct points for issues
2079
- let score = 100;
2080
- score -= critical * 20;
2081
- score -= high * 10;
2082
- score -= open * 2;
2083
- return Math.max(0, Math.min(100, score));
2084
- }
2085
-
2086
- private generatePostureRecommendations(
2087
- critical: number,
2088
- high: number,
2089
- score: number
2090
- ): string[] {
2091
- const recommendations: string[] = [];
2092
-
2093
- if (critical > 0) {
2094
- recommendations.push('Immediately address all critical vulnerabilities');
2095
- }
2096
-
2097
- if (high > 3) {
2098
- recommendations.push('Prioritize fixing high-severity issues');
2099
- }
2100
-
2101
- if (score < 50) {
2102
- recommendations.push('Consider a comprehensive security review');
2103
- recommendations.push('Implement automated security scanning in CI/CD');
2104
- }
2105
-
2106
- if (score >= 80) {
2107
- recommendations.push('Maintain current security practices');
2108
- recommendations.push('Consider penetration testing for deeper analysis');
2109
- }
2110
-
2111
- return recommendations;
2112
- }
2113
-
2114
- /**
2115
- * Count vulnerabilities resolved in the last week
2116
- * Calculates by comparing consecutive audit reports
2117
- */
2118
- private async countResolvedLastWeek(): Promise<number> {
2119
- try {
2120
- const audits = await this.getRecentAudits();
2121
- if (audits.length < 2) return 0;
2122
-
2123
- const oneWeekAgo = new Date(Date.now() - 7 * 24 * 60 * 60 * 1000);
2124
-
2125
- // Find audits from this week
2126
- const recentAudits = audits.filter(
2127
- (audit) => new Date(audit.timestamp) >= oneWeekAgo
2128
- );
2129
-
2130
- if (recentAudits.length < 2) return 0;
2131
-
2132
- // Compare vulnerability counts between first and last audit of the week
2133
- const oldest = recentAudits[recentAudits.length - 1];
2134
- const newest = recentAudits[0];
2135
-
2136
- const oldCount = this.countOpenVulnerabilities(oldest);
2137
- const newCount = this.countOpenVulnerabilities(newest);
2138
-
2139
- // Resolved = old count - new count (if positive)
2140
- return Math.max(0, oldCount - newCount);
2141
- } catch (error) {
2142
- console.error('Failed to count resolved vulnerabilities:', error);
2143
- return 0;
2144
- }
2145
- }
2146
-
2147
- /**
2148
- * Calculate average resolution time from historical audit data
2149
- */
2150
- private async calculateAverageResolutionTime(): Promise<number> {
2151
- try {
2152
- const audits = await this.getRecentAudits();
2153
- if (audits.length < 2) return 72; // Default to 72 hours
2154
-
2155
- // Track vulnerabilities across audits to calculate resolution time
2156
- const vulnFirstSeen = new Map<string, Date>();
2157
- const resolutionTimes: number[] = [];
2158
-
2159
- // Process audits from oldest to newest
2160
- const sortedAudits = [...audits].reverse();
2161
-
2162
- for (const audit of sortedAudits) {
2163
- const currentVulnIds = new Set<string>();
2164
-
2165
- // Collect all vulnerability IDs in this audit
2166
- if (audit.sastResults) {
2167
- audit.sastResults.vulnerabilities.forEach((v) => currentVulnIds.add(v.id));
2168
- }
2169
- if (audit.dastResults) {
2170
- audit.dastResults.vulnerabilities.forEach((v) => currentVulnIds.add(v.id));
2171
- }
2172
- if (audit.dependencyResults) {
2173
- audit.dependencyResults.vulnerabilities.forEach((v) => currentVulnIds.add(v.id));
2174
- }
2175
-
2176
- // Track new vulnerabilities
2177
- for (const vulnId of currentVulnIds) {
2178
- if (!vulnFirstSeen.has(vulnId)) {
2179
- vulnFirstSeen.set(vulnId, audit.timestamp);
2180
- }
2181
- }
2182
-
2183
- // Check for resolved vulnerabilities
2184
- for (const [vulnId, firstSeen] of vulnFirstSeen) {
2185
- if (!currentVulnIds.has(vulnId)) {
2186
- const resolutionTime = (audit.timestamp.getTime() - firstSeen.getTime()) / (1000 * 60 * 60);
2187
- resolutionTimes.push(resolutionTime);
2188
- vulnFirstSeen.delete(vulnId);
2189
- }
2190
- }
2191
- }
2192
-
2193
- if (resolutionTimes.length === 0) return 72; // Default
2194
-
2195
- // Calculate average
2196
- const sum = resolutionTimes.reduce((acc, time) => acc + time, 0);
2197
- return Math.round(sum / resolutionTimes.length);
2198
- } catch (error) {
2199
- console.error('Failed to calculate average resolution time:', error);
2200
- return 72; // Default to 72 hours
2201
- }
2202
- }
2203
-
2204
- private determinePriorityBucket(
2205
- vuln: Vulnerability
2206
- ): keyof TriagedVulnerabilities {
2207
- const effort = vuln.remediation.estimatedEffort;
2208
-
2209
- if (vuln.severity === 'critical') {
2210
- return 'immediate';
2211
- }
2212
-
2213
- if (vuln.severity === 'high') {
2214
- return effort === 'trivial' || effort === 'minor' ? 'immediate' : 'shortTerm';
2215
- }
2216
-
2217
- if (vuln.severity === 'medium') {
2218
- return effort === 'major' ? 'longTerm' : 'mediumTerm';
2219
- }
2220
-
2221
- if (vuln.severity === 'low' || vuln.severity === 'informational') {
2222
- return 'longTerm';
2223
- }
2224
-
2225
- return 'accepted';
2226
- }
2227
- }