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

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 (609) 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 +8 -8
  149. package/dist/init/agents-installer.js +4 -4
  150. package/dist/init/agents-installer.js.map +1 -1
  151. package/dist/init/skills-installer.js +4 -4
  152. package/dist/init/skills-installer.js.map +1 -1
  153. package/package.json +7 -1
  154. package/docs/analysis/V3-INIT-REQUIREMENTS-ANALYSIS.md +0 -352
  155. package/implementation/README.md +0 -90
  156. package/implementation/adrs/ADR-030-coherence-gated-quality-gates.md +0 -312
  157. package/implementation/adrs/ADR-031-strange-loop-self-awareness.md +0 -484
  158. package/implementation/adrs/ADR-032-time-crystal-scheduling.md +0 -530
  159. package/implementation/adrs/ADR-033-early-exit-testing.md +0 -634
  160. package/implementation/adrs/ADR-034-neural-topology-optimizer.md +0 -589
  161. package/implementation/adrs/ADR-035-causal-discovery.md +0 -610
  162. package/implementation/adrs/ADR-036-result-persistence.md +0 -326
  163. package/implementation/adrs/ADR-037-v3-qe-agent-naming.md +0 -105
  164. package/implementation/adrs/ADR-038-v3-qe-memory-unification.md +0 -154
  165. package/implementation/adrs/ADR-039-v3-qe-mcp-optimization.md +0 -179
  166. package/implementation/adrs/ADR-040-v3-qe-agentic-flow-integration.md +0 -240
  167. package/implementation/adrs/ADR-041-v3-qe-cli-enhancement.md +0 -296
  168. package/implementation/adrs/ADR-042-v3-qe-token-tracking-integration.md +0 -517
  169. package/implementation/adrs/v3-adrs.md +0 -2783
  170. package/implementation/planning/AQE-V3-MASTER-PLAN.md +0 -815
  171. package/security-scan-report-2026-01-11.md +0 -410
  172. package/security-verification-report-2026-01-11.md +0 -278
  173. package/src/benchmarks/performance-benchmarks.ts +0 -646
  174. package/src/benchmarks/run-benchmarks.ts +0 -324
  175. package/src/causal-discovery/causal-graph.ts +0 -450
  176. package/src/causal-discovery/discovery-engine.ts +0 -438
  177. package/src/causal-discovery/index.ts +0 -117
  178. package/src/causal-discovery/types.ts +0 -456
  179. package/src/causal-discovery/weight-matrix.ts +0 -453
  180. package/src/cli/commands/qe-tools.ts +0 -634
  181. package/src/cli/index.ts +0 -1976
  182. package/src/compatibility/agent-mapper.ts +0 -291
  183. package/src/compatibility/cli-adapter.ts +0 -277
  184. package/src/compatibility/config-migrator.ts +0 -334
  185. package/src/compatibility/index.ts +0 -112
  186. package/src/compatibility/mcp-adapter.ts +0 -248
  187. package/src/compatibility/types.ts +0 -156
  188. package/src/coordination/claims/claim-repository.ts +0 -636
  189. package/src/coordination/claims/claim-service.ts +0 -675
  190. package/src/coordination/claims/handoff-manager.ts +0 -535
  191. package/src/coordination/claims/index.ts +0 -276
  192. package/src/coordination/claims/interfaces.ts +0 -687
  193. package/src/coordination/claims/work-stealing.ts +0 -436
  194. package/src/coordination/cross-domain-router.ts +0 -492
  195. package/src/coordination/index.ts +0 -127
  196. package/src/coordination/interfaces.ts +0 -691
  197. package/src/coordination/protocol-executor.ts +0 -760
  198. package/src/coordination/protocols/code-intelligence-index.ts +0 -855
  199. package/src/coordination/protocols/defect-investigation.ts +0 -1184
  200. package/src/coordination/protocols/index.ts +0 -11
  201. package/src/coordination/protocols/learning-consolidation.ts +0 -1181
  202. package/src/coordination/protocols/morning-sync.ts +0 -1055
  203. package/src/coordination/protocols/quality-gate.ts +0 -1566
  204. package/src/coordination/protocols/security-audit.ts +0 -1587
  205. package/src/coordination/queen-coordinator.ts +0 -1176
  206. package/src/coordination/result-saver.ts +0 -780
  207. package/src/coordination/task-executor.ts +0 -1146
  208. package/src/coordination/workflow-orchestrator.ts +0 -1917
  209. package/src/domains/chaos-resilience/coordinator.ts +0 -1032
  210. package/src/domains/chaos-resilience/index.ts +0 -143
  211. package/src/domains/chaos-resilience/interfaces.ts +0 -659
  212. package/src/domains/chaos-resilience/plugin.ts +0 -691
  213. package/src/domains/chaos-resilience/services/chaos-engineer.ts +0 -1097
  214. package/src/domains/chaos-resilience/services/index.ts +0 -19
  215. package/src/domains/chaos-resilience/services/load-tester.ts +0 -799
  216. package/src/domains/chaos-resilience/services/performance-profiler.ts +0 -792
  217. package/src/domains/code-intelligence/coordinator.ts +0 -631
  218. package/src/domains/code-intelligence/index.ts +0 -86
  219. package/src/domains/code-intelligence/interfaces.ts +0 -162
  220. package/src/domains/code-intelligence/plugin.ts +0 -451
  221. package/src/domains/code-intelligence/services/impact-analyzer.ts +0 -567
  222. package/src/domains/code-intelligence/services/index.ts +0 -26
  223. package/src/domains/code-intelligence/services/knowledge-graph.ts +0 -1067
  224. package/src/domains/code-intelligence/services/semantic-analyzer.ts +0 -901
  225. package/src/domains/contract-testing/coordinator.ts +0 -1038
  226. package/src/domains/contract-testing/index.ts +0 -122
  227. package/src/domains/contract-testing/interfaces.ts +0 -458
  228. package/src/domains/contract-testing/plugin.ts +0 -746
  229. package/src/domains/contract-testing/services/api-compatibility.ts +0 -748
  230. package/src/domains/contract-testing/services/contract-validator.ts +0 -1700
  231. package/src/domains/contract-testing/services/index.ts +0 -19
  232. package/src/domains/contract-testing/services/schema-validator.ts +0 -1102
  233. package/src/domains/coverage-analysis/coordinator.ts +0 -485
  234. package/src/domains/coverage-analysis/index.ts +0 -114
  235. package/src/domains/coverage-analysis/interfaces.ts +0 -142
  236. package/src/domains/coverage-analysis/plugin.ts +0 -172
  237. package/src/domains/coverage-analysis/services/coverage-analyzer.ts +0 -449
  238. package/src/domains/coverage-analysis/services/coverage-embedder.ts +0 -733
  239. package/src/domains/coverage-analysis/services/coverage-parser.ts +0 -753
  240. package/src/domains/coverage-analysis/services/gap-detector.ts +0 -592
  241. package/src/domains/coverage-analysis/services/hnsw-index.ts +0 -728
  242. package/src/domains/coverage-analysis/services/index.ts +0 -61
  243. package/src/domains/coverage-analysis/services/risk-scorer.ts +0 -540
  244. package/src/domains/coverage-analysis/services/sublinear-analyzer.ts +0 -747
  245. package/src/domains/defect-intelligence/coordinator.ts +0 -635
  246. package/src/domains/defect-intelligence/index.ts +0 -83
  247. package/src/domains/defect-intelligence/interfaces.ts +0 -152
  248. package/src/domains/defect-intelligence/plugin.ts +0 -483
  249. package/src/domains/defect-intelligence/services/causal-root-cause-analyzer.ts +0 -494
  250. package/src/domains/defect-intelligence/services/defect-predictor.ts +0 -852
  251. package/src/domains/defect-intelligence/services/index.ts +0 -37
  252. package/src/domains/defect-intelligence/services/pattern-learner.ts +0 -738
  253. package/src/domains/defect-intelligence/services/root-cause-analyzer.ts +0 -637
  254. package/src/domains/domain-interface.ts +0 -77
  255. package/src/domains/index.ts +0 -23
  256. package/src/domains/learning-optimization/coordinator.ts +0 -1215
  257. package/src/domains/learning-optimization/index.ts +0 -127
  258. package/src/domains/learning-optimization/interfaces.ts +0 -570
  259. package/src/domains/learning-optimization/plugin.ts +0 -851
  260. package/src/domains/learning-optimization/services/index.ts +0 -29
  261. package/src/domains/learning-optimization/services/learning-coordinator.ts +0 -972
  262. package/src/domains/learning-optimization/services/metrics-optimizer.ts +0 -915
  263. package/src/domains/learning-optimization/services/production-intel.ts +0 -971
  264. package/src/domains/learning-optimization/services/transfer-specialist.ts +0 -723
  265. package/src/domains/quality-assessment/coherence/gate-controller.ts +0 -549
  266. package/src/domains/quality-assessment/coherence/index.ts +0 -211
  267. package/src/domains/quality-assessment/coherence/lambda-calculator.ts +0 -384
  268. package/src/domains/quality-assessment/coherence/partition-detector.ts +0 -469
  269. package/src/domains/quality-assessment/coherence/types.ts +0 -384
  270. package/src/domains/quality-assessment/coordinator.ts +0 -605
  271. package/src/domains/quality-assessment/index.ts +0 -97
  272. package/src/domains/quality-assessment/interfaces.ts +0 -152
  273. package/src/domains/quality-assessment/plugin.ts +0 -496
  274. package/src/domains/quality-assessment/services/coherence-gate.ts +0 -358
  275. package/src/domains/quality-assessment/services/deployment-advisor.ts +0 -571
  276. package/src/domains/quality-assessment/services/index.ts +0 -34
  277. package/src/domains/quality-assessment/services/quality-analyzer.ts +0 -670
  278. package/src/domains/quality-assessment/services/quality-gate.ts +0 -384
  279. package/src/domains/requirements-validation/coordinator.ts +0 -812
  280. package/src/domains/requirements-validation/index.ts +0 -92
  281. package/src/domains/requirements-validation/interfaces.ts +0 -303
  282. package/src/domains/requirements-validation/plugin.ts +0 -576
  283. package/src/domains/requirements-validation/services/bdd-scenario-writer.ts +0 -676
  284. package/src/domains/requirements-validation/services/index.ts +0 -20
  285. package/src/domains/requirements-validation/services/requirements-validator.ts +0 -559
  286. package/src/domains/requirements-validation/services/testability-scorer.ts +0 -639
  287. package/src/domains/security-compliance/coordinator.ts +0 -757
  288. package/src/domains/security-compliance/index.ts +0 -120
  289. package/src/domains/security-compliance/interfaces.ts +0 -434
  290. package/src/domains/security-compliance/plugin.ts +0 -509
  291. package/src/domains/security-compliance/services/compliance-validator.ts +0 -1226
  292. package/src/domains/security-compliance/services/index.ts +0 -31
  293. package/src/domains/security-compliance/services/security-auditor.ts +0 -2227
  294. package/src/domains/security-compliance/services/security-scanner.ts +0 -2354
  295. package/src/domains/security-compliance/services/semgrep-integration.ts +0 -289
  296. package/src/domains/test-execution/coordinator.ts +0 -426
  297. package/src/domains/test-execution/index.ts +0 -76
  298. package/src/domains/test-execution/interfaces.ts +0 -119
  299. package/src/domains/test-execution/plugin.ts +0 -208
  300. package/src/domains/test-execution/services/flaky-detector.ts +0 -1240
  301. package/src/domains/test-execution/services/index.ts +0 -8
  302. package/src/domains/test-execution/services/retry-handler.ts +0 -820
  303. package/src/domains/test-execution/services/test-executor.ts +0 -885
  304. package/src/domains/test-generation/coordinator.ts +0 -656
  305. package/src/domains/test-generation/index.ts +0 -77
  306. package/src/domains/test-generation/interfaces.ts +0 -118
  307. package/src/domains/test-generation/plugin.ts +0 -397
  308. package/src/domains/test-generation/services/index.ts +0 -23
  309. package/src/domains/test-generation/services/pattern-matcher.ts +0 -1725
  310. package/src/domains/test-generation/services/test-generator.ts +0 -2750
  311. package/src/domains/visual-accessibility/coordinator.ts +0 -860
  312. package/src/domains/visual-accessibility/index.ts +0 -116
  313. package/src/domains/visual-accessibility/interfaces.ts +0 -435
  314. package/src/domains/visual-accessibility/plugin.ts +0 -568
  315. package/src/domains/visual-accessibility/services/accessibility-tester.ts +0 -982
  316. package/src/domains/visual-accessibility/services/axe-core-audit.ts +0 -630
  317. package/src/domains/visual-accessibility/services/index.ts +0 -28
  318. package/src/domains/visual-accessibility/services/responsive-tester.ts +0 -934
  319. package/src/domains/visual-accessibility/services/visual-tester.ts +0 -458
  320. package/src/early-exit/early-exit-controller.ts +0 -490
  321. package/src/early-exit/early-exit-decision.ts +0 -391
  322. package/src/early-exit/index.ts +0 -115
  323. package/src/early-exit/quality-signal.ts +0 -389
  324. package/src/early-exit/speculative-executor.ts +0 -505
  325. package/src/early-exit/types.ts +0 -407
  326. package/src/feedback/coverage-learner.ts +0 -456
  327. package/src/feedback/feedback-loop.ts +0 -426
  328. package/src/feedback/index.ts +0 -72
  329. package/src/feedback/pattern-promotion.ts +0 -373
  330. package/src/feedback/quality-score-calculator.ts +0 -334
  331. package/src/feedback/test-outcome-tracker.ts +0 -450
  332. package/src/feedback/types.ts +0 -497
  333. package/src/index.ts +0 -224
  334. package/src/init/agents-installer.ts +0 -536
  335. package/src/init/index.ts +0 -80
  336. package/src/init/init-wizard.ts +0 -1061
  337. package/src/init/project-analyzer.ts +0 -696
  338. package/src/init/self-configurator.ts +0 -488
  339. package/src/init/skills-installer.ts +0 -467
  340. package/src/init/types.ts +0 -432
  341. package/src/integrations/ruvector/ast-complexity.ts +0 -470
  342. package/src/integrations/ruvector/coverage-router.ts +0 -594
  343. package/src/integrations/ruvector/diff-risk-classifier.ts +0 -759
  344. package/src/integrations/ruvector/fallback.ts +0 -942
  345. package/src/integrations/ruvector/graph-boundaries.ts +0 -809
  346. package/src/integrations/ruvector/index.ts +0 -363
  347. package/src/integrations/ruvector/interfaces.ts +0 -609
  348. package/src/integrations/ruvector/q-learning-router.ts +0 -550
  349. package/src/kernel/agent-coordinator.ts +0 -165
  350. package/src/kernel/agentdb-backend.ts +0 -504
  351. package/src/kernel/event-bus.ts +0 -129
  352. package/src/kernel/hybrid-backend.ts +0 -538
  353. package/src/kernel/index.ts +0 -28
  354. package/src/kernel/interfaces.ts +0 -257
  355. package/src/kernel/kernel.ts +0 -285
  356. package/src/kernel/memory-backend.ts +0 -169
  357. package/src/kernel/memory-factory.ts +0 -293
  358. package/src/kernel/plugin-loader.ts +0 -179
  359. package/src/learning/index.ts +0 -219
  360. package/src/learning/pattern-store.ts +0 -990
  361. package/src/learning/qe-guidance.ts +0 -832
  362. package/src/learning/qe-hooks.ts +0 -644
  363. package/src/learning/qe-patterns.ts +0 -449
  364. package/src/learning/qe-reasoning-bank.ts +0 -951
  365. package/src/learning/real-embeddings.ts +0 -277
  366. package/src/learning/real-qe-reasoning-bank.ts +0 -833
  367. package/src/learning/sqlite-persistence.ts +0 -554
  368. package/src/mcp/entry.ts +0 -59
  369. package/src/mcp/handlers/agent-handlers.ts +0 -285
  370. package/src/mcp/handlers/core-handlers.ts +0 -317
  371. package/src/mcp/handlers/domain-handlers.ts +0 -1444
  372. package/src/mcp/handlers/index.ts +0 -57
  373. package/src/mcp/handlers/memory-handlers.ts +0 -338
  374. package/src/mcp/handlers/task-handlers.ts +0 -363
  375. package/src/mcp/index.ts +0 -30
  376. package/src/mcp/metrics/index.ts +0 -14
  377. package/src/mcp/metrics/metrics-collector.ts +0 -503
  378. package/src/mcp/protocol-server.ts +0 -752
  379. package/src/mcp/security/cve-prevention.ts +0 -742
  380. package/src/mcp/security/index.ts +0 -356
  381. package/src/mcp/security/oauth21-provider.ts +0 -821
  382. package/src/mcp/security/rate-limiter.ts +0 -615
  383. package/src/mcp/security/sampling-server.ts +0 -662
  384. package/src/mcp/security/schema-validator.ts +0 -855
  385. package/src/mcp/server.ts +0 -657
  386. package/src/mcp/tool-registry.ts +0 -391
  387. package/src/mcp/tools/base.ts +0 -399
  388. package/src/mcp/tools/chaos-resilience/inject.ts +0 -699
  389. package/src/mcp/tools/code-intelligence/analyze.ts +0 -745
  390. package/src/mcp/tools/contract-testing/validate.ts +0 -708
  391. package/src/mcp/tools/coverage-analysis/index.ts +0 -770
  392. package/src/mcp/tools/defect-intelligence/predict.ts +0 -466
  393. package/src/mcp/tools/index.ts +0 -214
  394. package/src/mcp/tools/learning-optimization/optimize.ts +0 -772
  395. package/src/mcp/tools/quality-assessment/evaluate.ts +0 -385
  396. package/src/mcp/tools/registry.ts +0 -248
  397. package/src/mcp/tools/requirements-validation/validate.ts +0 -394
  398. package/src/mcp/tools/security-compliance/scan.ts +0 -365
  399. package/src/mcp/tools/test-execution/execute.ts +0 -291
  400. package/src/mcp/tools/test-generation/generate.ts +0 -544
  401. package/src/mcp/tools/visual-accessibility/index.ts +0 -791
  402. package/src/mcp/transport/index.ts +0 -31
  403. package/src/mcp/transport/stdio.ts +0 -318
  404. package/src/mcp/types.ts +0 -543
  405. package/src/neural-optimizer/index.ts +0 -111
  406. package/src/neural-optimizer/replay-buffer.ts +0 -455
  407. package/src/neural-optimizer/swarm-topology.ts +0 -508
  408. package/src/neural-optimizer/topology-optimizer.ts +0 -828
  409. package/src/neural-optimizer/types.ts +0 -481
  410. package/src/neural-optimizer/value-network.ts +0 -351
  411. package/src/optimization/auto-tuner.ts +0 -817
  412. package/src/optimization/index.ts +0 -77
  413. package/src/optimization/metric-collectors.ts +0 -474
  414. package/src/optimization/qe-workers.ts +0 -704
  415. package/src/optimization/tuning-algorithm.ts +0 -401
  416. package/src/optimization/types.ts +0 -314
  417. package/src/routing/index.ts +0 -51
  418. package/src/routing/qe-agent-registry.ts +0 -963
  419. package/src/routing/qe-task-router.ts +0 -564
  420. package/src/routing/routing-feedback.ts +0 -365
  421. package/src/routing/types.ts +0 -406
  422. package/src/shared/embeddings/embedding-cache.ts +0 -157
  423. package/src/shared/embeddings/index.ts +0 -50
  424. package/src/shared/embeddings/nomic-embedder.ts +0 -404
  425. package/src/shared/embeddings/ollama-client.ts +0 -195
  426. package/src/shared/embeddings/types.ts +0 -147
  427. package/src/shared/entities/agent.ts +0 -141
  428. package/src/shared/entities/base-entity.ts +0 -79
  429. package/src/shared/entities/index.ts +0 -6
  430. package/src/shared/events/domain-events.ts +0 -259
  431. package/src/shared/events/index.ts +0 -5
  432. package/src/shared/git/git-analyzer.ts +0 -656
  433. package/src/shared/git/index.ts +0 -11
  434. package/src/shared/http/http-client.ts +0 -420
  435. package/src/shared/http/index.ts +0 -13
  436. package/src/shared/index.ts +0 -41
  437. package/src/shared/io/file-reader.ts +0 -525
  438. package/src/shared/io/index.ts +0 -25
  439. package/src/shared/llm/cache.ts +0 -473
  440. package/src/shared/llm/circuit-breaker.ts +0 -369
  441. package/src/shared/llm/cost-tracker.ts +0 -460
  442. package/src/shared/llm/index.ts +0 -140
  443. package/src/shared/llm/interfaces.ts +0 -629
  444. package/src/shared/llm/provider-manager.ts +0 -685
  445. package/src/shared/llm/providers/claude.ts +0 -524
  446. package/src/shared/llm/providers/index.ts +0 -8
  447. package/src/shared/llm/providers/ollama.ts +0 -575
  448. package/src/shared/llm/providers/openai.ts +0 -609
  449. package/src/shared/metrics/code-metrics.ts +0 -520
  450. package/src/shared/metrics/index.ts +0 -23
  451. package/src/shared/metrics/system-metrics.ts +0 -353
  452. package/src/shared/parsers/index.ts +0 -6
  453. package/src/shared/parsers/typescript-parser.ts +0 -841
  454. package/src/shared/security/compliance-patterns.ts +0 -666
  455. package/src/shared/security/index.ts +0 -30
  456. package/src/shared/security/osv-client.ts +0 -468
  457. package/src/shared/types/index.ts +0 -150
  458. package/src/shared/value-objects/index.ts +0 -273
  459. package/src/strange-loop/healing-controller.ts +0 -833
  460. package/src/strange-loop/index.ts +0 -104
  461. package/src/strange-loop/self-model.ts +0 -494
  462. package/src/strange-loop/strange-loop.ts +0 -446
  463. package/src/strange-loop/swarm-observer.ts +0 -448
  464. package/src/strange-loop/topology-analyzer.ts +0 -565
  465. package/src/strange-loop/types.ts +0 -640
  466. package/src/time-crystal/default-phases.ts +0 -520
  467. package/src/time-crystal/index.ts +0 -164
  468. package/src/time-crystal/oscillator.ts +0 -425
  469. package/src/time-crystal/phase-executor.ts +0 -521
  470. package/src/time-crystal/scheduler.ts +0 -1025
  471. package/src/time-crystal/test-runner.ts +0 -787
  472. package/src/time-crystal/types.ts +0 -421
  473. package/src/workers/base-worker.ts +0 -304
  474. package/src/workers/daemon.ts +0 -264
  475. package/src/workers/index.ts +0 -119
  476. package/src/workers/interfaces.ts +0 -393
  477. package/src/workers/worker-manager.ts +0 -424
  478. package/src/workers/workers/compliance-checker.ts +0 -445
  479. package/src/workers/workers/coverage-tracker.ts +0 -344
  480. package/src/workers/workers/defect-predictor.ts +0 -375
  481. package/src/workers/workers/flaky-detector.ts +0 -390
  482. package/src/workers/workers/index.ts +0 -17
  483. package/src/workers/workers/learning-consolidation.ts +0 -442
  484. package/src/workers/workers/performance-baseline.ts +0 -434
  485. package/src/workers/workers/quality-gate.ts +0 -419
  486. package/src/workers/workers/regression-monitor.ts +0 -357
  487. package/src/workers/workers/security-scan.ts +0 -349
  488. package/src/workers/workers/test-health.ts +0 -359
  489. package/tests/integration/code-intelligence/knowledge-graph-real.test.ts +0 -540
  490. package/tests/integration/coordination/cross-domain-router.test.ts +0 -403
  491. package/tests/integration/coordination/protocol-executor.test.ts +0 -454
  492. package/tests/integration/coordination/workflow-orchestrator.test.ts +0 -418
  493. package/tests/integration/feedback/feedback-loop-integration.test.ts +0 -560
  494. package/tests/integration/migration/v2-to-v3-migration.test.ts +0 -471
  495. package/tests/integration/parsers/typescript-parser.test.ts +0 -463
  496. package/tests/integration/security/vulnerability-detection.test.ts +0 -628
  497. package/tests/integration/test-execution/coordinator.test.ts +0 -410
  498. package/tests/integration/test-generation/coordinator.test.ts +0 -361
  499. package/tests/mocks/index.ts +0 -228
  500. package/tests/time-crystal/default-phases.test.ts +0 -476
  501. package/tests/time-crystal/oscillator.test.ts +0 -541
  502. package/tests/time-crystal/phase-executor.test.ts +0 -653
  503. package/tests/time-crystal/scheduler.test.ts +0 -626
  504. package/tests/time-crystal/test-runner.test.ts +0 -594
  505. package/tests/unit/causal-discovery/causal-graph.test.ts +0 -504
  506. package/tests/unit/causal-discovery/causal-root-cause-analyzer.test.ts +0 -347
  507. package/tests/unit/causal-discovery/discovery-engine.test.ts +0 -435
  508. package/tests/unit/causal-discovery/weight-matrix.test.ts +0 -328
  509. package/tests/unit/cli/cli.test.ts +0 -341
  510. package/tests/unit/cli/commands.test.ts +0 -414
  511. package/tests/unit/cli/init-command.test.ts +0 -274
  512. package/tests/unit/cli/migrate-command.test.ts +0 -396
  513. package/tests/unit/coordination/claims/claim-service.test.ts +0 -949
  514. package/tests/unit/coordination/claims/handoff-manager.test.ts +0 -773
  515. package/tests/unit/coordination/claims/work-stealing.test.ts +0 -492
  516. package/tests/unit/coordination/queen-coordinator.test.ts +0 -966
  517. package/tests/unit/coordination/result-saver.test.ts +0 -653
  518. package/tests/unit/coordination/task-executor.test.ts +0 -810
  519. package/tests/unit/domains/chaos-resilience/chaos-engineer.test.ts +0 -484
  520. package/tests/unit/domains/chaos-resilience/load-tester.test.ts +0 -559
  521. package/tests/unit/domains/chaos-resilience/performance-profiler.test.ts +0 -490
  522. package/tests/unit/domains/code-intelligence/impact-analyzer.test.ts +0 -560
  523. package/tests/unit/domains/code-intelligence/knowledge-graph.test.ts +0 -460
  524. package/tests/unit/domains/code-intelligence/semantic-analyzer.test.ts +0 -584
  525. package/tests/unit/domains/contract-testing/api-compatibility.test.ts +0 -483
  526. package/tests/unit/domains/contract-testing/contract-validator.test.ts +0 -370
  527. package/tests/unit/domains/contract-testing/schema-validator.test.ts +0 -610
  528. package/tests/unit/domains/coverage-analysis/coverage-embedder.test.ts +0 -298
  529. package/tests/unit/domains/coverage-analysis/hnsw-index.test.ts +0 -292
  530. package/tests/unit/domains/coverage-analysis/sublinear-analyzer.test.ts +0 -506
  531. package/tests/unit/domains/defect-intelligence/defect-predictor.test.ts +0 -370
  532. package/tests/unit/domains/defect-intelligence/pattern-learner.test.ts +0 -546
  533. package/tests/unit/domains/defect-intelligence/root-cause-analyzer.test.ts +0 -534
  534. package/tests/unit/domains/learning-optimization/learning-coordinator.test.ts +0 -541
  535. package/tests/unit/domains/learning-optimization/metrics-optimizer.test.ts +0 -552
  536. package/tests/unit/domains/learning-optimization/production-intel.test.ts +0 -589
  537. package/tests/unit/domains/learning-optimization/transfer-specialist.test.ts +0 -453
  538. package/tests/unit/domains/quality-assessment/coherence-gate.test.ts +0 -1006
  539. package/tests/unit/domains/quality-assessment/deployment-advisor.test.ts +0 -515
  540. package/tests/unit/domains/quality-assessment/quality-analyzer.test.ts +0 -401
  541. package/tests/unit/domains/quality-assessment/quality-gate.test.ts +0 -324
  542. package/tests/unit/domains/requirements-validation/bdd-scenario-writer.test.ts +0 -479
  543. package/tests/unit/domains/requirements-validation/requirements-validator.test.ts +0 -452
  544. package/tests/unit/domains/requirements-validation/testability-scorer.test.ts +0 -505
  545. package/tests/unit/domains/security-compliance/compliance-validator.test.ts +0 -500
  546. package/tests/unit/domains/security-compliance/security-auditor.test.ts +0 -498
  547. package/tests/unit/domains/security-compliance/security-scanner.test.ts +0 -412
  548. package/tests/unit/domains/visual-accessibility/accessibility-tester.test.ts +0 -432
  549. package/tests/unit/domains/visual-accessibility/responsive-tester.test.ts +0 -506
  550. package/tests/unit/domains/visual-accessibility/visual-tester.test.ts +0 -412
  551. package/tests/unit/early-exit/early-exit-controller.test.ts +0 -548
  552. package/tests/unit/early-exit/early-exit-decision.test.ts +0 -617
  553. package/tests/unit/early-exit/index.test.ts +0 -254
  554. package/tests/unit/early-exit/quality-signal.test.ts +0 -589
  555. package/tests/unit/early-exit/speculative-executor.test.ts +0 -453
  556. package/tests/unit/feedback/coverage-learner.test.ts +0 -288
  557. package/tests/unit/feedback/feedback-loop.test.ts +0 -458
  558. package/tests/unit/feedback/pattern-promotion.test.ts +0 -390
  559. package/tests/unit/feedback/quality-score-calculator.test.ts +0 -364
  560. package/tests/unit/feedback/test-outcome-tracker.test.ts +0 -243
  561. package/tests/unit/init/init-wizard.test.ts +0 -881
  562. package/tests/unit/init/project-analyzer.test.ts +0 -807
  563. package/tests/unit/init/self-configurator.test.ts +0 -493
  564. package/tests/unit/integrations/ruvector/ast-complexity.test.ts +0 -240
  565. package/tests/unit/integrations/ruvector/coverage-router.test.ts +0 -366
  566. package/tests/unit/integrations/ruvector/diff-risk-classifier.test.ts +0 -340
  567. package/tests/unit/integrations/ruvector/graph-boundaries.test.ts +0 -355
  568. package/tests/unit/integrations/ruvector/q-learning-router.test.ts +0 -314
  569. package/tests/unit/kernel/agent-coordinator.test.ts +0 -220
  570. package/tests/unit/kernel/event-bus.test.ts +0 -197
  571. package/tests/unit/learning/qe-reasoning-bank.test.ts +0 -666
  572. package/tests/unit/learning/real-qe-reasoning-bank.benchmark.test.ts +0 -415
  573. package/tests/unit/mcp/mcp-server.test.ts +0 -544
  574. package/tests/unit/mcp/metrics/metrics-collector.test.ts +0 -340
  575. package/tests/unit/mcp/security/cve-prevention.test.ts +0 -512
  576. package/tests/unit/mcp/security/oauth21-provider.test.ts +0 -624
  577. package/tests/unit/mcp/security/rate-limiter.test.ts +0 -410
  578. package/tests/unit/mcp/security/sampling-server.test.ts +0 -420
  579. package/tests/unit/mcp/security/schema-validator.test.ts +0 -494
  580. package/tests/unit/mcp/tools/base.test.ts +0 -336
  581. package/tests/unit/mcp/tools/domain-tools.test.ts +0 -759
  582. package/tests/unit/mcp/tools/registry.test.ts +0 -240
  583. package/tests/unit/neural-optimizer/replay-buffer.test.ts +0 -403
  584. package/tests/unit/neural-optimizer/swarm-topology.test.ts +0 -473
  585. package/tests/unit/neural-optimizer/topology-optimizer.test.ts +0 -595
  586. package/tests/unit/neural-optimizer/value-network.test.ts +0 -343
  587. package/tests/unit/optimization/auto-tuner.test.ts +0 -506
  588. package/tests/unit/optimization/metric-collectors.test.ts +0 -352
  589. package/tests/unit/optimization/qe-workers.test.ts +0 -407
  590. package/tests/unit/optimization/tuning-algorithm.test.ts +0 -467
  591. package/tests/unit/routing/qe-agent-registry.test.ts +0 -229
  592. package/tests/unit/routing/qe-task-router.test.ts +0 -390
  593. package/tests/unit/routing/routing-feedback.test.ts +0 -339
  594. package/tests/unit/shared/embeddings/nomic-embedder.test.ts +0 -419
  595. package/tests/unit/shared/http/http-client.test.ts +0 -719
  596. package/tests/unit/shared/io/file-reader.test.ts +0 -511
  597. package/tests/unit/shared/llm/cache.test.ts +0 -391
  598. package/tests/unit/shared/llm/circuit-breaker.test.ts +0 -293
  599. package/tests/unit/shared/llm/cost-tracker.test.ts +0 -431
  600. package/tests/unit/shared/llm/provider-manager.test.ts +0 -550
  601. package/tests/unit/shared/llm/providers.test.ts +0 -532
  602. package/tests/unit/shared/parsers/typescript-parser.test.ts +0 -693
  603. package/tests/unit/shared/value-objects.test.ts +0 -184
  604. package/tests/unit/strange-loop/strange-loop.test.ts +0 -1170
  605. package/tests/unit/workers/base-worker.test.ts +0 -341
  606. package/tests/unit/workers/daemon.test.ts +0 -291
  607. package/tests/unit/workers/worker-manager.test.ts +0 -284
  608. package/tsconfig.json +0 -32
  609. 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
- }