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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (612) hide show
  1. package/assets/agents/v3/subagents/v3-qe-code-reviewer.md +339 -0
  2. package/assets/agents/v3/subagents/v3-qe-integration-reviewer.md +344 -0
  3. package/assets/agents/v3/subagents/v3-qe-performance-reviewer.md +351 -0
  4. package/assets/agents/v3/subagents/v3-qe-security-reviewer.md +374 -0
  5. package/assets/agents/v3/subagents/v3-qe-tdd-green.md +334 -0
  6. package/assets/agents/v3/subagents/v3-qe-tdd-red.md +329 -0
  7. package/assets/agents/v3/subagents/v3-qe-tdd-refactor.md +361 -0
  8. package/assets/agents/v3/v3-qe-accessibility-auditor.md +266 -0
  9. package/assets/agents/v3/v3-qe-bdd-generator.md +279 -0
  10. package/assets/agents/v3/v3-qe-chaos-engineer.md +265 -0
  11. package/assets/agents/v3/v3-qe-code-complexity.md +298 -0
  12. package/assets/agents/v3/v3-qe-code-intelligence.md +262 -0
  13. package/assets/agents/v3/v3-qe-contract-validator.md +267 -0
  14. package/assets/agents/v3/v3-qe-coverage-specialist.md +227 -0
  15. package/assets/agents/v3/v3-qe-defect-predictor.md +251 -0
  16. package/assets/agents/v3/v3-qe-dependency-mapper.md +277 -0
  17. package/assets/agents/v3/v3-qe-deployment-advisor.md +275 -0
  18. package/assets/agents/v3/v3-qe-flaky-hunter.md +248 -0
  19. package/assets/agents/v3/v3-qe-fleet-commander.md +293 -0
  20. package/assets/agents/v3/v3-qe-gap-detector.md +260 -0
  21. package/assets/agents/v3/v3-qe-graphql-tester.md +308 -0
  22. package/assets/agents/v3/v3-qe-impact-analyzer.md +299 -0
  23. package/assets/agents/v3/v3-qe-integration-tester.md +238 -0
  24. package/assets/agents/v3/v3-qe-kg-builder.md +273 -0
  25. package/assets/agents/v3/v3-qe-learning-coordinator.md +226 -0
  26. package/assets/agents/v3/v3-qe-load-tester.md +280 -0
  27. package/assets/agents/v3/v3-qe-metrics-optimizer.md +300 -0
  28. package/assets/agents/v3/v3-qe-mutation-tester.md +301 -0
  29. package/assets/agents/v3/v3-qe-parallel-executor.md +240 -0
  30. package/assets/agents/v3/v3-qe-pattern-learner.md +271 -0
  31. package/assets/agents/v3/v3-qe-performance-tester.md +262 -0
  32. package/assets/agents/v3/v3-qe-property-tester.md +247 -0
  33. package/assets/agents/v3/v3-qe-quality-gate.md +218 -0
  34. package/assets/agents/v3/v3-qe-queen-coordinator.md +214 -0
  35. package/assets/agents/v3/v3-qe-qx-partner.md +313 -0
  36. package/assets/agents/v3/v3-qe-regression-analyzer.md +322 -0
  37. package/assets/agents/v3/v3-qe-requirements-validator.md +360 -0
  38. package/assets/agents/v3/v3-qe-responsive-tester.md +311 -0
  39. package/assets/agents/v3/v3-qe-retry-handler.md +256 -0
  40. package/assets/agents/v3/v3-qe-risk-assessor.md +273 -0
  41. package/assets/agents/v3/v3-qe-root-cause-analyzer.md +286 -0
  42. package/assets/agents/v3/v3-qe-security-auditor.md +299 -0
  43. package/assets/agents/v3/v3-qe-security-scanner.md +235 -0
  44. package/assets/agents/v3/v3-qe-tdd-specialist.md +239 -0
  45. package/assets/agents/v3/v3-qe-test-architect.md +233 -0
  46. package/assets/agents/v3/v3-qe-transfer-specialist.md +295 -0
  47. package/assets/agents/v3/v3-qe-visual-tester.md +232 -0
  48. package/assets/skills/accessibility-testing/SKILL.md +216 -0
  49. package/assets/skills/agentdb-advanced/SKILL.md +550 -0
  50. package/assets/skills/agentdb-learning/SKILL.md +545 -0
  51. package/assets/skills/agentdb-memory-patterns/SKILL.md +339 -0
  52. package/assets/skills/agentdb-optimization/SKILL.md +509 -0
  53. package/assets/skills/agentdb-vector-search/SKILL.md +339 -0
  54. package/assets/skills/agentic-jujutsu/SKILL.md +645 -0
  55. package/assets/skills/agentic-quality-engineering/SKILL.md +335 -0
  56. package/assets/skills/api-testing-patterns/SKILL.md +294 -0
  57. package/assets/skills/aqe-v2-v3-migration/skill.md +322 -0
  58. package/assets/skills/brutal-honesty-review/README.md +218 -0
  59. package/assets/skills/brutal-honesty-review/SKILL.md +235 -0
  60. package/assets/skills/brutal-honesty-review/resources/assessment-rubrics.md +295 -0
  61. package/assets/skills/brutal-honesty-review/resources/review-template.md +102 -0
  62. package/assets/skills/brutal-honesty-review/scripts/assess-code.sh +179 -0
  63. package/assets/skills/brutal-honesty-review/scripts/assess-tests.sh +223 -0
  64. package/assets/skills/bug-reporting-excellence/SKILL.md +225 -0
  65. package/assets/skills/chaos-engineering-resilience/SKILL.md +158 -0
  66. package/assets/skills/cicd-pipeline-qe-orchestrator/README.md +304 -0
  67. package/assets/skills/cicd-pipeline-qe-orchestrator/SKILL.md +315 -0
  68. package/assets/skills/cicd-pipeline-qe-orchestrator/resources/workflows/microservice-pipeline.md +239 -0
  69. package/assets/skills/cicd-pipeline-qe-orchestrator/resources/workflows/mobile-pipeline.md +375 -0
  70. package/assets/skills/cicd-pipeline-qe-orchestrator/resources/workflows/monolith-pipeline.md +268 -0
  71. package/assets/skills/code-review-quality/SKILL.md +227 -0
  72. package/assets/skills/compatibility-testing/SKILL.md +205 -0
  73. package/assets/skills/compliance-testing/SKILL.md +225 -0
  74. package/assets/skills/consultancy-practices/SKILL.md +202 -0
  75. package/assets/skills/context-driven-testing/SKILL.md +196 -0
  76. package/assets/skills/contract-testing/SKILL.md +222 -0
  77. package/assets/skills/database-testing/SKILL.md +244 -0
  78. package/assets/skills/exploratory-testing-advanced/SKILL.md +201 -0
  79. package/assets/skills/flow-nexus-neural/SKILL.md +738 -0
  80. package/assets/skills/flow-nexus-platform/SKILL.md +1157 -0
  81. package/assets/skills/flow-nexus-swarm/SKILL.md +610 -0
  82. package/assets/skills/github-code-review/SKILL.md +1140 -0
  83. package/assets/skills/github-multi-repo/SKILL.md +874 -0
  84. package/assets/skills/github-project-management/SKILL.md +1277 -0
  85. package/assets/skills/github-release-management/SKILL.md +1081 -0
  86. package/assets/skills/github-workflow-automation/SKILL.md +1065 -0
  87. package/assets/skills/hive-mind-advanced/SKILL.md +712 -0
  88. package/assets/skills/holistic-testing-pact/SKILL.md +171 -0
  89. package/assets/skills/hooks-automation/SKILL.md +1201 -0
  90. package/assets/skills/localization-testing/SKILL.md +221 -0
  91. package/assets/skills/mobile-testing/SKILL.md +219 -0
  92. package/assets/skills/mutation-testing/SKILL.md +229 -0
  93. package/assets/skills/n8n-expression-testing/SKILL.md +434 -0
  94. package/assets/skills/n8n-integration-testing-patterns/SKILL.md +540 -0
  95. package/assets/skills/n8n-security-testing/SKILL.md +599 -0
  96. package/assets/skills/n8n-trigger-testing-strategies/SKILL.md +541 -0
  97. package/assets/skills/n8n-workflow-testing-fundamentals/SKILL.md +447 -0
  98. package/assets/skills/pair-programming/SKILL.md +1202 -0
  99. package/assets/skills/performance-analysis/SKILL.md +563 -0
  100. package/assets/skills/performance-testing/SKILL.md +310 -0
  101. package/assets/skills/quality-metrics/SKILL.md +225 -0
  102. package/assets/skills/reasoningbank-agentdb/SKILL.md +446 -0
  103. package/assets/skills/reasoningbank-intelligence/SKILL.md +201 -0
  104. package/assets/skills/refactoring-patterns/SKILL.md +205 -0
  105. package/assets/skills/regression-testing/SKILL.md +227 -0
  106. package/assets/skills/risk-based-testing/SKILL.md +206 -0
  107. package/assets/skills/security-testing/SKILL.md +306 -0
  108. package/assets/skills/sherlock-review/SKILL.md +250 -0
  109. package/assets/skills/shift-left-testing/SKILL.md +225 -0
  110. package/assets/skills/shift-right-testing/SKILL.md +227 -0
  111. package/assets/skills/six-thinking-hats/README.md +190 -0
  112. package/assets/skills/six-thinking-hats/SKILL.md +280 -0
  113. package/assets/skills/six-thinking-hats/resources/examples/api-testing-example.md +345 -0
  114. package/assets/skills/six-thinking-hats/resources/templates/solo-session-template.md +167 -0
  115. package/assets/skills/six-thinking-hats/resources/templates/team-session-template.md +336 -0
  116. package/assets/skills/skill-builder/SKILL.md +910 -0
  117. package/assets/skills/sparc-methodology/SKILL.md +1115 -0
  118. package/assets/skills/stream-chain/SKILL.md +563 -0
  119. package/assets/skills/swarm-advanced/SKILL.md +973 -0
  120. package/assets/skills/swarm-orchestration/SKILL.md +179 -0
  121. package/assets/skills/tdd-london-chicago/SKILL.md +244 -0
  122. package/assets/skills/technical-writing/SKILL.md +178 -0
  123. package/assets/skills/test-automation-strategy/SKILL.md +230 -0
  124. package/assets/skills/test-data-management/SKILL.md +270 -0
  125. package/assets/skills/test-design-techniques/SKILL.md +244 -0
  126. package/assets/skills/test-environment-management/SKILL.md +243 -0
  127. package/assets/skills/test-reporting-analytics/SKILL.md +214 -0
  128. package/assets/skills/testability-scoring/README.md +71 -0
  129. package/assets/skills/testability-scoring/SKILL.md +346 -0
  130. package/assets/skills/testability-scoring/resources/templates/config.template.js +84 -0
  131. package/assets/skills/testability-scoring/resources/templates/testability-scoring.spec.template.js +532 -0
  132. package/assets/skills/testability-scoring/scripts/generate-html-report.js +1007 -0
  133. package/assets/skills/testability-scoring/scripts/run-assessment.sh +70 -0
  134. package/assets/skills/v3-qe-chaos-resilience/SKILL.md +238 -0
  135. package/assets/skills/v3-qe-code-intelligence/SKILL.md +209 -0
  136. package/assets/skills/v3-qe-contract-testing/SKILL.md +218 -0
  137. package/assets/skills/v3-qe-coverage-analysis/SKILL.md +187 -0
  138. package/assets/skills/v3-qe-defect-intelligence/SKILL.md +205 -0
  139. package/assets/skills/v3-qe-learning-optimization/SKILL.md +238 -0
  140. package/assets/skills/v3-qe-quality-assessment/SKILL.md +213 -0
  141. package/assets/skills/v3-qe-requirements-validation/SKILL.md +248 -0
  142. package/assets/skills/v3-qe-test-execution/SKILL.md +182 -0
  143. package/assets/skills/v3-qe-test-generation/SKILL.md +141 -0
  144. package/assets/skills/v3-qe-visual-accessibility/SKILL.md +242 -0
  145. package/assets/skills/verification-quality/SKILL.md +649 -0
  146. package/assets/skills/visual-testing-advanced/SKILL.md +219 -0
  147. package/assets/skills/xp-practices/SKILL.md +229 -0
  148. package/dist/cli/bundle.js +23 -13
  149. package/dist/init/agents-installer.js +4 -4
  150. package/dist/init/agents-installer.js.map +1 -1
  151. package/dist/init/init-wizard.d.ts.map +1 -1
  152. package/dist/init/init-wizard.js +15 -5
  153. package/dist/init/init-wizard.js.map +1 -1
  154. package/dist/init/skills-installer.js +4 -4
  155. package/dist/init/skills-installer.js.map +1 -1
  156. package/package.json +7 -1
  157. package/docs/analysis/V3-INIT-REQUIREMENTS-ANALYSIS.md +0 -352
  158. package/implementation/README.md +0 -90
  159. package/implementation/adrs/ADR-030-coherence-gated-quality-gates.md +0 -312
  160. package/implementation/adrs/ADR-031-strange-loop-self-awareness.md +0 -484
  161. package/implementation/adrs/ADR-032-time-crystal-scheduling.md +0 -530
  162. package/implementation/adrs/ADR-033-early-exit-testing.md +0 -634
  163. package/implementation/adrs/ADR-034-neural-topology-optimizer.md +0 -589
  164. package/implementation/adrs/ADR-035-causal-discovery.md +0 -610
  165. package/implementation/adrs/ADR-036-result-persistence.md +0 -326
  166. package/implementation/adrs/ADR-037-v3-qe-agent-naming.md +0 -105
  167. package/implementation/adrs/ADR-038-v3-qe-memory-unification.md +0 -154
  168. package/implementation/adrs/ADR-039-v3-qe-mcp-optimization.md +0 -179
  169. package/implementation/adrs/ADR-040-v3-qe-agentic-flow-integration.md +0 -240
  170. package/implementation/adrs/ADR-041-v3-qe-cli-enhancement.md +0 -296
  171. package/implementation/adrs/ADR-042-v3-qe-token-tracking-integration.md +0 -517
  172. package/implementation/adrs/v3-adrs.md +0 -2783
  173. package/implementation/planning/AQE-V3-MASTER-PLAN.md +0 -815
  174. package/security-scan-report-2026-01-11.md +0 -410
  175. package/security-verification-report-2026-01-11.md +0 -278
  176. package/src/benchmarks/performance-benchmarks.ts +0 -646
  177. package/src/benchmarks/run-benchmarks.ts +0 -324
  178. package/src/causal-discovery/causal-graph.ts +0 -450
  179. package/src/causal-discovery/discovery-engine.ts +0 -438
  180. package/src/causal-discovery/index.ts +0 -117
  181. package/src/causal-discovery/types.ts +0 -456
  182. package/src/causal-discovery/weight-matrix.ts +0 -453
  183. package/src/cli/commands/qe-tools.ts +0 -634
  184. package/src/cli/index.ts +0 -1976
  185. package/src/compatibility/agent-mapper.ts +0 -291
  186. package/src/compatibility/cli-adapter.ts +0 -277
  187. package/src/compatibility/config-migrator.ts +0 -334
  188. package/src/compatibility/index.ts +0 -112
  189. package/src/compatibility/mcp-adapter.ts +0 -248
  190. package/src/compatibility/types.ts +0 -156
  191. package/src/coordination/claims/claim-repository.ts +0 -636
  192. package/src/coordination/claims/claim-service.ts +0 -675
  193. package/src/coordination/claims/handoff-manager.ts +0 -535
  194. package/src/coordination/claims/index.ts +0 -276
  195. package/src/coordination/claims/interfaces.ts +0 -687
  196. package/src/coordination/claims/work-stealing.ts +0 -436
  197. package/src/coordination/cross-domain-router.ts +0 -492
  198. package/src/coordination/index.ts +0 -127
  199. package/src/coordination/interfaces.ts +0 -691
  200. package/src/coordination/protocol-executor.ts +0 -760
  201. package/src/coordination/protocols/code-intelligence-index.ts +0 -855
  202. package/src/coordination/protocols/defect-investigation.ts +0 -1184
  203. package/src/coordination/protocols/index.ts +0 -11
  204. package/src/coordination/protocols/learning-consolidation.ts +0 -1181
  205. package/src/coordination/protocols/morning-sync.ts +0 -1055
  206. package/src/coordination/protocols/quality-gate.ts +0 -1566
  207. package/src/coordination/protocols/security-audit.ts +0 -1587
  208. package/src/coordination/queen-coordinator.ts +0 -1176
  209. package/src/coordination/result-saver.ts +0 -780
  210. package/src/coordination/task-executor.ts +0 -1146
  211. package/src/coordination/workflow-orchestrator.ts +0 -1917
  212. package/src/domains/chaos-resilience/coordinator.ts +0 -1032
  213. package/src/domains/chaos-resilience/index.ts +0 -143
  214. package/src/domains/chaos-resilience/interfaces.ts +0 -659
  215. package/src/domains/chaos-resilience/plugin.ts +0 -691
  216. package/src/domains/chaos-resilience/services/chaos-engineer.ts +0 -1097
  217. package/src/domains/chaos-resilience/services/index.ts +0 -19
  218. package/src/domains/chaos-resilience/services/load-tester.ts +0 -799
  219. package/src/domains/chaos-resilience/services/performance-profiler.ts +0 -792
  220. package/src/domains/code-intelligence/coordinator.ts +0 -631
  221. package/src/domains/code-intelligence/index.ts +0 -86
  222. package/src/domains/code-intelligence/interfaces.ts +0 -162
  223. package/src/domains/code-intelligence/plugin.ts +0 -451
  224. package/src/domains/code-intelligence/services/impact-analyzer.ts +0 -567
  225. package/src/domains/code-intelligence/services/index.ts +0 -26
  226. package/src/domains/code-intelligence/services/knowledge-graph.ts +0 -1067
  227. package/src/domains/code-intelligence/services/semantic-analyzer.ts +0 -901
  228. package/src/domains/contract-testing/coordinator.ts +0 -1038
  229. package/src/domains/contract-testing/index.ts +0 -122
  230. package/src/domains/contract-testing/interfaces.ts +0 -458
  231. package/src/domains/contract-testing/plugin.ts +0 -746
  232. package/src/domains/contract-testing/services/api-compatibility.ts +0 -748
  233. package/src/domains/contract-testing/services/contract-validator.ts +0 -1700
  234. package/src/domains/contract-testing/services/index.ts +0 -19
  235. package/src/domains/contract-testing/services/schema-validator.ts +0 -1102
  236. package/src/domains/coverage-analysis/coordinator.ts +0 -485
  237. package/src/domains/coverage-analysis/index.ts +0 -114
  238. package/src/domains/coverage-analysis/interfaces.ts +0 -142
  239. package/src/domains/coverage-analysis/plugin.ts +0 -172
  240. package/src/domains/coverage-analysis/services/coverage-analyzer.ts +0 -449
  241. package/src/domains/coverage-analysis/services/coverage-embedder.ts +0 -733
  242. package/src/domains/coverage-analysis/services/coverage-parser.ts +0 -753
  243. package/src/domains/coverage-analysis/services/gap-detector.ts +0 -592
  244. package/src/domains/coverage-analysis/services/hnsw-index.ts +0 -728
  245. package/src/domains/coverage-analysis/services/index.ts +0 -61
  246. package/src/domains/coverage-analysis/services/risk-scorer.ts +0 -540
  247. package/src/domains/coverage-analysis/services/sublinear-analyzer.ts +0 -747
  248. package/src/domains/defect-intelligence/coordinator.ts +0 -635
  249. package/src/domains/defect-intelligence/index.ts +0 -83
  250. package/src/domains/defect-intelligence/interfaces.ts +0 -152
  251. package/src/domains/defect-intelligence/plugin.ts +0 -483
  252. package/src/domains/defect-intelligence/services/causal-root-cause-analyzer.ts +0 -494
  253. package/src/domains/defect-intelligence/services/defect-predictor.ts +0 -852
  254. package/src/domains/defect-intelligence/services/index.ts +0 -37
  255. package/src/domains/defect-intelligence/services/pattern-learner.ts +0 -738
  256. package/src/domains/defect-intelligence/services/root-cause-analyzer.ts +0 -637
  257. package/src/domains/domain-interface.ts +0 -77
  258. package/src/domains/index.ts +0 -23
  259. package/src/domains/learning-optimization/coordinator.ts +0 -1215
  260. package/src/domains/learning-optimization/index.ts +0 -127
  261. package/src/domains/learning-optimization/interfaces.ts +0 -570
  262. package/src/domains/learning-optimization/plugin.ts +0 -851
  263. package/src/domains/learning-optimization/services/index.ts +0 -29
  264. package/src/domains/learning-optimization/services/learning-coordinator.ts +0 -972
  265. package/src/domains/learning-optimization/services/metrics-optimizer.ts +0 -915
  266. package/src/domains/learning-optimization/services/production-intel.ts +0 -971
  267. package/src/domains/learning-optimization/services/transfer-specialist.ts +0 -723
  268. package/src/domains/quality-assessment/coherence/gate-controller.ts +0 -549
  269. package/src/domains/quality-assessment/coherence/index.ts +0 -211
  270. package/src/domains/quality-assessment/coherence/lambda-calculator.ts +0 -384
  271. package/src/domains/quality-assessment/coherence/partition-detector.ts +0 -469
  272. package/src/domains/quality-assessment/coherence/types.ts +0 -384
  273. package/src/domains/quality-assessment/coordinator.ts +0 -605
  274. package/src/domains/quality-assessment/index.ts +0 -97
  275. package/src/domains/quality-assessment/interfaces.ts +0 -152
  276. package/src/domains/quality-assessment/plugin.ts +0 -496
  277. package/src/domains/quality-assessment/services/coherence-gate.ts +0 -358
  278. package/src/domains/quality-assessment/services/deployment-advisor.ts +0 -571
  279. package/src/domains/quality-assessment/services/index.ts +0 -34
  280. package/src/domains/quality-assessment/services/quality-analyzer.ts +0 -670
  281. package/src/domains/quality-assessment/services/quality-gate.ts +0 -384
  282. package/src/domains/requirements-validation/coordinator.ts +0 -812
  283. package/src/domains/requirements-validation/index.ts +0 -92
  284. package/src/domains/requirements-validation/interfaces.ts +0 -303
  285. package/src/domains/requirements-validation/plugin.ts +0 -576
  286. package/src/domains/requirements-validation/services/bdd-scenario-writer.ts +0 -676
  287. package/src/domains/requirements-validation/services/index.ts +0 -20
  288. package/src/domains/requirements-validation/services/requirements-validator.ts +0 -559
  289. package/src/domains/requirements-validation/services/testability-scorer.ts +0 -639
  290. package/src/domains/security-compliance/coordinator.ts +0 -757
  291. package/src/domains/security-compliance/index.ts +0 -120
  292. package/src/domains/security-compliance/interfaces.ts +0 -434
  293. package/src/domains/security-compliance/plugin.ts +0 -509
  294. package/src/domains/security-compliance/services/compliance-validator.ts +0 -1226
  295. package/src/domains/security-compliance/services/index.ts +0 -31
  296. package/src/domains/security-compliance/services/security-auditor.ts +0 -2227
  297. package/src/domains/security-compliance/services/security-scanner.ts +0 -2354
  298. package/src/domains/security-compliance/services/semgrep-integration.ts +0 -289
  299. package/src/domains/test-execution/coordinator.ts +0 -426
  300. package/src/domains/test-execution/index.ts +0 -76
  301. package/src/domains/test-execution/interfaces.ts +0 -119
  302. package/src/domains/test-execution/plugin.ts +0 -208
  303. package/src/domains/test-execution/services/flaky-detector.ts +0 -1240
  304. package/src/domains/test-execution/services/index.ts +0 -8
  305. package/src/domains/test-execution/services/retry-handler.ts +0 -820
  306. package/src/domains/test-execution/services/test-executor.ts +0 -885
  307. package/src/domains/test-generation/coordinator.ts +0 -656
  308. package/src/domains/test-generation/index.ts +0 -77
  309. package/src/domains/test-generation/interfaces.ts +0 -118
  310. package/src/domains/test-generation/plugin.ts +0 -397
  311. package/src/domains/test-generation/services/index.ts +0 -23
  312. package/src/domains/test-generation/services/pattern-matcher.ts +0 -1725
  313. package/src/domains/test-generation/services/test-generator.ts +0 -2750
  314. package/src/domains/visual-accessibility/coordinator.ts +0 -860
  315. package/src/domains/visual-accessibility/index.ts +0 -116
  316. package/src/domains/visual-accessibility/interfaces.ts +0 -435
  317. package/src/domains/visual-accessibility/plugin.ts +0 -568
  318. package/src/domains/visual-accessibility/services/accessibility-tester.ts +0 -982
  319. package/src/domains/visual-accessibility/services/axe-core-audit.ts +0 -630
  320. package/src/domains/visual-accessibility/services/index.ts +0 -28
  321. package/src/domains/visual-accessibility/services/responsive-tester.ts +0 -934
  322. package/src/domains/visual-accessibility/services/visual-tester.ts +0 -458
  323. package/src/early-exit/early-exit-controller.ts +0 -490
  324. package/src/early-exit/early-exit-decision.ts +0 -391
  325. package/src/early-exit/index.ts +0 -115
  326. package/src/early-exit/quality-signal.ts +0 -389
  327. package/src/early-exit/speculative-executor.ts +0 -505
  328. package/src/early-exit/types.ts +0 -407
  329. package/src/feedback/coverage-learner.ts +0 -456
  330. package/src/feedback/feedback-loop.ts +0 -426
  331. package/src/feedback/index.ts +0 -72
  332. package/src/feedback/pattern-promotion.ts +0 -373
  333. package/src/feedback/quality-score-calculator.ts +0 -334
  334. package/src/feedback/test-outcome-tracker.ts +0 -450
  335. package/src/feedback/types.ts +0 -497
  336. package/src/index.ts +0 -224
  337. package/src/init/agents-installer.ts +0 -536
  338. package/src/init/index.ts +0 -80
  339. package/src/init/init-wizard.ts +0 -1061
  340. package/src/init/project-analyzer.ts +0 -696
  341. package/src/init/self-configurator.ts +0 -488
  342. package/src/init/skills-installer.ts +0 -467
  343. package/src/init/types.ts +0 -432
  344. package/src/integrations/ruvector/ast-complexity.ts +0 -470
  345. package/src/integrations/ruvector/coverage-router.ts +0 -594
  346. package/src/integrations/ruvector/diff-risk-classifier.ts +0 -759
  347. package/src/integrations/ruvector/fallback.ts +0 -942
  348. package/src/integrations/ruvector/graph-boundaries.ts +0 -809
  349. package/src/integrations/ruvector/index.ts +0 -363
  350. package/src/integrations/ruvector/interfaces.ts +0 -609
  351. package/src/integrations/ruvector/q-learning-router.ts +0 -550
  352. package/src/kernel/agent-coordinator.ts +0 -165
  353. package/src/kernel/agentdb-backend.ts +0 -504
  354. package/src/kernel/event-bus.ts +0 -129
  355. package/src/kernel/hybrid-backend.ts +0 -538
  356. package/src/kernel/index.ts +0 -28
  357. package/src/kernel/interfaces.ts +0 -257
  358. package/src/kernel/kernel.ts +0 -285
  359. package/src/kernel/memory-backend.ts +0 -169
  360. package/src/kernel/memory-factory.ts +0 -293
  361. package/src/kernel/plugin-loader.ts +0 -179
  362. package/src/learning/index.ts +0 -219
  363. package/src/learning/pattern-store.ts +0 -990
  364. package/src/learning/qe-guidance.ts +0 -832
  365. package/src/learning/qe-hooks.ts +0 -644
  366. package/src/learning/qe-patterns.ts +0 -449
  367. package/src/learning/qe-reasoning-bank.ts +0 -951
  368. package/src/learning/real-embeddings.ts +0 -277
  369. package/src/learning/real-qe-reasoning-bank.ts +0 -833
  370. package/src/learning/sqlite-persistence.ts +0 -554
  371. package/src/mcp/entry.ts +0 -59
  372. package/src/mcp/handlers/agent-handlers.ts +0 -285
  373. package/src/mcp/handlers/core-handlers.ts +0 -317
  374. package/src/mcp/handlers/domain-handlers.ts +0 -1444
  375. package/src/mcp/handlers/index.ts +0 -57
  376. package/src/mcp/handlers/memory-handlers.ts +0 -338
  377. package/src/mcp/handlers/task-handlers.ts +0 -363
  378. package/src/mcp/index.ts +0 -30
  379. package/src/mcp/metrics/index.ts +0 -14
  380. package/src/mcp/metrics/metrics-collector.ts +0 -503
  381. package/src/mcp/protocol-server.ts +0 -752
  382. package/src/mcp/security/cve-prevention.ts +0 -742
  383. package/src/mcp/security/index.ts +0 -356
  384. package/src/mcp/security/oauth21-provider.ts +0 -821
  385. package/src/mcp/security/rate-limiter.ts +0 -615
  386. package/src/mcp/security/sampling-server.ts +0 -662
  387. package/src/mcp/security/schema-validator.ts +0 -855
  388. package/src/mcp/server.ts +0 -657
  389. package/src/mcp/tool-registry.ts +0 -391
  390. package/src/mcp/tools/base.ts +0 -399
  391. package/src/mcp/tools/chaos-resilience/inject.ts +0 -699
  392. package/src/mcp/tools/code-intelligence/analyze.ts +0 -745
  393. package/src/mcp/tools/contract-testing/validate.ts +0 -708
  394. package/src/mcp/tools/coverage-analysis/index.ts +0 -770
  395. package/src/mcp/tools/defect-intelligence/predict.ts +0 -466
  396. package/src/mcp/tools/index.ts +0 -214
  397. package/src/mcp/tools/learning-optimization/optimize.ts +0 -772
  398. package/src/mcp/tools/quality-assessment/evaluate.ts +0 -385
  399. package/src/mcp/tools/registry.ts +0 -248
  400. package/src/mcp/tools/requirements-validation/validate.ts +0 -394
  401. package/src/mcp/tools/security-compliance/scan.ts +0 -365
  402. package/src/mcp/tools/test-execution/execute.ts +0 -291
  403. package/src/mcp/tools/test-generation/generate.ts +0 -544
  404. package/src/mcp/tools/visual-accessibility/index.ts +0 -791
  405. package/src/mcp/transport/index.ts +0 -31
  406. package/src/mcp/transport/stdio.ts +0 -318
  407. package/src/mcp/types.ts +0 -543
  408. package/src/neural-optimizer/index.ts +0 -111
  409. package/src/neural-optimizer/replay-buffer.ts +0 -455
  410. package/src/neural-optimizer/swarm-topology.ts +0 -508
  411. package/src/neural-optimizer/topology-optimizer.ts +0 -828
  412. package/src/neural-optimizer/types.ts +0 -481
  413. package/src/neural-optimizer/value-network.ts +0 -351
  414. package/src/optimization/auto-tuner.ts +0 -817
  415. package/src/optimization/index.ts +0 -77
  416. package/src/optimization/metric-collectors.ts +0 -474
  417. package/src/optimization/qe-workers.ts +0 -704
  418. package/src/optimization/tuning-algorithm.ts +0 -401
  419. package/src/optimization/types.ts +0 -314
  420. package/src/routing/index.ts +0 -51
  421. package/src/routing/qe-agent-registry.ts +0 -963
  422. package/src/routing/qe-task-router.ts +0 -564
  423. package/src/routing/routing-feedback.ts +0 -365
  424. package/src/routing/types.ts +0 -406
  425. package/src/shared/embeddings/embedding-cache.ts +0 -157
  426. package/src/shared/embeddings/index.ts +0 -50
  427. package/src/shared/embeddings/nomic-embedder.ts +0 -404
  428. package/src/shared/embeddings/ollama-client.ts +0 -195
  429. package/src/shared/embeddings/types.ts +0 -147
  430. package/src/shared/entities/agent.ts +0 -141
  431. package/src/shared/entities/base-entity.ts +0 -79
  432. package/src/shared/entities/index.ts +0 -6
  433. package/src/shared/events/domain-events.ts +0 -259
  434. package/src/shared/events/index.ts +0 -5
  435. package/src/shared/git/git-analyzer.ts +0 -656
  436. package/src/shared/git/index.ts +0 -11
  437. package/src/shared/http/http-client.ts +0 -420
  438. package/src/shared/http/index.ts +0 -13
  439. package/src/shared/index.ts +0 -41
  440. package/src/shared/io/file-reader.ts +0 -525
  441. package/src/shared/io/index.ts +0 -25
  442. package/src/shared/llm/cache.ts +0 -473
  443. package/src/shared/llm/circuit-breaker.ts +0 -369
  444. package/src/shared/llm/cost-tracker.ts +0 -460
  445. package/src/shared/llm/index.ts +0 -140
  446. package/src/shared/llm/interfaces.ts +0 -629
  447. package/src/shared/llm/provider-manager.ts +0 -685
  448. package/src/shared/llm/providers/claude.ts +0 -524
  449. package/src/shared/llm/providers/index.ts +0 -8
  450. package/src/shared/llm/providers/ollama.ts +0 -575
  451. package/src/shared/llm/providers/openai.ts +0 -609
  452. package/src/shared/metrics/code-metrics.ts +0 -520
  453. package/src/shared/metrics/index.ts +0 -23
  454. package/src/shared/metrics/system-metrics.ts +0 -353
  455. package/src/shared/parsers/index.ts +0 -6
  456. package/src/shared/parsers/typescript-parser.ts +0 -841
  457. package/src/shared/security/compliance-patterns.ts +0 -666
  458. package/src/shared/security/index.ts +0 -30
  459. package/src/shared/security/osv-client.ts +0 -468
  460. package/src/shared/types/index.ts +0 -150
  461. package/src/shared/value-objects/index.ts +0 -273
  462. package/src/strange-loop/healing-controller.ts +0 -833
  463. package/src/strange-loop/index.ts +0 -104
  464. package/src/strange-loop/self-model.ts +0 -494
  465. package/src/strange-loop/strange-loop.ts +0 -446
  466. package/src/strange-loop/swarm-observer.ts +0 -448
  467. package/src/strange-loop/topology-analyzer.ts +0 -565
  468. package/src/strange-loop/types.ts +0 -640
  469. package/src/time-crystal/default-phases.ts +0 -520
  470. package/src/time-crystal/index.ts +0 -164
  471. package/src/time-crystal/oscillator.ts +0 -425
  472. package/src/time-crystal/phase-executor.ts +0 -521
  473. package/src/time-crystal/scheduler.ts +0 -1025
  474. package/src/time-crystal/test-runner.ts +0 -787
  475. package/src/time-crystal/types.ts +0 -421
  476. package/src/workers/base-worker.ts +0 -304
  477. package/src/workers/daemon.ts +0 -264
  478. package/src/workers/index.ts +0 -119
  479. package/src/workers/interfaces.ts +0 -393
  480. package/src/workers/worker-manager.ts +0 -424
  481. package/src/workers/workers/compliance-checker.ts +0 -445
  482. package/src/workers/workers/coverage-tracker.ts +0 -344
  483. package/src/workers/workers/defect-predictor.ts +0 -375
  484. package/src/workers/workers/flaky-detector.ts +0 -390
  485. package/src/workers/workers/index.ts +0 -17
  486. package/src/workers/workers/learning-consolidation.ts +0 -442
  487. package/src/workers/workers/performance-baseline.ts +0 -434
  488. package/src/workers/workers/quality-gate.ts +0 -419
  489. package/src/workers/workers/regression-monitor.ts +0 -357
  490. package/src/workers/workers/security-scan.ts +0 -349
  491. package/src/workers/workers/test-health.ts +0 -359
  492. package/tests/integration/code-intelligence/knowledge-graph-real.test.ts +0 -540
  493. package/tests/integration/coordination/cross-domain-router.test.ts +0 -403
  494. package/tests/integration/coordination/protocol-executor.test.ts +0 -454
  495. package/tests/integration/coordination/workflow-orchestrator.test.ts +0 -418
  496. package/tests/integration/feedback/feedback-loop-integration.test.ts +0 -560
  497. package/tests/integration/migration/v2-to-v3-migration.test.ts +0 -471
  498. package/tests/integration/parsers/typescript-parser.test.ts +0 -463
  499. package/tests/integration/security/vulnerability-detection.test.ts +0 -628
  500. package/tests/integration/test-execution/coordinator.test.ts +0 -410
  501. package/tests/integration/test-generation/coordinator.test.ts +0 -361
  502. package/tests/mocks/index.ts +0 -228
  503. package/tests/time-crystal/default-phases.test.ts +0 -476
  504. package/tests/time-crystal/oscillator.test.ts +0 -541
  505. package/tests/time-crystal/phase-executor.test.ts +0 -653
  506. package/tests/time-crystal/scheduler.test.ts +0 -626
  507. package/tests/time-crystal/test-runner.test.ts +0 -594
  508. package/tests/unit/causal-discovery/causal-graph.test.ts +0 -504
  509. package/tests/unit/causal-discovery/causal-root-cause-analyzer.test.ts +0 -347
  510. package/tests/unit/causal-discovery/discovery-engine.test.ts +0 -435
  511. package/tests/unit/causal-discovery/weight-matrix.test.ts +0 -328
  512. package/tests/unit/cli/cli.test.ts +0 -341
  513. package/tests/unit/cli/commands.test.ts +0 -414
  514. package/tests/unit/cli/init-command.test.ts +0 -274
  515. package/tests/unit/cli/migrate-command.test.ts +0 -396
  516. package/tests/unit/coordination/claims/claim-service.test.ts +0 -949
  517. package/tests/unit/coordination/claims/handoff-manager.test.ts +0 -773
  518. package/tests/unit/coordination/claims/work-stealing.test.ts +0 -492
  519. package/tests/unit/coordination/queen-coordinator.test.ts +0 -966
  520. package/tests/unit/coordination/result-saver.test.ts +0 -653
  521. package/tests/unit/coordination/task-executor.test.ts +0 -810
  522. package/tests/unit/domains/chaos-resilience/chaos-engineer.test.ts +0 -484
  523. package/tests/unit/domains/chaos-resilience/load-tester.test.ts +0 -559
  524. package/tests/unit/domains/chaos-resilience/performance-profiler.test.ts +0 -490
  525. package/tests/unit/domains/code-intelligence/impact-analyzer.test.ts +0 -560
  526. package/tests/unit/domains/code-intelligence/knowledge-graph.test.ts +0 -460
  527. package/tests/unit/domains/code-intelligence/semantic-analyzer.test.ts +0 -584
  528. package/tests/unit/domains/contract-testing/api-compatibility.test.ts +0 -483
  529. package/tests/unit/domains/contract-testing/contract-validator.test.ts +0 -370
  530. package/tests/unit/domains/contract-testing/schema-validator.test.ts +0 -610
  531. package/tests/unit/domains/coverage-analysis/coverage-embedder.test.ts +0 -298
  532. package/tests/unit/domains/coverage-analysis/hnsw-index.test.ts +0 -292
  533. package/tests/unit/domains/coverage-analysis/sublinear-analyzer.test.ts +0 -506
  534. package/tests/unit/domains/defect-intelligence/defect-predictor.test.ts +0 -370
  535. package/tests/unit/domains/defect-intelligence/pattern-learner.test.ts +0 -546
  536. package/tests/unit/domains/defect-intelligence/root-cause-analyzer.test.ts +0 -534
  537. package/tests/unit/domains/learning-optimization/learning-coordinator.test.ts +0 -541
  538. package/tests/unit/domains/learning-optimization/metrics-optimizer.test.ts +0 -552
  539. package/tests/unit/domains/learning-optimization/production-intel.test.ts +0 -589
  540. package/tests/unit/domains/learning-optimization/transfer-specialist.test.ts +0 -453
  541. package/tests/unit/domains/quality-assessment/coherence-gate.test.ts +0 -1006
  542. package/tests/unit/domains/quality-assessment/deployment-advisor.test.ts +0 -515
  543. package/tests/unit/domains/quality-assessment/quality-analyzer.test.ts +0 -401
  544. package/tests/unit/domains/quality-assessment/quality-gate.test.ts +0 -324
  545. package/tests/unit/domains/requirements-validation/bdd-scenario-writer.test.ts +0 -479
  546. package/tests/unit/domains/requirements-validation/requirements-validator.test.ts +0 -452
  547. package/tests/unit/domains/requirements-validation/testability-scorer.test.ts +0 -505
  548. package/tests/unit/domains/security-compliance/compliance-validator.test.ts +0 -500
  549. package/tests/unit/domains/security-compliance/security-auditor.test.ts +0 -498
  550. package/tests/unit/domains/security-compliance/security-scanner.test.ts +0 -412
  551. package/tests/unit/domains/visual-accessibility/accessibility-tester.test.ts +0 -432
  552. package/tests/unit/domains/visual-accessibility/responsive-tester.test.ts +0 -506
  553. package/tests/unit/domains/visual-accessibility/visual-tester.test.ts +0 -412
  554. package/tests/unit/early-exit/early-exit-controller.test.ts +0 -548
  555. package/tests/unit/early-exit/early-exit-decision.test.ts +0 -617
  556. package/tests/unit/early-exit/index.test.ts +0 -254
  557. package/tests/unit/early-exit/quality-signal.test.ts +0 -589
  558. package/tests/unit/early-exit/speculative-executor.test.ts +0 -453
  559. package/tests/unit/feedback/coverage-learner.test.ts +0 -288
  560. package/tests/unit/feedback/feedback-loop.test.ts +0 -458
  561. package/tests/unit/feedback/pattern-promotion.test.ts +0 -390
  562. package/tests/unit/feedback/quality-score-calculator.test.ts +0 -364
  563. package/tests/unit/feedback/test-outcome-tracker.test.ts +0 -243
  564. package/tests/unit/init/init-wizard.test.ts +0 -881
  565. package/tests/unit/init/project-analyzer.test.ts +0 -807
  566. package/tests/unit/init/self-configurator.test.ts +0 -493
  567. package/tests/unit/integrations/ruvector/ast-complexity.test.ts +0 -240
  568. package/tests/unit/integrations/ruvector/coverage-router.test.ts +0 -366
  569. package/tests/unit/integrations/ruvector/diff-risk-classifier.test.ts +0 -340
  570. package/tests/unit/integrations/ruvector/graph-boundaries.test.ts +0 -355
  571. package/tests/unit/integrations/ruvector/q-learning-router.test.ts +0 -314
  572. package/tests/unit/kernel/agent-coordinator.test.ts +0 -220
  573. package/tests/unit/kernel/event-bus.test.ts +0 -197
  574. package/tests/unit/learning/qe-reasoning-bank.test.ts +0 -666
  575. package/tests/unit/learning/real-qe-reasoning-bank.benchmark.test.ts +0 -415
  576. package/tests/unit/mcp/mcp-server.test.ts +0 -544
  577. package/tests/unit/mcp/metrics/metrics-collector.test.ts +0 -340
  578. package/tests/unit/mcp/security/cve-prevention.test.ts +0 -512
  579. package/tests/unit/mcp/security/oauth21-provider.test.ts +0 -624
  580. package/tests/unit/mcp/security/rate-limiter.test.ts +0 -410
  581. package/tests/unit/mcp/security/sampling-server.test.ts +0 -420
  582. package/tests/unit/mcp/security/schema-validator.test.ts +0 -494
  583. package/tests/unit/mcp/tools/base.test.ts +0 -336
  584. package/tests/unit/mcp/tools/domain-tools.test.ts +0 -759
  585. package/tests/unit/mcp/tools/registry.test.ts +0 -240
  586. package/tests/unit/neural-optimizer/replay-buffer.test.ts +0 -403
  587. package/tests/unit/neural-optimizer/swarm-topology.test.ts +0 -473
  588. package/tests/unit/neural-optimizer/topology-optimizer.test.ts +0 -595
  589. package/tests/unit/neural-optimizer/value-network.test.ts +0 -343
  590. package/tests/unit/optimization/auto-tuner.test.ts +0 -506
  591. package/tests/unit/optimization/metric-collectors.test.ts +0 -352
  592. package/tests/unit/optimization/qe-workers.test.ts +0 -407
  593. package/tests/unit/optimization/tuning-algorithm.test.ts +0 -467
  594. package/tests/unit/routing/qe-agent-registry.test.ts +0 -229
  595. package/tests/unit/routing/qe-task-router.test.ts +0 -390
  596. package/tests/unit/routing/routing-feedback.test.ts +0 -339
  597. package/tests/unit/shared/embeddings/nomic-embedder.test.ts +0 -419
  598. package/tests/unit/shared/http/http-client.test.ts +0 -719
  599. package/tests/unit/shared/io/file-reader.test.ts +0 -511
  600. package/tests/unit/shared/llm/cache.test.ts +0 -391
  601. package/tests/unit/shared/llm/circuit-breaker.test.ts +0 -293
  602. package/tests/unit/shared/llm/cost-tracker.test.ts +0 -431
  603. package/tests/unit/shared/llm/provider-manager.test.ts +0 -550
  604. package/tests/unit/shared/llm/providers.test.ts +0 -532
  605. package/tests/unit/shared/parsers/typescript-parser.test.ts +0 -693
  606. package/tests/unit/shared/value-objects.test.ts +0 -184
  607. package/tests/unit/strange-loop/strange-loop.test.ts +0 -1170
  608. package/tests/unit/workers/base-worker.test.ts +0 -341
  609. package/tests/unit/workers/daemon.test.ts +0 -291
  610. package/tests/unit/workers/worker-manager.test.ts +0 -284
  611. package/tsconfig.json +0 -32
  612. package/vitest.config.ts +0 -27
@@ -1,2354 +0,0 @@
1
- /**
2
- * Agentic QE v3 - Security Scanner Service
3
- * Implements SAST and DAST security scanning capabilities
4
- * Includes OSV API integration for dependency vulnerability scanning
5
- */
6
-
7
- import { v4 as uuidv4 } from 'uuid';
8
- import { Result, ok, err } from '../../../shared/types/index.js';
9
- import type { MemoryBackend } from '../../../kernel/interfaces.js';
10
- import type { FilePath } from '../../../shared/value-objects/index.js';
11
- import type {
12
- SASTResult,
13
- DASTResult,
14
- DASTOptions,
15
- AuthCredentials,
16
- RuleSet,
17
- FalsePositiveCheck,
18
- Vulnerability,
19
- VulnerabilitySeverity,
20
- VulnerabilityCategory,
21
- VulnerabilityLocation,
22
- RemediationAdvice,
23
- ScanSummary,
24
- SecurityCoverage,
25
- ScanStatus,
26
- } from '../interfaces.js';
27
- import { OSVClient, ParsedVulnerability } from '../../../shared/security/index.js';
28
-
29
- // ============================================================================
30
- // Service Interfaces
31
- // ============================================================================
32
-
33
- /**
34
- * Dependency scan result
35
- */
36
- export interface DependencyScanResult {
37
- readonly scanId: string;
38
- readonly vulnerabilities: Vulnerability[];
39
- readonly packagesScanned: number;
40
- readonly vulnerablePackages: number;
41
- readonly summary: ScanSummary;
42
- readonly scanDurationMs: number;
43
- }
44
-
45
- /**
46
- * Combined security scanner service interface
47
- * Note: We define separate methods for SAST and DAST to avoid interface conflicts
48
- */
49
- export interface ISecurityScannerService {
50
- // SAST Methods
51
- scanFiles(files: FilePath[]): Promise<Result<SASTResult>>;
52
- scanWithRules(files: FilePath[], ruleSetIds: string[]): Promise<Result<SASTResult>>;
53
- getAvailableRuleSets(): Promise<RuleSet[]>;
54
- checkFalsePositive(vulnerability: Vulnerability): Promise<Result<FalsePositiveCheck>>;
55
-
56
- // DAST Methods
57
- scanUrl(targetUrl: string, options?: DASTOptions): Promise<Result<DASTResult>>;
58
- scanAuthenticated(
59
- targetUrl: string,
60
- credentials: AuthCredentials,
61
- options?: DASTOptions
62
- ): Promise<Result<DASTResult>>;
63
- getScanStatus(scanId: string): Promise<ScanStatus>;
64
-
65
- // Dependency Scanning (OSV)
66
- scanDependencies(dependencies: Record<string, string>): Promise<Result<DependencyScanResult>>;
67
- scanPackageJson(packageJsonPath: string): Promise<Result<DependencyScanResult>>;
68
-
69
- // Combined
70
- runFullScan(
71
- files: FilePath[],
72
- targetUrl?: string,
73
- options?: DASTOptions
74
- ): Promise<Result<FullScanResult>>;
75
- }
76
-
77
- export interface FullScanResult {
78
- readonly sastResult: SASTResult;
79
- readonly dastResult?: DASTResult;
80
- readonly combinedSummary: ScanSummary;
81
- }
82
-
83
- // ============================================================================
84
- // Configuration
85
- // ============================================================================
86
-
87
- export interface SecurityScannerConfig {
88
- defaultRuleSets: string[];
89
- maxConcurrentScans: number;
90
- timeout: number;
91
- enableFalsePositiveDetection: boolean;
92
- dastMaxDepth: number;
93
- dastActiveScanning: boolean;
94
- }
95
-
96
- const DEFAULT_CONFIG: SecurityScannerConfig = {
97
- defaultRuleSets: ['owasp-top-10', 'cwe-sans-25'],
98
- maxConcurrentScans: 4,
99
- timeout: 300000, // 5 minutes
100
- enableFalsePositiveDetection: true,
101
- dastMaxDepth: 5,
102
- dastActiveScanning: false,
103
- };
104
-
105
- // ============================================================================
106
- // Security Pattern Definitions
107
- // ============================================================================
108
-
109
- /**
110
- * Pattern definition for vulnerability detection
111
- */
112
- interface SecurityPattern {
113
- readonly id: string;
114
- readonly pattern: RegExp;
115
- readonly category: VulnerabilityCategory;
116
- readonly severity: VulnerabilitySeverity;
117
- readonly title: string;
118
- readonly description: string;
119
- readonly owaspId: string;
120
- readonly cweId: string;
121
- readonly remediation: string;
122
- readonly fixExample?: string;
123
- }
124
-
125
- /**
126
- * SQL Injection Detection Patterns
127
- * OWASP A03:2021 - Injection
128
- */
129
- const SQL_INJECTION_PATTERNS: SecurityPattern[] = [
130
- {
131
- id: 'sqli-string-concat',
132
- pattern: /query\s*\(\s*['"`].*\+.*['"`]\s*\)/g,
133
- category: 'injection',
134
- severity: 'critical',
135
- title: 'SQL Injection via String Concatenation',
136
- description: 'SQL query constructed using string concatenation with potentially untrusted input',
137
- owaspId: 'A03:2021',
138
- cweId: 'CWE-89',
139
- remediation: 'Use parameterized queries or prepared statements instead of string concatenation',
140
- fixExample: 'db.query("SELECT * FROM users WHERE id = $1", [userId])',
141
- },
142
- {
143
- id: 'sqli-template-literal',
144
- pattern: /execute\s*\(\s*`[^`]*\$\{[^}]+\}[^`]*`\s*\)/g,
145
- category: 'injection',
146
- severity: 'critical',
147
- title: 'SQL Injection via Template Literal',
148
- description: 'SQL query constructed using template literals with embedded expressions',
149
- owaspId: 'A03:2021',
150
- cweId: 'CWE-89',
151
- remediation: 'Use parameterized queries instead of template literals for SQL',
152
- fixExample: 'db.execute("DELETE FROM users WHERE id = ?", [userId])',
153
- },
154
- {
155
- id: 'sqli-raw-query',
156
- pattern: /\.raw\s*\(\s*['"`].*\+|\.raw\s*\(\s*`[^`]*\$\{/g,
157
- category: 'injection',
158
- severity: 'high',
159
- title: 'SQL Injection via Raw Query',
160
- description: 'Raw SQL query with potential user input interpolation',
161
- owaspId: 'A03:2021',
162
- cweId: 'CWE-89',
163
- remediation: 'Avoid raw queries with user input; use ORM methods or parameterized queries',
164
- },
165
- {
166
- id: 'sqli-exec',
167
- pattern: /exec(?:ute)?(?:Sql|Query)?\s*\([^)]*\+[^)]*\)/gi,
168
- category: 'injection',
169
- severity: 'critical',
170
- title: 'SQL Injection via Dynamic Execution',
171
- description: 'Dynamic SQL execution with string concatenation detected',
172
- owaspId: 'A03:2021',
173
- cweId: 'CWE-89',
174
- remediation: 'Never concatenate user input into SQL queries',
175
- },
176
- ];
177
-
178
- /**
179
- * XSS (Cross-Site Scripting) Detection Patterns
180
- * OWASP A03:2021 - Injection (includes XSS)
181
- */
182
- const XSS_PATTERNS: SecurityPattern[] = [
183
- {
184
- id: 'xss-innerhtml',
185
- pattern: /\.innerHTML\s*=\s*[^'"`;\n]+/g,
186
- category: 'xss',
187
- severity: 'high',
188
- title: 'XSS via innerHTML Assignment',
189
- description: 'Direct innerHTML assignment with potentially unsanitized content',
190
- owaspId: 'A03:2021',
191
- cweId: 'CWE-79',
192
- remediation: 'Use textContent for text, or sanitize HTML with DOMPurify before innerHTML assignment',
193
- fixExample: 'element.textContent = userInput; // or DOMPurify.sanitize(userInput)',
194
- },
195
- {
196
- id: 'xss-document-write',
197
- pattern: /document\.write\s*\([^)]+\)/g,
198
- category: 'xss',
199
- severity: 'high',
200
- title: 'XSS via document.write',
201
- description: 'document.write() can execute scripts from untrusted data',
202
- owaspId: 'A03:2021',
203
- cweId: 'CWE-79',
204
- remediation: 'Avoid document.write(); use DOM manipulation methods instead',
205
- fixExample: 'document.body.appendChild(document.createTextNode(text))',
206
- },
207
- {
208
- id: 'xss-dangerously-set',
209
- pattern: /dangerouslySetInnerHTML\s*=\s*\{/g,
210
- category: 'xss',
211
- severity: 'medium',
212
- title: 'React dangerouslySetInnerHTML Usage',
213
- description: 'dangerouslySetInnerHTML bypasses React XSS protections',
214
- owaspId: 'A03:2021',
215
- cweId: 'CWE-79',
216
- remediation: 'Sanitize HTML content with DOMPurify before using dangerouslySetInnerHTML',
217
- fixExample: 'dangerouslySetInnerHTML={{ __html: DOMPurify.sanitize(content) }}',
218
- },
219
- {
220
- id: 'xss-eval',
221
- pattern: /eval\s*\([^)]+\)/g,
222
- category: 'xss',
223
- severity: 'critical',
224
- title: 'Code Injection via eval()',
225
- description: 'eval() executes arbitrary code and is a major security risk',
226
- owaspId: 'A03:2021',
227
- cweId: 'CWE-95',
228
- remediation: 'Never use eval(); use JSON.parse() for JSON data or safer alternatives',
229
- fixExample: 'JSON.parse(jsonString) // instead of eval(jsonString)',
230
- },
231
- {
232
- id: 'xss-new-function',
233
- pattern: /new\s+Function\s*\([^)]+\)/g,
234
- category: 'xss',
235
- severity: 'critical',
236
- title: 'Code Injection via Function Constructor',
237
- description: 'Function constructor can execute arbitrary code like eval()',
238
- owaspId: 'A03:2021',
239
- cweId: 'CWE-95',
240
- remediation: 'Avoid the Function constructor; use predefined functions instead',
241
- },
242
- {
243
- id: 'xss-outerhtml',
244
- pattern: /\.outerHTML\s*=\s*[^'"`;\n]+/g,
245
- category: 'xss',
246
- severity: 'high',
247
- title: 'XSS via outerHTML Assignment',
248
- description: 'Direct outerHTML assignment with potentially unsanitized content',
249
- owaspId: 'A03:2021',
250
- cweId: 'CWE-79',
251
- remediation: 'Sanitize content before outerHTML assignment',
252
- },
253
- ];
254
-
255
- /**
256
- * Hardcoded Secrets Detection Patterns
257
- * OWASP A02:2021 - Cryptographic Failures
258
- */
259
- const SECRET_PATTERNS: SecurityPattern[] = [
260
- {
261
- id: 'secret-aws-access-key',
262
- pattern: /['"`]AKIA[0-9A-Z]{16}['"`]/g,
263
- category: 'sensitive-data',
264
- severity: 'critical',
265
- title: 'AWS Access Key Detected',
266
- description: 'Hardcoded AWS Access Key ID found in source code',
267
- owaspId: 'A02:2021',
268
- cweId: 'CWE-798',
269
- remediation: 'Use environment variables or AWS Secrets Manager for credentials',
270
- fixExample: 'const accessKey = process.env.AWS_ACCESS_KEY_ID',
271
- },
272
- {
273
- id: 'secret-aws-secret-key',
274
- pattern: /['"`][A-Za-z0-9/+=]{40}['"`]/g,
275
- category: 'sensitive-data',
276
- severity: 'critical',
277
- title: 'Potential AWS Secret Key Detected',
278
- description: 'Potential hardcoded AWS Secret Access Key found',
279
- owaspId: 'A02:2021',
280
- cweId: 'CWE-798',
281
- remediation: 'Store secrets in environment variables or secrets manager',
282
- },
283
- {
284
- id: 'secret-openai-key',
285
- pattern: /['"`]sk-[a-zA-Z0-9]{48,}['"`]/g,
286
- category: 'sensitive-data',
287
- severity: 'critical',
288
- title: 'OpenAI API Key Detected',
289
- description: 'Hardcoded OpenAI API key found in source code',
290
- owaspId: 'A02:2021',
291
- cweId: 'CWE-798',
292
- remediation: 'Use environment variables for API keys',
293
- fixExample: 'const apiKey = process.env.OPENAI_API_KEY',
294
- },
295
- {
296
- id: 'secret-generic-password',
297
- pattern: /password\s*[:=]\s*['"`][^'"`]{4,}['"`]/gi,
298
- category: 'sensitive-data',
299
- severity: 'high',
300
- title: 'Hardcoded Password Detected',
301
- description: 'Hardcoded password found in source code',
302
- owaspId: 'A02:2021',
303
- cweId: 'CWE-798',
304
- remediation: 'Never hardcode passwords; use environment variables or secrets manager',
305
- fixExample: 'const password = process.env.DB_PASSWORD',
306
- },
307
- {
308
- id: 'secret-api-key',
309
- pattern: /api[_-]?key\s*[:=]\s*['"`][a-zA-Z0-9_\-]{16,}['"`]/gi,
310
- category: 'sensitive-data',
311
- severity: 'high',
312
- title: 'Hardcoded API Key Detected',
313
- description: 'Hardcoded API key found in source code',
314
- owaspId: 'A02:2021',
315
- cweId: 'CWE-798',
316
- remediation: 'Use environment variables for API keys',
317
- fixExample: 'const apiKey = process.env.API_KEY',
318
- },
319
- {
320
- id: 'secret-jwt',
321
- pattern: /['"`]eyJ[A-Za-z0-9_-]+\.eyJ[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+['"`]/g,
322
- category: 'sensitive-data',
323
- severity: 'high',
324
- title: 'Hardcoded JWT Token Detected',
325
- description: 'Hardcoded JWT token found in source code',
326
- owaspId: 'A02:2021',
327
- cweId: 'CWE-798',
328
- remediation: 'Generate JWT tokens dynamically; never hardcode them',
329
- },
330
- {
331
- id: 'secret-private-key',
332
- pattern: /-----BEGIN\s+(RSA|EC|OPENSSH|DSA)?\s*PRIVATE\s+KEY-----/g,
333
- category: 'sensitive-data',
334
- severity: 'critical',
335
- title: 'Private Key Detected',
336
- description: 'Private key found in source code',
337
- owaspId: 'A02:2021',
338
- cweId: 'CWE-798',
339
- remediation: 'Store private keys in secure key management systems, not in code',
340
- },
341
- {
342
- id: 'secret-github-token',
343
- pattern: /['"`]ghp_[a-zA-Z0-9]{36}['"`]|['"`]github_pat_[a-zA-Z0-9]{22}_[a-zA-Z0-9]{59}['"`]/g,
344
- category: 'sensitive-data',
345
- severity: 'critical',
346
- title: 'GitHub Token Detected',
347
- description: 'Hardcoded GitHub personal access token found',
348
- owaspId: 'A02:2021',
349
- cweId: 'CWE-798',
350
- remediation: 'Use environment variables or GitHub Actions secrets',
351
- },
352
- {
353
- id: 'secret-slack-token',
354
- pattern: /['"`]xox[baprs]-[0-9]{10,13}-[0-9]{10,13}[a-zA-Z0-9-]*['"`]/g,
355
- category: 'sensitive-data',
356
- severity: 'high',
357
- title: 'Slack Token Detected',
358
- description: 'Hardcoded Slack token found in source code',
359
- owaspId: 'A02:2021',
360
- cweId: 'CWE-798',
361
- remediation: 'Use environment variables for Slack tokens',
362
- },
363
- ];
364
-
365
- /**
366
- * Path Traversal Detection Patterns
367
- * OWASP A01:2021 - Broken Access Control
368
- */
369
- const PATH_TRAVERSAL_PATTERNS: SecurityPattern[] = [
370
- {
371
- id: 'path-traversal-readfile',
372
- pattern: /(?:readFile|readFileSync)\s*\([^)]*\+/g,
373
- category: 'access-control',
374
- severity: 'high',
375
- title: 'Path Traversal via File Read',
376
- description: 'File read operation with concatenated path may allow directory traversal',
377
- owaspId: 'A01:2021',
378
- cweId: 'CWE-22',
379
- remediation: 'Validate and sanitize file paths; use path.resolve() and check against base directory',
380
- fixExample: 'const safePath = path.resolve(baseDir, path.basename(userInput))',
381
- },
382
- {
383
- id: 'path-traversal-pattern',
384
- pattern: /\.\.\/.*\.\.\//g,
385
- category: 'access-control',
386
- severity: 'medium',
387
- title: 'Path Traversal Pattern Detected',
388
- description: 'Suspicious path traversal pattern (../) found in code',
389
- owaspId: 'A01:2021',
390
- cweId: 'CWE-22',
391
- remediation: 'Validate paths and ensure they resolve within expected directories',
392
- },
393
- {
394
- id: 'path-traversal-writefile',
395
- pattern: /(?:writeFile|writeFileSync)\s*\([^)]*\+/g,
396
- category: 'access-control',
397
- severity: 'high',
398
- title: 'Path Traversal via File Write',
399
- description: 'File write operation with concatenated path may allow directory traversal',
400
- owaspId: 'A01:2021',
401
- cweId: 'CWE-22',
402
- remediation: 'Validate file paths before writing; ensure path is within allowed directory',
403
- },
404
- {
405
- id: 'path-traversal-createstream',
406
- pattern: /createReadStream\s*\([^)]*\+/g,
407
- category: 'access-control',
408
- severity: 'high',
409
- title: 'Path Traversal via Stream',
410
- description: 'Stream creation with concatenated path may allow directory traversal',
411
- owaspId: 'A01:2021',
412
- cweId: 'CWE-22',
413
- remediation: 'Validate and sanitize file paths before creating streams',
414
- },
415
- ];
416
-
417
- /**
418
- * Command Injection Detection Patterns
419
- * OWASP A03:2021 - Injection
420
- */
421
- const COMMAND_INJECTION_PATTERNS: SecurityPattern[] = [
422
- {
423
- id: 'cmd-injection-exec',
424
- pattern: /exec\s*\([^)]*\+[^)]*\)|exec\s*\(\s*`[^`]*\$\{/g,
425
- category: 'injection',
426
- severity: 'critical',
427
- title: 'Command Injection via exec()',
428
- description: 'Shell command execution with unsanitized input',
429
- owaspId: 'A03:2021',
430
- cweId: 'CWE-78',
431
- remediation: 'Use execFile() with argument array instead of exec() with string concatenation',
432
- fixExample: 'execFile("command", [arg1, arg2], callback)',
433
- },
434
- {
435
- id: 'cmd-injection-spawn',
436
- pattern: /spawn\s*\(\s*[^,]+\+|spawn\s*\(\s*`[^`]*\$\{/g,
437
- category: 'injection',
438
- severity: 'critical',
439
- title: 'Command Injection via spawn()',
440
- description: 'Process spawn with potentially unsanitized command',
441
- owaspId: 'A03:2021',
442
- cweId: 'CWE-78',
443
- remediation: 'Use spawn with command and args array; validate inputs',
444
- fixExample: 'spawn("command", [sanitizedArg1, sanitizedArg2])',
445
- },
446
- {
447
- id: 'cmd-injection-shell-true',
448
- pattern: /spawn\s*\([^)]+,\s*\{[^}]*shell\s*:\s*true/g,
449
- category: 'injection',
450
- severity: 'high',
451
- title: 'Dangerous Shell Option in spawn()',
452
- description: 'spawn() with shell: true can enable command injection',
453
- owaspId: 'A03:2021',
454
- cweId: 'CWE-78',
455
- remediation: 'Avoid shell: true option; use direct command execution',
456
- },
457
- ];
458
-
459
- /**
460
- * Insecure Configuration Detection Patterns
461
- * OWASP A05:2021 - Security Misconfiguration
462
- */
463
- const MISCONFIGURATION_PATTERNS: SecurityPattern[] = [
464
- {
465
- id: 'misc-cors-wildcard',
466
- pattern: /cors\s*\(\s*\{[^}]*origin\s*:\s*['"]\*['"]/gi,
467
- category: 'security-misconfiguration',
468
- severity: 'medium',
469
- title: 'Permissive CORS Configuration',
470
- description: 'CORS allows all origins (*) which may expose sensitive data',
471
- owaspId: 'A05:2021',
472
- cweId: 'CWE-942',
473
- remediation: 'Restrict CORS to specific trusted origins',
474
- fixExample: 'cors({ origin: ["https://trusted-domain.com"] })',
475
- },
476
- {
477
- id: 'misc-debug-enabled',
478
- pattern: /debug\s*[:=]\s*true|DEBUG\s*[:=]\s*['"]?true['"]?/gi,
479
- category: 'security-misconfiguration',
480
- severity: 'low',
481
- title: 'Debug Mode Enabled',
482
- description: 'Debug mode may expose sensitive information in production',
483
- owaspId: 'A05:2021',
484
- cweId: 'CWE-489',
485
- remediation: 'Disable debug mode in production environments',
486
- },
487
- {
488
- id: 'misc-ssl-disabled',
489
- pattern: /rejectUnauthorized\s*:\s*false|NODE_TLS_REJECT_UNAUTHORIZED\s*=\s*['"]?0['"]?/g,
490
- category: 'security-misconfiguration',
491
- severity: 'high',
492
- title: 'TLS Certificate Validation Disabled',
493
- description: 'Disabling TLS certificate validation exposes to MITM attacks',
494
- owaspId: 'A05:2021',
495
- cweId: 'CWE-295',
496
- remediation: 'Always enable TLS certificate validation in production',
497
- },
498
- {
499
- id: 'misc-helmet-missing',
500
- pattern: /app\.use\s*\(\s*express\s*\(\s*\)\s*\)/g,
501
- category: 'security-misconfiguration',
502
- severity: 'low',
503
- title: 'Express App Without Security Headers',
504
- description: 'Express app initialized without helmet or security headers',
505
- owaspId: 'A05:2021',
506
- cweId: 'CWE-693',
507
- remediation: 'Use helmet middleware for security headers',
508
- fixExample: 'app.use(helmet())',
509
- },
510
- ];
511
-
512
- /**
513
- * Insecure Deserialization Patterns
514
- * OWASP A08:2021 - Software and Data Integrity Failures
515
- */
516
- const DESERIALIZATION_PATTERNS: SecurityPattern[] = [
517
- {
518
- id: 'deser-yaml-load',
519
- pattern: /yaml\.load\s*\([^)]+\)/g,
520
- category: 'insecure-deserialization',
521
- severity: 'high',
522
- title: 'Unsafe YAML Deserialization',
523
- description: 'yaml.load() can execute arbitrary code from untrusted YAML',
524
- owaspId: 'A08:2021',
525
- cweId: 'CWE-502',
526
- remediation: 'Use yaml.safeLoad() or schema-constrained loading',
527
- fixExample: 'yaml.load(content, { schema: yaml.SAFE_SCHEMA })',
528
- },
529
- {
530
- id: 'deser-serialize-js',
531
- pattern: /serialize\s*\([^)]+\)|unserialize\s*\([^)]+\)/g,
532
- category: 'insecure-deserialization',
533
- severity: 'high',
534
- title: 'Unsafe Serialization Function',
535
- description: 'Node serialize/unserialize functions can execute arbitrary code',
536
- owaspId: 'A08:2021',
537
- cweId: 'CWE-502',
538
- remediation: 'Use JSON.parse/stringify for serialization',
539
- },
540
- ];
541
-
542
- /**
543
- * Authentication Weakness Patterns
544
- * OWASP A07:2021 - Identification and Authentication Failures
545
- */
546
- const AUTH_PATTERNS: SecurityPattern[] = [
547
- {
548
- id: 'auth-weak-jwt-secret',
549
- pattern: /jwt\.sign\s*\([^)]+,\s*['"][a-zA-Z0-9]{1,16}['"]/g,
550
- category: 'broken-auth',
551
- severity: 'high',
552
- title: 'Weak JWT Secret',
553
- description: 'JWT signed with a weak or short secret key',
554
- owaspId: 'A07:2021',
555
- cweId: 'CWE-327',
556
- remediation: 'Use a strong, randomly generated secret of at least 256 bits',
557
- },
558
- {
559
- id: 'auth-no-algorithm',
560
- pattern: /jwt\.verify\s*\([^)]+\)\s*(?!.*algorithm)/g,
561
- category: 'broken-auth',
562
- severity: 'medium',
563
- title: 'JWT Without Algorithm Specification',
564
- description: 'JWT verification without explicit algorithm can be exploited',
565
- owaspId: 'A07:2021',
566
- cweId: 'CWE-347',
567
- remediation: 'Always specify the expected algorithm in JWT verification',
568
- fixExample: 'jwt.verify(token, secret, { algorithms: ["HS256"] })',
569
- },
570
- ];
571
-
572
- /**
573
- * All security patterns combined by category for rule set application
574
- */
575
- const ALL_SECURITY_PATTERNS: SecurityPattern[] = [
576
- ...SQL_INJECTION_PATTERNS,
577
- ...XSS_PATTERNS,
578
- ...SECRET_PATTERNS,
579
- ...PATH_TRAVERSAL_PATTERNS,
580
- ...COMMAND_INJECTION_PATTERNS,
581
- ...MISCONFIGURATION_PATTERNS,
582
- ...DESERIALIZATION_PATTERNS,
583
- ...AUTH_PATTERNS,
584
- ];
585
-
586
- // ============================================================================
587
- // Built-in Rule Sets
588
- // ============================================================================
589
-
590
- const BUILT_IN_RULE_SETS: RuleSet[] = [
591
- {
592
- id: 'owasp-top-10',
593
- name: 'OWASP Top 10',
594
- description: 'OWASP Top 10 most critical security risks',
595
- ruleCount: 45,
596
- categories: [
597
- 'injection',
598
- 'broken-auth',
599
- 'sensitive-data',
600
- 'xxe',
601
- 'access-control',
602
- 'security-misconfiguration',
603
- 'xss',
604
- 'insecure-deserialization',
605
- 'vulnerable-components',
606
- 'insufficient-logging',
607
- ],
608
- },
609
- {
610
- id: 'cwe-sans-25',
611
- name: 'CWE/SANS Top 25',
612
- description: 'Most dangerous software errors',
613
- ruleCount: 38,
614
- categories: [
615
- 'injection',
616
- 'xss',
617
- 'access-control',
618
- 'sensitive-data',
619
- 'broken-auth',
620
- ],
621
- },
622
- {
623
- id: 'nodejs-security',
624
- name: 'Node.js Security',
625
- description: 'Node.js specific security rules',
626
- ruleCount: 25,
627
- categories: ['injection', 'xss', 'sensitive-data', 'security-misconfiguration'],
628
- },
629
- {
630
- id: 'typescript-security',
631
- name: 'TypeScript Security',
632
- description: 'TypeScript specific security rules',
633
- ruleCount: 20,
634
- categories: ['injection', 'xss', 'sensitive-data'],
635
- },
636
- ];
637
-
638
- // ============================================================================
639
- // Mutable Summary Type for Internal Use
640
- // ============================================================================
641
-
642
- interface MutableScanSummary {
643
- critical: number;
644
- high: number;
645
- medium: number;
646
- low: number;
647
- informational: number;
648
- totalFiles: number;
649
- scanDurationMs: number;
650
- }
651
-
652
- // ============================================================================
653
- // Security Scanner Service Implementation
654
- // ============================================================================
655
-
656
- export class SecurityScannerService implements ISecurityScannerService {
657
- private readonly config: SecurityScannerConfig;
658
- private readonly activeScans: Map<string, ScanStatus> = new Map();
659
- private readonly osvClient: OSVClient;
660
-
661
- constructor(
662
- private readonly memory: MemoryBackend,
663
- config: Partial<SecurityScannerConfig> = {}
664
- ) {
665
- this.config = { ...DEFAULT_CONFIG, ...config };
666
- this.osvClient = new OSVClient({ enableCache: true });
667
- }
668
-
669
- // ==========================================================================
670
- // SAST Methods
671
- // ==========================================================================
672
-
673
- /**
674
- * Scan files for security vulnerabilities using static analysis
675
- */
676
- async scanFiles(files: FilePath[]): Promise<Result<SASTResult>> {
677
- return this.scanWithRules(files, this.config.defaultRuleSets);
678
- }
679
-
680
- /**
681
- * Scan with specific rule sets
682
- */
683
- async scanWithRules(
684
- files: FilePath[],
685
- ruleSetIds: string[]
686
- ): Promise<Result<SASTResult>> {
687
- const scanId = uuidv4();
688
-
689
- try {
690
- if (files.length === 0) {
691
- return err(new Error('No files provided for scanning'));
692
- }
693
-
694
- this.activeScans.set(scanId, 'running');
695
- const startTime = Date.now();
696
-
697
- // Get applicable rule sets
698
- const ruleSets = BUILT_IN_RULE_SETS.filter((rs) =>
699
- ruleSetIds.includes(rs.id)
700
- );
701
-
702
- if (ruleSets.length === 0) {
703
- return err(new Error(`No valid rule sets found: ${ruleSetIds.join(', ')}`));
704
- }
705
-
706
- // Perform static analysis on each file
707
- const vulnerabilities: Vulnerability[] = [];
708
- let linesScanned = 0;
709
-
710
- for (const file of files) {
711
- const fileVulns = await this.analyzeFile(file, ruleSets);
712
- vulnerabilities.push(...fileVulns.vulnerabilities);
713
- linesScanned += fileVulns.linesScanned;
714
- }
715
-
716
- const scanDurationMs = Date.now() - startTime;
717
-
718
- // Calculate summary
719
- const summary = this.calculateSummary(
720
- vulnerabilities,
721
- files.length,
722
- scanDurationMs
723
- );
724
-
725
- // Calculate coverage
726
- const coverage: SecurityCoverage = {
727
- filesScanned: files.length,
728
- linesScanned,
729
- rulesApplied: ruleSets.reduce((acc, rs) => acc + rs.ruleCount, 0),
730
- };
731
-
732
- // Store scan results in memory
733
- await this.storeScanResults(scanId, 'sast', vulnerabilities, summary);
734
-
735
- this.activeScans.set(scanId, 'completed');
736
-
737
- return ok({
738
- scanId,
739
- vulnerabilities,
740
- summary,
741
- coverage,
742
- });
743
- } catch (error) {
744
- this.activeScans.set(scanId, 'failed');
745
- return err(error instanceof Error ? error : new Error(String(error)));
746
- }
747
- }
748
-
749
- /**
750
- * Get available rule sets
751
- */
752
- async getAvailableRuleSets(): Promise<RuleSet[]> {
753
- // Return built-in rule sets plus any custom ones from memory
754
- const customRuleSets = await this.memory.get<RuleSet[]>(
755
- 'security:custom-rule-sets'
756
- );
757
-
758
- return [...BUILT_IN_RULE_SETS, ...(customRuleSets || [])];
759
- }
760
-
761
- /**
762
- * Check if vulnerability is a false positive
763
- */
764
- async checkFalsePositive(
765
- vulnerability: Vulnerability
766
- ): Promise<Result<FalsePositiveCheck>> {
767
- try {
768
- if (!this.config.enableFalsePositiveDetection) {
769
- return ok({
770
- isFalsePositive: false,
771
- confidence: 0,
772
- reason: 'False positive detection is disabled',
773
- });
774
- }
775
-
776
- // Analyze vulnerability using heuristics-based false positive detection
777
- const analysis = await this.analyzeFalsePositive(vulnerability);
778
-
779
- // Store the check result for learning
780
- await this.memory.set(
781
- `security:fp-check:${vulnerability.id}`,
782
- { vulnerability, analysis },
783
- { namespace: 'security-compliance', ttl: 86400 * 30 } // 30 days
784
- );
785
-
786
- return ok(analysis);
787
- } catch (error) {
788
- return err(error instanceof Error ? error : new Error(String(error)));
789
- }
790
- }
791
-
792
- // ==========================================================================
793
- // DAST Methods
794
- // ==========================================================================
795
-
796
- /**
797
- * Scan running application using dynamic analysis
798
- */
799
- async scanUrl(
800
- targetUrl: string,
801
- options?: DASTOptions
802
- ): Promise<Result<DASTResult>> {
803
- const scanId = uuidv4();
804
-
805
- try {
806
- this.activeScans.set(scanId, 'running');
807
- const startTime = Date.now();
808
-
809
- const mergedOptions: DASTOptions = {
810
- maxDepth: options?.maxDepth ?? this.config.dastMaxDepth,
811
- activeScanning: options?.activeScanning ?? this.config.dastActiveScanning,
812
- timeout: options?.timeout ?? this.config.timeout,
813
- excludePatterns: options?.excludePatterns ?? [],
814
- };
815
-
816
- // Perform dynamic analysis
817
- const result = await this.performDynamicScan(targetUrl, mergedOptions);
818
-
819
- const scanDurationMs = Date.now() - startTime;
820
-
821
- const summary = this.calculateSummary(
822
- result.vulnerabilities,
823
- 1,
824
- scanDurationMs
825
- );
826
-
827
- // Store results
828
- await this.storeScanResults(scanId, 'dast', result.vulnerabilities, summary);
829
-
830
- this.activeScans.set(scanId, 'completed');
831
-
832
- return ok({
833
- scanId,
834
- targetUrl,
835
- vulnerabilities: result.vulnerabilities,
836
- summary,
837
- crawledUrls: result.crawledUrls,
838
- });
839
- } catch (error) {
840
- this.activeScans.set(scanId, 'failed');
841
- return err(error instanceof Error ? error : new Error(String(error)));
842
- }
843
- }
844
-
845
- /**
846
- * Scan authenticated endpoints
847
- */
848
- async scanAuthenticated(
849
- targetUrl: string,
850
- credentials: AuthCredentials,
851
- options?: DASTOptions
852
- ): Promise<Result<DASTResult>> {
853
- const scanId = uuidv4();
854
-
855
- try {
856
- this.activeScans.set(scanId, 'running');
857
- const startTime = Date.now();
858
-
859
- // Validate credentials
860
- const credValidation = this.validateCredentials(credentials);
861
- if (!credValidation.valid) {
862
- return err(new Error(credValidation.reason));
863
- }
864
-
865
- const mergedOptions: DASTOptions = {
866
- maxDepth: options?.maxDepth ?? this.config.dastMaxDepth,
867
- activeScanning: options?.activeScanning ?? this.config.dastActiveScanning,
868
- timeout: options?.timeout ?? this.config.timeout,
869
- excludePatterns: options?.excludePatterns ?? [],
870
- };
871
-
872
- // Perform authenticated dynamic analysis
873
- const result = await this.performAuthenticatedScan(
874
- targetUrl,
875
- credentials,
876
- mergedOptions
877
- );
878
-
879
- const scanDurationMs = Date.now() - startTime;
880
-
881
- const summary = this.calculateSummary(
882
- result.vulnerabilities,
883
- 1,
884
- scanDurationMs
885
- );
886
-
887
- // Store results (without credentials)
888
- await this.storeScanResults(scanId, 'dast-auth', result.vulnerabilities, summary);
889
-
890
- this.activeScans.set(scanId, 'completed');
891
-
892
- return ok({
893
- scanId,
894
- targetUrl,
895
- vulnerabilities: result.vulnerabilities,
896
- summary,
897
- crawledUrls: result.crawledUrls,
898
- });
899
- } catch (error) {
900
- this.activeScans.set(scanId, 'failed');
901
- return err(error instanceof Error ? error : new Error(String(error)));
902
- }
903
- }
904
-
905
- /**
906
- * Get scan status
907
- */
908
- async getScanStatus(scanId: string): Promise<ScanStatus> {
909
- return this.activeScans.get(scanId) ?? 'pending';
910
- }
911
-
912
- // ==========================================================================
913
- // Combined Scanning
914
- // ==========================================================================
915
-
916
- /**
917
- * Run combined SAST and DAST scan
918
- */
919
- async runFullScan(
920
- files: FilePath[],
921
- targetUrl?: string,
922
- options?: DASTOptions
923
- ): Promise<Result<FullScanResult>> {
924
- try {
925
- // Run SAST scan
926
- const sastResult = await this.scanWithRules(files, this.config.defaultRuleSets);
927
- if (sastResult.success === false) {
928
- return err(sastResult.error);
929
- }
930
-
931
- // Run DAST scan if target URL provided
932
- let dastResult: DASTResult | undefined;
933
- if (targetUrl) {
934
- const dastScan = await this.scanUrl(targetUrl, options);
935
- if (dastScan.success) {
936
- dastResult = dastScan.value;
937
- }
938
- // Don't fail the full scan if DAST fails
939
- }
940
-
941
- // Combine summaries
942
- const combinedSummary = this.combineSummaries(
943
- sastResult.value.summary,
944
- dastResult?.summary
945
- );
946
-
947
- return ok({
948
- sastResult: sastResult.value,
949
- dastResult,
950
- combinedSummary,
951
- });
952
- } catch (error) {
953
- return err(error instanceof Error ? error : new Error(String(error)));
954
- }
955
- }
956
-
957
- // ==========================================================================
958
- // Private Helper Methods
959
- // ==========================================================================
960
-
961
- /**
962
- * Analyze a file for security vulnerabilities using pattern-based detection
963
- */
964
- private async analyzeFile(
965
- file: FilePath,
966
- ruleSets: RuleSet[]
967
- ): Promise<{ vulnerabilities: Vulnerability[]; linesScanned: number }> {
968
- const vulnerabilities: Vulnerability[] = [];
969
- const filePath = file.value;
970
- const extension = file.extension;
971
-
972
- // Read file content
973
- let content: string;
974
- let lines: string[];
975
- try {
976
- const fs = await import('fs/promises');
977
- content = await fs.readFile(filePath, 'utf-8');
978
- lines = content.split('\n');
979
- } catch (error) {
980
- // File not accessible - return empty results
981
- return { vulnerabilities: [], linesScanned: 0 };
982
- }
983
-
984
- const linesScanned = lines.length;
985
-
986
- // Only scan supported file types
987
- const supportedExtensions = ['ts', 'tsx', 'js', 'jsx', 'mjs', 'cjs'];
988
- if (!supportedExtensions.includes(extension)) {
989
- return { vulnerabilities: [], linesScanned };
990
- }
991
-
992
- // Get applicable categories from rule sets
993
- const applicableCategories = new Set(ruleSets.flatMap((rs) => rs.categories));
994
-
995
- // Filter patterns to only those matching applicable categories
996
- const applicablePatterns = ALL_SECURITY_PATTERNS.filter((pattern) =>
997
- applicableCategories.has(pattern.category)
998
- );
999
-
1000
- // Scan content for each pattern
1001
- for (const securityPattern of applicablePatterns) {
1002
- const matches = this.findPatternMatches(content, lines, securityPattern);
1003
- for (const match of matches) {
1004
- // Skip if in comments or string that looks like documentation
1005
- if (this.isInComment(content, match.index) || this.isInDocumentation(match.snippet)) {
1006
- continue;
1007
- }
1008
-
1009
- // Skip nosec annotations
1010
- if (this.hasNosecAnnotation(lines, match.line)) {
1011
- continue;
1012
- }
1013
-
1014
- vulnerabilities.push(
1015
- this.createVulnerabilityFromPattern(securityPattern, filePath, match)
1016
- );
1017
- }
1018
- }
1019
-
1020
- return { vulnerabilities, linesScanned };
1021
- }
1022
-
1023
- /**
1024
- * Find all matches of a security pattern in the file content
1025
- */
1026
- private findPatternMatches(
1027
- content: string,
1028
- lines: string[],
1029
- securityPattern: SecurityPattern
1030
- ): Array<{ index: number; line: number; column: number; snippet: string }> {
1031
- const matches: Array<{ index: number; line: number; column: number; snippet: string }> = [];
1032
-
1033
- // Reset regex state for global patterns
1034
- const pattern = new RegExp(securityPattern.pattern.source, securityPattern.pattern.flags);
1035
-
1036
- let match: RegExpExecArray | null;
1037
- while ((match = pattern.exec(content)) !== null) {
1038
- const index = match.index;
1039
- const { line, column } = this.getLineAndColumn(content, index);
1040
-
1041
- // Extract snippet with context (the matched line plus surrounding context)
1042
- const snippetLines: string[] = [];
1043
- const startLine = Math.max(0, line - 2);
1044
- const endLine = Math.min(lines.length - 1, line + 1);
1045
- for (let i = startLine; i <= endLine; i++) {
1046
- snippetLines.push(lines[i]);
1047
- }
1048
- const snippet = snippetLines.join('\n');
1049
-
1050
- matches.push({ index, line: line + 1, column: column + 1, snippet }); // 1-indexed
1051
- }
1052
-
1053
- return matches;
1054
- }
1055
-
1056
- /**
1057
- * Convert character index to line and column numbers
1058
- */
1059
- private getLineAndColumn(content: string, index: number): { line: number; column: number } {
1060
- const beforeMatch = content.substring(0, index);
1061
- const lines = beforeMatch.split('\n');
1062
- const line = lines.length - 1;
1063
- const column = lines[lines.length - 1].length;
1064
- return { line, column };
1065
- }
1066
-
1067
- /**
1068
- * Check if the match is inside a comment
1069
- */
1070
- private isInComment(content: string, index: number): boolean {
1071
- const beforeMatch = content.substring(0, index);
1072
-
1073
- // Check for single-line comment
1074
- const lastNewline = beforeMatch.lastIndexOf('\n');
1075
- const currentLine = beforeMatch.substring(lastNewline + 1);
1076
- if (currentLine.includes('//')) {
1077
- const commentStart = currentLine.indexOf('//');
1078
- if (index - (beforeMatch.length - currentLine.length) > commentStart) {
1079
- return true;
1080
- }
1081
- }
1082
-
1083
- // Check for multi-line comment
1084
- const lastBlockCommentStart = beforeMatch.lastIndexOf('/*');
1085
- const lastBlockCommentEnd = beforeMatch.lastIndexOf('*/');
1086
- if (lastBlockCommentStart > lastBlockCommentEnd) {
1087
- return true;
1088
- }
1089
-
1090
- return false;
1091
- }
1092
-
1093
- /**
1094
- * Check if the snippet appears to be in documentation or test code examples
1095
- */
1096
- private isInDocumentation(snippet: string): boolean {
1097
- const docPatterns = [
1098
- /\*\s*@example/i,
1099
- /\*\s*@description/i,
1100
- /\/\/\s*example:/i,
1101
- /\/\/\s*e\.g\./i,
1102
- /```[\s\S]*```/,
1103
- ];
1104
- return docPatterns.some((pattern) => pattern.test(snippet));
1105
- }
1106
-
1107
- /**
1108
- * Check if the line has a nosec annotation
1109
- */
1110
- private hasNosecAnnotation(lines: string[], lineNumber: number): boolean {
1111
- const lineIndex = lineNumber - 1;
1112
- if (lineIndex < 0 || lineIndex >= lines.length) {
1113
- return false;
1114
- }
1115
-
1116
- const currentLine = lines[lineIndex];
1117
- const previousLine = lineIndex > 0 ? lines[lineIndex - 1] : '';
1118
-
1119
- const nosecPatterns = [
1120
- /\/\/\s*nosec/i,
1121
- /\/\/\s*security-ignore/i,
1122
- /\/\*\s*nosec\s*\*\//i,
1123
- /#\s*nosec/i,
1124
- ];
1125
-
1126
- return nosecPatterns.some(
1127
- (pattern) => pattern.test(currentLine) || pattern.test(previousLine)
1128
- );
1129
- }
1130
-
1131
- /**
1132
- * Create a Vulnerability object from a pattern match
1133
- */
1134
- private createVulnerabilityFromPattern(
1135
- pattern: SecurityPattern,
1136
- file: string,
1137
- match: { line: number; column: number; snippet: string }
1138
- ): Vulnerability {
1139
- const location: VulnerabilityLocation = {
1140
- file,
1141
- line: match.line,
1142
- column: match.column,
1143
- snippet: match.snippet,
1144
- };
1145
-
1146
- const remediation: RemediationAdvice = {
1147
- description: pattern.remediation,
1148
- fixExample: pattern.fixExample,
1149
- estimatedEffort: this.getEffortForSeverity(pattern.severity),
1150
- automatable: pattern.severity === 'low' || pattern.severity === 'informational',
1151
- };
1152
-
1153
- return {
1154
- id: uuidv4(),
1155
- cveId: undefined,
1156
- title: pattern.title,
1157
- description: `${pattern.description} [${pattern.cweId}]`,
1158
- severity: pattern.severity,
1159
- category: pattern.category,
1160
- location,
1161
- remediation,
1162
- references: [
1163
- `https://owasp.org/Top10/${pattern.owaspId.replace(':', '_')}/`,
1164
- `https://cwe.mitre.org/data/definitions/${pattern.cweId.replace('CWE-', '')}.html`,
1165
- ],
1166
- };
1167
- }
1168
-
1169
- private getEffortForSeverity(
1170
- severity: VulnerabilitySeverity
1171
- ): RemediationAdvice['estimatedEffort'] {
1172
- const efforts: Record<VulnerabilitySeverity, RemediationAdvice['estimatedEffort']> = {
1173
- critical: 'major',
1174
- high: 'moderate',
1175
- medium: 'minor',
1176
- low: 'trivial',
1177
- informational: 'trivial',
1178
- };
1179
- return efforts[severity];
1180
- }
1181
-
1182
- /**
1183
- * Perform dynamic (DAST) scanning on a target URL
1184
- * Makes actual HTTP requests to detect security vulnerabilities
1185
- *
1186
- * **Capabilities:**
1187
- * - Security header analysis (HSTS, CSP, X-Frame-Options, etc.)
1188
- * - Cookie security (Secure, HttpOnly, SameSite flags)
1189
- * - CORS misconfiguration detection
1190
- * - Sensitive file exposure (/.git, /.env, etc.)
1191
- * - Link crawling with same-origin scope
1192
- * - XSS reflection testing (GET parameters)
1193
- * - SQL injection error-based detection (GET parameters)
1194
- * - Form security analysis (CSRF tokens, autocomplete, action URLs)
1195
- *
1196
- * **Limitations:**
1197
- * - Injection testing: GET parameters only (POST form submission not implemented)
1198
- * - Crawling: Same-origin only, max 10 links per page, single depth
1199
- * - Auth flows: Header-based only, no login form automation
1200
- * - No JavaScript execution (static response analysis only)
1201
- * - No session management testing beyond cookie attributes
1202
- */
1203
- private async performDynamicScan(
1204
- targetUrl: string,
1205
- options: DASTOptions
1206
- ): Promise<{ vulnerabilities: Vulnerability[]; crawledUrls: number }> {
1207
- const vulnerabilities: Vulnerability[] = [];
1208
- let crawledUrls = 0;
1209
-
1210
- try {
1211
- // Validate and parse URL
1212
- let parsedUrl: URL;
1213
- try {
1214
- parsedUrl = new URL(targetUrl);
1215
- } catch {
1216
- // Invalid URL - return informational finding
1217
- vulnerabilities.push({
1218
- id: uuidv4(),
1219
- title: 'Invalid Target URL',
1220
- description: 'The provided target URL is not valid',
1221
- severity: 'informational',
1222
- category: 'security-misconfiguration',
1223
- location: { file: targetUrl },
1224
- remediation: { description: 'Provide a valid URL', estimatedEffort: 'trivial', automatable: false },
1225
- references: [],
1226
- });
1227
- return { vulnerabilities, crawledUrls: 0 };
1228
- }
1229
-
1230
- const timeout = options.timeout ?? this.config.timeout;
1231
- const maxDepth = options.maxDepth ?? this.config.dastMaxDepth;
1232
-
1233
- // Perform main page scan
1234
- const controller = new AbortController();
1235
- const timeoutId = setTimeout(() => controller.abort(), Math.min(timeout, 30000));
1236
-
1237
- try {
1238
- const response = await fetch(targetUrl, {
1239
- method: 'GET',
1240
- headers: {
1241
- 'User-Agent': 'AgenticQE-DAST-Scanner/3.0',
1242
- 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
1243
- },
1244
- signal: controller.signal,
1245
- redirect: 'follow',
1246
- });
1247
-
1248
- clearTimeout(timeoutId);
1249
- crawledUrls++;
1250
-
1251
- // Security header analysis
1252
- const headers = response.headers;
1253
-
1254
- // Check for missing security headers
1255
- const headerChecks = [
1256
- { header: 'strict-transport-security', title: 'Missing HSTS Header', severity: 'medium' as VulnerabilitySeverity, remediation: 'Add Strict-Transport-Security header' },
1257
- { header: 'x-content-type-options', title: 'Missing X-Content-Type-Options', severity: 'low' as VulnerabilitySeverity, remediation: 'Add X-Content-Type-Options: nosniff' },
1258
- { header: 'x-frame-options', title: 'Missing X-Frame-Options', severity: 'medium' as VulnerabilitySeverity, remediation: 'Add X-Frame-Options: DENY or SAMEORIGIN' },
1259
- { header: 'content-security-policy', title: 'Missing Content-Security-Policy', severity: 'medium' as VulnerabilitySeverity, remediation: 'Implement a Content-Security-Policy' },
1260
- { header: 'referrer-policy', title: 'Missing Referrer-Policy', severity: 'low' as VulnerabilitySeverity, remediation: 'Add Referrer-Policy header' },
1261
- { header: 'permissions-policy', title: 'Missing Permissions-Policy', severity: 'low' as VulnerabilitySeverity, remediation: 'Add Permissions-Policy header' },
1262
- ];
1263
-
1264
- for (const check of headerChecks) {
1265
- if (!headers.get(check.header)) {
1266
- vulnerabilities.push({
1267
- id: uuidv4(),
1268
- title: check.title,
1269
- description: `Security header ${check.header} is not present in the response`,
1270
- severity: check.severity,
1271
- category: 'security-misconfiguration',
1272
- location: { file: targetUrl, snippet: `Missing: ${check.header}` },
1273
- remediation: { description: check.remediation, estimatedEffort: 'minor', automatable: true },
1274
- references: ['https://owasp.org/www-project-secure-headers/'],
1275
- });
1276
- }
1277
- }
1278
-
1279
- // Check for insecure protocol
1280
- if (parsedUrl.protocol === 'http:') {
1281
- vulnerabilities.push({
1282
- id: uuidv4(),
1283
- title: 'Insecure HTTP Protocol',
1284
- description: 'Application is accessible over unencrypted HTTP',
1285
- severity: 'high',
1286
- category: 'sensitive-data',
1287
- location: { file: targetUrl },
1288
- remediation: { description: 'Redirect all HTTP traffic to HTTPS', estimatedEffort: 'moderate', automatable: false },
1289
- references: ['https://owasp.org/www-project-web-security-testing-guide/'],
1290
- });
1291
- }
1292
-
1293
- // Check for cookie security
1294
- const setCookie = headers.get('set-cookie');
1295
- if (setCookie) {
1296
- const cookieLower = setCookie.toLowerCase();
1297
- if (!cookieLower.includes('secure')) {
1298
- vulnerabilities.push({
1299
- id: uuidv4(),
1300
- title: 'Cookie Missing Secure Flag',
1301
- description: 'Cookie is set without the Secure attribute',
1302
- severity: 'medium',
1303
- category: 'sensitive-data',
1304
- location: { file: targetUrl, snippet: `Set-Cookie header without Secure flag` },
1305
- remediation: { description: 'Add Secure flag to all cookies', estimatedEffort: 'trivial', automatable: true },
1306
- references: ['https://owasp.org/www-community/controls/SecureCookieAttribute'],
1307
- });
1308
- }
1309
- if (!cookieLower.includes('httponly')) {
1310
- vulnerabilities.push({
1311
- id: uuidv4(),
1312
- title: 'Cookie Missing HttpOnly Flag',
1313
- description: 'Cookie is accessible to client-side JavaScript',
1314
- severity: 'medium',
1315
- category: 'sensitive-data',
1316
- location: { file: targetUrl, snippet: `Set-Cookie header without HttpOnly flag` },
1317
- remediation: { description: 'Add HttpOnly flag to session cookies', estimatedEffort: 'trivial', automatable: true },
1318
- references: ['https://owasp.org/www-community/HttpOnly'],
1319
- });
1320
- }
1321
- }
1322
-
1323
- // Check for server version disclosure
1324
- const serverHeader = headers.get('server') || headers.get('x-powered-by');
1325
- if (serverHeader && /\d+\.\d+/.test(serverHeader)) {
1326
- vulnerabilities.push({
1327
- id: uuidv4(),
1328
- title: 'Server Version Disclosure',
1329
- description: `Server version information exposed: ${serverHeader}`,
1330
- severity: 'low',
1331
- category: 'security-misconfiguration',
1332
- location: { file: targetUrl, snippet: `Server: ${serverHeader}` },
1333
- remediation: { description: 'Remove or obfuscate server version headers', estimatedEffort: 'trivial', automatable: true },
1334
- references: ['https://owasp.org/www-project-web-security-testing-guide/'],
1335
- });
1336
- }
1337
-
1338
- // Scan for sensitive file exposure (only if active scanning is enabled)
1339
- if (options.activeScanning ?? this.config.dastActiveScanning) {
1340
- const sensitiveEndpoints = [
1341
- { path: '/.git/config', name: 'Git Configuration' },
1342
- { path: '/.env', name: 'Environment File' },
1343
- { path: '/robots.txt', name: 'Robots.txt' },
1344
- { path: '/sitemap.xml', name: 'Sitemap' },
1345
- { path: '/.htaccess', name: 'htaccess File' },
1346
- { path: '/web.config', name: 'IIS Configuration' },
1347
- ];
1348
-
1349
- for (const endpoint of sensitiveEndpoints) {
1350
- if (crawledUrls >= maxDepth * 10) break; // Limit crawling
1351
-
1352
- try {
1353
- const testUrl = new URL(endpoint.path, parsedUrl.origin).toString();
1354
- const testResponse = await fetch(testUrl, {
1355
- method: 'GET',
1356
- signal: AbortSignal.timeout(5000),
1357
- });
1358
-
1359
- if (testResponse.ok) {
1360
- crawledUrls++;
1361
- const contentType = testResponse.headers.get('content-type') || '';
1362
- const text = await testResponse.text();
1363
-
1364
- // Verify it's not a custom 404 page
1365
- if (text.length > 20 && !text.toLowerCase().includes('not found') && !text.toLowerCase().includes('404')) {
1366
- // Check for sensitive content markers
1367
- const isSensitive =
1368
- endpoint.path.includes('.git') ||
1369
- endpoint.path.includes('.env') ||
1370
- endpoint.path.includes('.htaccess') ||
1371
- endpoint.path.includes('web.config');
1372
-
1373
- if (isSensitive) {
1374
- vulnerabilities.push({
1375
- id: uuidv4(),
1376
- title: `Sensitive File Exposed: ${endpoint.name}`,
1377
- description: `${endpoint.name} is publicly accessible`,
1378
- severity: endpoint.path.includes('.git') || endpoint.path.includes('.env') ? 'high' : 'medium',
1379
- category: 'sensitive-data',
1380
- location: { file: testUrl },
1381
- remediation: { description: `Restrict access to ${endpoint.path}`, estimatedEffort: 'trivial', automatable: true },
1382
- references: ['https://owasp.org/www-project-web-security-testing-guide/'],
1383
- });
1384
- }
1385
- }
1386
- }
1387
- } catch {
1388
- // File not accessible - this is expected/good
1389
- }
1390
- }
1391
- }
1392
-
1393
- // CORS analysis
1394
- try {
1395
- const corsResponse = await fetch(targetUrl, {
1396
- method: 'OPTIONS',
1397
- headers: {
1398
- 'Origin': 'https://evil-attacker.com',
1399
- 'Access-Control-Request-Method': 'GET',
1400
- },
1401
- signal: AbortSignal.timeout(5000),
1402
- });
1403
-
1404
- const allowOrigin = corsResponse.headers.get('access-control-allow-origin');
1405
- if (allowOrigin === '*' || allowOrigin === 'https://evil-attacker.com') {
1406
- vulnerabilities.push({
1407
- id: uuidv4(),
1408
- title: 'Overly Permissive CORS Policy',
1409
- description: allowOrigin === '*' ? 'CORS allows all origins' : 'CORS reflects arbitrary origin',
1410
- severity: 'medium',
1411
- category: 'access-control',
1412
- location: { file: targetUrl, snippet: `Access-Control-Allow-Origin: ${allowOrigin}` },
1413
- remediation: { description: 'Restrict CORS to specific trusted origins', estimatedEffort: 'minor', automatable: false },
1414
- references: ['https://owasp.org/www-community/attacks/CORS_OriginHeaderScrutiny'],
1415
- });
1416
- }
1417
- } catch {
1418
- // OPTIONS request failed - CORS might be properly restricted
1419
- }
1420
-
1421
- // ============================================================
1422
- // ENHANCED DAST: Link crawling, injection testing, form analysis
1423
- // ============================================================
1424
-
1425
- if (options.activeScanning ?? this.config.dastActiveScanning) {
1426
- const responseText = await response.clone().text();
1427
-
1428
- // 1. LINK CRAWLING - Extract and scan discovered links
1429
- const discoveredUrls = await this.extractAndCrawlLinks(
1430
- responseText,
1431
- parsedUrl,
1432
- crawledUrls,
1433
- maxDepth,
1434
- vulnerabilities
1435
- );
1436
- crawledUrls = discoveredUrls;
1437
-
1438
- // 2. INJECTION TESTING - Test URL parameters for XSS/SQLi
1439
- if (parsedUrl.search) {
1440
- await this.testInjectionVulnerabilities(
1441
- targetUrl,
1442
- parsedUrl,
1443
- vulnerabilities
1444
- );
1445
- }
1446
-
1447
- // 3. FORM DISCOVERY - Analyze forms for security issues
1448
- await this.analyzeFormsForSecurityIssues(
1449
- responseText,
1450
- targetUrl,
1451
- vulnerabilities
1452
- );
1453
- }
1454
-
1455
- } catch (fetchError) {
1456
- clearTimeout(timeoutId);
1457
- const errorMsg = fetchError instanceof Error ? fetchError.message : String(fetchError);
1458
-
1459
- if (errorMsg.includes('CERT') || errorMsg.includes('SSL') || errorMsg.includes('TLS') || errorMsg.includes('certificate')) {
1460
- vulnerabilities.push({
1461
- id: uuidv4(),
1462
- title: 'TLS Certificate Error',
1463
- description: `SSL/TLS error: ${errorMsg}`,
1464
- severity: 'high',
1465
- category: 'security-misconfiguration',
1466
- location: { file: targetUrl },
1467
- remediation: { description: 'Fix TLS certificate configuration', estimatedEffort: 'moderate', automatable: false },
1468
- references: ['https://owasp.org/www-project-web-security-testing-guide/'],
1469
- });
1470
- } else if (errorMsg.includes('timeout') || errorMsg.includes('abort')) {
1471
- vulnerabilities.push({
1472
- id: uuidv4(),
1473
- title: 'Connection Timeout',
1474
- description: `Target did not respond within timeout: ${errorMsg}`,
1475
- severity: 'informational',
1476
- category: 'security-misconfiguration',
1477
- location: { file: targetUrl },
1478
- remediation: { description: 'Verify target is accessible', estimatedEffort: 'trivial', automatable: false },
1479
- references: [],
1480
- });
1481
- }
1482
- }
1483
-
1484
- } catch (error) {
1485
- console.error('DAST scan error:', error);
1486
- }
1487
-
1488
- return { vulnerabilities, crawledUrls };
1489
- }
1490
-
1491
- /**
1492
- * Perform authenticated dynamic scanning with credentials
1493
- * Supports basic auth, bearer token, OAuth, and cookie-based authentication
1494
- */
1495
- private async performAuthenticatedScan(
1496
- targetUrl: string,
1497
- credentials: AuthCredentials,
1498
- options: DASTOptions
1499
- ): Promise<{ vulnerabilities: Vulnerability[]; crawledUrls: number }> {
1500
- const vulnerabilities: Vulnerability[] = [];
1501
- let crawledUrls = 0;
1502
-
1503
- try {
1504
- // Build authentication headers based on credential type
1505
- const authHeaders: Record<string, string> = {};
1506
-
1507
- switch (credentials.type) {
1508
- case 'basic':
1509
- if (credentials.username && credentials.password) {
1510
- const encoded = Buffer.from(`${credentials.username}:${credentials.password}`).toString('base64');
1511
- authHeaders['Authorization'] = `Basic ${encoded}`;
1512
- }
1513
- break;
1514
- case 'bearer':
1515
- case 'oauth':
1516
- if (credentials.token) {
1517
- authHeaders['Authorization'] = `Bearer ${credentials.token}`;
1518
- }
1519
- break;
1520
- case 'cookie':
1521
- if (credentials.token) {
1522
- authHeaders['Cookie'] = credentials.token;
1523
- }
1524
- break;
1525
- }
1526
-
1527
- // Validate and parse URL
1528
- let parsedUrl: URL;
1529
- try {
1530
- parsedUrl = new URL(targetUrl);
1531
- } catch {
1532
- vulnerabilities.push({
1533
- id: uuidv4(),
1534
- title: 'Invalid Target URL',
1535
- description: 'The provided target URL is not valid',
1536
- severity: 'informational',
1537
- category: 'security-misconfiguration',
1538
- location: { file: targetUrl },
1539
- remediation: { description: 'Provide a valid URL', estimatedEffort: 'trivial', automatable: false },
1540
- references: [],
1541
- });
1542
- return { vulnerabilities, crawledUrls: 0 };
1543
- }
1544
-
1545
- const timeout = options.timeout ?? this.config.timeout;
1546
- const maxDepth = options.maxDepth ?? this.config.dastMaxDepth;
1547
-
1548
- // Test authentication by making an authenticated request
1549
- const controller = new AbortController();
1550
- const timeoutId = setTimeout(() => controller.abort(), Math.min(timeout, 30000));
1551
-
1552
- try {
1553
- const response = await fetch(targetUrl, {
1554
- method: 'GET',
1555
- headers: {
1556
- 'User-Agent': 'AgenticQE-DAST-Scanner/3.0',
1557
- 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
1558
- ...authHeaders,
1559
- },
1560
- signal: controller.signal,
1561
- redirect: 'follow',
1562
- });
1563
-
1564
- clearTimeout(timeoutId);
1565
- crawledUrls++;
1566
-
1567
- // Check if authentication was successful
1568
- if (response.status === 401 || response.status === 403) {
1569
- vulnerabilities.push({
1570
- id: uuidv4(),
1571
- title: 'Authentication Failed',
1572
- description: `Authentication returned ${response.status} status`,
1573
- severity: 'informational',
1574
- category: 'broken-auth',
1575
- location: { file: targetUrl },
1576
- remediation: { description: 'Verify credentials are correct', estimatedEffort: 'trivial', automatable: false },
1577
- references: [],
1578
- });
1579
- }
1580
-
1581
- // Perform all the standard header checks from unauthenticated scan
1582
- const headers = response.headers;
1583
-
1584
- // Security header analysis (same as unauthenticated)
1585
- const headerChecks = [
1586
- { header: 'strict-transport-security', title: 'Missing HSTS Header', severity: 'medium' as VulnerabilitySeverity },
1587
- { header: 'x-content-type-options', title: 'Missing X-Content-Type-Options', severity: 'low' as VulnerabilitySeverity },
1588
- { header: 'x-frame-options', title: 'Missing X-Frame-Options', severity: 'medium' as VulnerabilitySeverity },
1589
- { header: 'content-security-policy', title: 'Missing Content-Security-Policy', severity: 'medium' as VulnerabilitySeverity },
1590
- ];
1591
-
1592
- for (const check of headerChecks) {
1593
- if (!headers.get(check.header)) {
1594
- vulnerabilities.push({
1595
- id: uuidv4(),
1596
- title: check.title,
1597
- description: `Security header ${check.header} is not present`,
1598
- severity: check.severity,
1599
- category: 'security-misconfiguration',
1600
- location: { file: targetUrl, snippet: `Missing: ${check.header}` },
1601
- remediation: { description: `Add ${check.header} header`, estimatedEffort: 'minor', automatable: true },
1602
- references: ['https://owasp.org/www-project-secure-headers/'],
1603
- });
1604
- }
1605
- }
1606
-
1607
- // Check for session token in URL (authenticated-specific)
1608
- if (parsedUrl.search.includes('token=') || parsedUrl.search.includes('session=') || parsedUrl.search.includes('auth=')) {
1609
- vulnerabilities.push({
1610
- id: uuidv4(),
1611
- title: 'Session Token in URL',
1612
- description: 'Authentication token appears in URL query string',
1613
- severity: 'high',
1614
- category: 'sensitive-data',
1615
- location: { file: targetUrl, snippet: parsedUrl.search.substring(0, 50) },
1616
- remediation: { description: 'Send tokens in headers or request body, not URL', estimatedEffort: 'moderate', automatable: false },
1617
- references: ['https://owasp.org/www-community/vulnerabilities/Information_exposure_through_query_strings_in_url'],
1618
- });
1619
- }
1620
-
1621
- // Test for authorization bypass on protected endpoints (authenticated-specific)
1622
- if (options.activeScanning ?? this.config.dastActiveScanning) {
1623
- const protectedEndpoints = [
1624
- '/admin',
1625
- '/dashboard',
1626
- '/api/users',
1627
- '/api/admin',
1628
- '/settings',
1629
- '/profile',
1630
- ];
1631
-
1632
- for (const endpoint of protectedEndpoints) {
1633
- if (crawledUrls >= maxDepth * 15) break;
1634
-
1635
- try {
1636
- const testUrl = new URL(endpoint, parsedUrl.origin).toString();
1637
-
1638
- // First, try with authentication
1639
- const authResponse = await fetch(testUrl, {
1640
- method: 'GET',
1641
- headers: { ...authHeaders },
1642
- signal: AbortSignal.timeout(5000),
1643
- });
1644
-
1645
- if (authResponse.ok) {
1646
- crawledUrls++;
1647
-
1648
- // Now try without authentication
1649
- const unauthResponse = await fetch(testUrl, {
1650
- method: 'GET',
1651
- signal: AbortSignal.timeout(5000),
1652
- });
1653
-
1654
- // If both succeed, there might be missing authentication
1655
- if (unauthResponse.ok && unauthResponse.status === 200) {
1656
- const authText = await authResponse.text();
1657
- const unauthText = await unauthResponse.text();
1658
-
1659
- // Check if the responses are similar (both returning actual content)
1660
- if (authText.length > 100 && unauthText.length > 100 &&
1661
- Math.abs(authText.length - unauthText.length) < authText.length * 0.1) {
1662
- vulnerabilities.push({
1663
- id: uuidv4(),
1664
- title: 'Missing Authentication on Protected Endpoint',
1665
- description: `Endpoint ${endpoint} is accessible without authentication`,
1666
- severity: 'high',
1667
- category: 'broken-auth',
1668
- location: { file: testUrl },
1669
- remediation: { description: 'Implement proper authentication checks', estimatedEffort: 'moderate', automatable: false },
1670
- references: ['https://owasp.org/www-project-web-security-testing-guide/'],
1671
- });
1672
- }
1673
- }
1674
- }
1675
- } catch {
1676
- // Endpoint not accessible - expected
1677
- }
1678
- }
1679
-
1680
- // Test for Insecure Direct Object References (IDOR)
1681
- const idorEndpoints = [
1682
- '/api/users/1',
1683
- '/api/users/2',
1684
- '/api/orders/1',
1685
- '/profile/1',
1686
- ];
1687
-
1688
- for (const endpoint of idorEndpoints.slice(0, 2)) {
1689
- if (crawledUrls >= maxDepth * 15) break;
1690
-
1691
- try {
1692
- const testUrl = new URL(endpoint, parsedUrl.origin).toString();
1693
- const response = await fetch(testUrl, {
1694
- method: 'GET',
1695
- headers: { ...authHeaders },
1696
- signal: AbortSignal.timeout(5000),
1697
- });
1698
-
1699
- if (response.ok) {
1700
- crawledUrls++;
1701
- const text = await response.text();
1702
-
1703
- // If we can access other users' data, that's an IDOR
1704
- if (text.includes('email') || text.includes('password') || text.includes('phone')) {
1705
- vulnerabilities.push({
1706
- id: uuidv4(),
1707
- title: 'Potential Insecure Direct Object Reference (IDOR)',
1708
- description: `Endpoint ${endpoint} may expose other users' data`,
1709
- severity: 'high',
1710
- category: 'access-control',
1711
- location: { file: testUrl },
1712
- remediation: { description: 'Implement proper authorization checks for resource access', estimatedEffort: 'moderate', automatable: false },
1713
- references: ['https://owasp.org/www-project-web-security-testing-guide/latest/4-Web_Application_Security_Testing/05-Authorization_Testing/04-Testing_for_Insecure_Direct_Object_References'],
1714
- });
1715
- }
1716
- }
1717
- } catch {
1718
- // Endpoint not accessible
1719
- }
1720
- }
1721
- }
1722
-
1723
- // Cookie security checks
1724
- const setCookie = headers.get('set-cookie');
1725
- if (setCookie) {
1726
- const cookieLower = setCookie.toLowerCase();
1727
- if (!cookieLower.includes('secure')) {
1728
- vulnerabilities.push({
1729
- id: uuidv4(),
1730
- title: 'Session Cookie Missing Secure Flag',
1731
- description: 'Authenticated session cookie is not marked as Secure',
1732
- severity: 'high', // Higher severity for authenticated sessions
1733
- category: 'sensitive-data',
1734
- location: { file: targetUrl },
1735
- remediation: { description: 'Add Secure flag to session cookies', estimatedEffort: 'trivial', automatable: true },
1736
- references: ['https://owasp.org/www-community/controls/SecureCookieAttribute'],
1737
- });
1738
- }
1739
- if (!cookieLower.includes('httponly')) {
1740
- vulnerabilities.push({
1741
- id: uuidv4(),
1742
- title: 'Session Cookie Missing HttpOnly Flag',
1743
- description: 'Session cookie is accessible to JavaScript',
1744
- severity: 'high',
1745
- category: 'sensitive-data',
1746
- location: { file: targetUrl },
1747
- remediation: { description: 'Add HttpOnly flag to session cookies', estimatedEffort: 'trivial', automatable: true },
1748
- references: ['https://owasp.org/www-community/HttpOnly'],
1749
- });
1750
- }
1751
- }
1752
-
1753
- } catch (fetchError) {
1754
- clearTimeout(timeoutId);
1755
- const errorMsg = fetchError instanceof Error ? fetchError.message : String(fetchError);
1756
-
1757
- if (errorMsg.includes('CERT') || errorMsg.includes('SSL') || errorMsg.includes('TLS')) {
1758
- vulnerabilities.push({
1759
- id: uuidv4(),
1760
- title: 'TLS Certificate Error',
1761
- description: `SSL/TLS error during authenticated scan: ${errorMsg}`,
1762
- severity: 'high',
1763
- category: 'security-misconfiguration',
1764
- location: { file: targetUrl },
1765
- remediation: { description: 'Fix TLS certificate configuration', estimatedEffort: 'moderate', automatable: false },
1766
- references: [],
1767
- });
1768
- }
1769
- }
1770
-
1771
- } catch (error) {
1772
- console.error('Authenticated DAST scan error:', error);
1773
- }
1774
-
1775
- return { vulnerabilities, crawledUrls };
1776
- }
1777
-
1778
- private validateCredentials(credentials: AuthCredentials): {
1779
- valid: boolean;
1780
- reason?: string;
1781
- } {
1782
- switch (credentials.type) {
1783
- case 'basic':
1784
- if (!credentials.username || !credentials.password) {
1785
- return { valid: false, reason: 'Basic auth requires username and password' };
1786
- }
1787
- break;
1788
- case 'bearer':
1789
- case 'oauth':
1790
- if (!credentials.token) {
1791
- return { valid: false, reason: 'Bearer/OAuth auth requires token' };
1792
- }
1793
- break;
1794
- case 'cookie':
1795
- if (!credentials.token) {
1796
- return { valid: false, reason: 'Cookie auth requires session cookie' };
1797
- }
1798
- break;
1799
- }
1800
- return { valid: true };
1801
- }
1802
-
1803
- /**
1804
- * Analyze if a vulnerability detection is a false positive using heuristics
1805
- * Future enhancement: integrate ML/AI models for improved false positive detection
1806
- */
1807
- private async analyzeFalsePositive(
1808
- vulnerability: Vulnerability
1809
- ): Promise<FalsePositiveCheck> {
1810
- let isFalsePositive = false;
1811
- let confidence = 0.5;
1812
- let reason = 'Manual review recommended';
1813
-
1814
- // Check for common false positive patterns
1815
- if (vulnerability.severity === 'informational') {
1816
- confidence = 0.3;
1817
- reason = 'Low severity findings often require manual verification';
1818
- }
1819
-
1820
- if (
1821
- vulnerability.location.snippet?.includes('test') ||
1822
- vulnerability.location.file.includes('test')
1823
- ) {
1824
- isFalsePositive = true;
1825
- confidence = 0.8;
1826
- reason = 'Vulnerability found in test code';
1827
- }
1828
-
1829
- if (vulnerability.location.snippet?.includes('// nosec')) {
1830
- isFalsePositive = true;
1831
- confidence = 0.95;
1832
- reason = 'Explicitly marked as ignored with nosec comment';
1833
- }
1834
-
1835
- return { isFalsePositive, confidence, reason };
1836
- }
1837
-
1838
- private calculateSummary(
1839
- vulnerabilities: Vulnerability[],
1840
- totalFiles: number,
1841
- scanDurationMs: number
1842
- ): ScanSummary {
1843
- const summary: MutableScanSummary = {
1844
- critical: 0,
1845
- high: 0,
1846
- medium: 0,
1847
- low: 0,
1848
- informational: 0,
1849
- totalFiles,
1850
- scanDurationMs,
1851
- };
1852
-
1853
- for (const vuln of vulnerabilities) {
1854
- summary[vuln.severity]++;
1855
- }
1856
-
1857
- return summary as ScanSummary;
1858
- }
1859
-
1860
- private combineSummaries(
1861
- sast: ScanSummary,
1862
- dast?: ScanSummary
1863
- ): ScanSummary {
1864
- if (!dast) return sast;
1865
-
1866
- return {
1867
- critical: sast.critical + dast.critical,
1868
- high: sast.high + dast.high,
1869
- medium: sast.medium + dast.medium,
1870
- low: sast.low + dast.low,
1871
- informational: sast.informational + dast.informational,
1872
- totalFiles: sast.totalFiles + dast.totalFiles,
1873
- scanDurationMs: sast.scanDurationMs + dast.scanDurationMs,
1874
- };
1875
- }
1876
-
1877
- private async storeScanResults(
1878
- scanId: string,
1879
- scanType: string,
1880
- vulnerabilities: Vulnerability[],
1881
- summary: ScanSummary
1882
- ): Promise<void> {
1883
- await this.memory.set(
1884
- `security:scan:${scanId}`,
1885
- {
1886
- scanId,
1887
- scanType,
1888
- vulnerabilities,
1889
- summary,
1890
- timestamp: new Date().toISOString(),
1891
- },
1892
- { namespace: 'security-compliance', ttl: 86400 * 7 } // 7 days
1893
- );
1894
- }
1895
-
1896
- // ==========================================================================
1897
- // Dependency Scanning Methods (OSV API)
1898
- // ==========================================================================
1899
-
1900
- /**
1901
- * Scan npm dependencies for known vulnerabilities using OSV API
1902
- */
1903
- async scanDependencies(
1904
- dependencies: Record<string, string>
1905
- ): Promise<Result<DependencyScanResult>> {
1906
- const scanId = uuidv4();
1907
- const startTime = Date.now();
1908
-
1909
- try {
1910
- if (Object.keys(dependencies).length === 0) {
1911
- return err(new Error('No dependencies provided for scanning'));
1912
- }
1913
-
1914
- this.activeScans.set(scanId, 'running');
1915
-
1916
- // Query OSV for vulnerabilities
1917
- const osvVulns = await this.osvClient.scanNpmDependencies(dependencies);
1918
-
1919
- // Convert OSV vulnerabilities to our format
1920
- const vulnerabilities = this.convertOSVVulnerabilities(osvVulns);
1921
-
1922
- const scanDurationMs = Date.now() - startTime;
1923
-
1924
- // Calculate unique vulnerable packages
1925
- const vulnerablePackageNames = new Set(
1926
- osvVulns.map((v) => v.affectedPackage)
1927
- );
1928
-
1929
- // Calculate summary
1930
- const summary = this.calculateSummary(
1931
- vulnerabilities,
1932
- Object.keys(dependencies).length,
1933
- scanDurationMs
1934
- );
1935
-
1936
- // Store scan results
1937
- await this.storeScanResults(scanId, 'dependency', vulnerabilities, summary);
1938
- this.activeScans.set(scanId, 'completed');
1939
-
1940
- return ok({
1941
- scanId,
1942
- vulnerabilities,
1943
- packagesScanned: Object.keys(dependencies).length,
1944
- vulnerablePackages: vulnerablePackageNames.size,
1945
- summary,
1946
- scanDurationMs,
1947
- });
1948
- } catch (error) {
1949
- this.activeScans.set(scanId, 'failed');
1950
- return err(error instanceof Error ? error : new Error(String(error)));
1951
- }
1952
- }
1953
-
1954
- /**
1955
- * Scan a package.json file for dependency vulnerabilities
1956
- */
1957
- async scanPackageJson(packageJsonPath: string): Promise<Result<DependencyScanResult>> {
1958
- try {
1959
- const fs = await import('fs/promises');
1960
- const content = await fs.readFile(packageJsonPath, 'utf-8');
1961
- const packageJson = JSON.parse(content);
1962
-
1963
- // Combine all dependency types
1964
- const allDependencies: Record<string, string> = {
1965
- ...(packageJson.dependencies || {}),
1966
- ...(packageJson.devDependencies || {}),
1967
- ...(packageJson.peerDependencies || {}),
1968
- ...(packageJson.optionalDependencies || {}),
1969
- };
1970
-
1971
- if (Object.keys(allDependencies).length === 0) {
1972
- return err(new Error('No dependencies found in package.json'));
1973
- }
1974
-
1975
- return this.scanDependencies(allDependencies);
1976
- } catch (error) {
1977
- if (error instanceof SyntaxError) {
1978
- return err(new Error(`Invalid JSON in package.json: ${error.message}`));
1979
- }
1980
- return err(error instanceof Error ? error : new Error(String(error)));
1981
- }
1982
- }
1983
-
1984
- /**
1985
- * Convert OSV vulnerabilities to our internal format
1986
- */
1987
- private convertOSVVulnerabilities(
1988
- osvVulns: ParsedVulnerability[]
1989
- ): Vulnerability[] {
1990
- return osvVulns.map((osv) => {
1991
- const location: VulnerabilityLocation = {
1992
- file: 'package.json',
1993
- line: 1,
1994
- column: 1,
1995
- snippet: `"${osv.affectedPackage}": "..."`,
1996
- };
1997
-
1998
- const remediation: RemediationAdvice = {
1999
- description: osv.fixedVersions.length > 0
2000
- ? `Update to version ${osv.fixedVersions[0]} or later`
2001
- : 'No fixed version available; consider alternative packages',
2002
- fixExample: osv.fixedVersions.length > 0
2003
- ? `npm install ${osv.affectedPackage}@${osv.fixedVersions[0]}`
2004
- : undefined,
2005
- estimatedEffort: 'minor',
2006
- automatable: true,
2007
- };
2008
-
2009
- return {
2010
- id: uuidv4(),
2011
- cveId: osv.cveIds[0],
2012
- title: `${osv.affectedPackage}: ${osv.summary.substring(0, 80)}`,
2013
- description: osv.details || osv.summary,
2014
- severity: this.mapOSVSeverity(osv.severity),
2015
- category: 'dependencies' as VulnerabilityCategory,
2016
- location,
2017
- remediation,
2018
- references: osv.references.slice(0, 5),
2019
- };
2020
- });
2021
- }
2022
-
2023
- /**
2024
- * Map OSV severity to our severity type
2025
- */
2026
- private mapOSVSeverity(
2027
- osvSeverity: ParsedVulnerability['severity']
2028
- ): VulnerabilitySeverity {
2029
- const mapping: Record<ParsedVulnerability['severity'], VulnerabilitySeverity> = {
2030
- critical: 'critical',
2031
- high: 'high',
2032
- medium: 'medium',
2033
- low: 'low',
2034
- unknown: 'medium',
2035
- };
2036
- return mapping[osvSeverity];
2037
- }
2038
-
2039
- // ============================================================
2040
- // ENHANCED DAST METHODS
2041
- // ============================================================
2042
-
2043
- /**
2044
- * Extract links from HTML and crawl discovered pages
2045
- * Implements basic web crawling within same origin
2046
- */
2047
- private async extractAndCrawlLinks(
2048
- html: string,
2049
- baseUrl: URL,
2050
- currentCrawled: number,
2051
- maxDepth: number,
2052
- vulnerabilities: Vulnerability[]
2053
- ): Promise<number> {
2054
- let crawledUrls = currentCrawled;
2055
- const maxCrawl = maxDepth * 5; // Allow more pages based on depth
2056
-
2057
- // Extract links from HTML using regex (no DOM parser needed)
2058
- const linkPattern = /href=["']([^"']+)["']/gi;
2059
- const discoveredLinks = new Set<string>();
2060
- let match;
2061
-
2062
- while ((match = linkPattern.exec(html)) !== null) {
2063
- const href = match[1];
2064
- // Only follow same-origin links
2065
- try {
2066
- const linkUrl = new URL(href, baseUrl.origin);
2067
- if (linkUrl.origin === baseUrl.origin && !discoveredLinks.has(linkUrl.pathname)) {
2068
- discoveredLinks.add(linkUrl.pathname);
2069
- }
2070
- } catch {
2071
- // Invalid URL - skip
2072
- }
2073
- }
2074
-
2075
- // Crawl discovered links (limited)
2076
- const linksToCrawl = Array.from(discoveredLinks).slice(0, Math.min(10, maxCrawl - crawledUrls));
2077
-
2078
- for (const path of linksToCrawl) {
2079
- if (crawledUrls >= maxCrawl) break;
2080
-
2081
- try {
2082
- const crawlUrl = new URL(path, baseUrl.origin).toString();
2083
- const crawlResponse = await fetch(crawlUrl, {
2084
- method: 'GET',
2085
- headers: { 'User-Agent': 'AgenticQE-DAST-Scanner/3.0' },
2086
- signal: AbortSignal.timeout(5000),
2087
- redirect: 'follow',
2088
- });
2089
-
2090
- crawledUrls++;
2091
-
2092
- // Check for security issues on crawled pages
2093
- if (crawlResponse.ok) {
2094
- // Check for sensitive data exposure in URLs
2095
- if (path.includes('password') || path.includes('token') || path.includes('api_key')) {
2096
- vulnerabilities.push({
2097
- id: uuidv4(),
2098
- title: 'Sensitive Data in URL Path',
2099
- description: `URL path may contain sensitive parameter names: ${path}`,
2100
- severity: 'medium',
2101
- category: 'sensitive-data',
2102
- location: { file: crawlUrl },
2103
- remediation: { description: 'Avoid sensitive data in URL paths', estimatedEffort: 'minor', automatable: false },
2104
- references: ['https://owasp.org/www-community/vulnerabilities/Information_exposure_through_query_strings_in_url'],
2105
- });
2106
- }
2107
-
2108
- // Check for directory listing
2109
- const responseText = await crawlResponse.text();
2110
- if (responseText.includes('Index of /') || responseText.includes('Directory listing for')) {
2111
- vulnerabilities.push({
2112
- id: uuidv4(),
2113
- title: 'Directory Listing Enabled',
2114
- description: `Directory listing is enabled at: ${crawlUrl}`,
2115
- severity: 'medium',
2116
- category: 'security-misconfiguration',
2117
- location: { file: crawlUrl },
2118
- remediation: { description: 'Disable directory listing in server configuration', estimatedEffort: 'trivial', automatable: true },
2119
- references: ['https://owasp.org/www-project-web-security-testing-guide/'],
2120
- });
2121
- }
2122
- }
2123
- } catch {
2124
- // Page not accessible - expected for some links
2125
- }
2126
- }
2127
-
2128
- return crawledUrls;
2129
- }
2130
-
2131
- /**
2132
- * Test URL parameters for injection vulnerabilities (XSS, SQLi)
2133
- * Uses safe payloads that reveal vulnerability without exploitation
2134
- */
2135
- private async testInjectionVulnerabilities(
2136
- targetUrl: string,
2137
- parsedUrl: URL,
2138
- vulnerabilities: Vulnerability[]
2139
- ): Promise<void> {
2140
- const params = new URLSearchParams(parsedUrl.search);
2141
- const paramNames = Array.from(params.keys());
2142
-
2143
- // Safe test payloads that reveal vulnerability without harm
2144
- const xssPayloads = [
2145
- { payload: '<script>alert(1)</script>', name: 'Basic XSS' },
2146
- { payload: '"><img src=x onerror=alert(1)>', name: 'Attribute Injection' },
2147
- { payload: "'-alert(1)-'", name: 'JavaScript Injection' },
2148
- ];
2149
-
2150
- const sqliPayloads = [
2151
- { payload: "' OR '1'='1", name: 'SQL OR Injection' },
2152
- { payload: "1; DROP TABLE test--", name: 'SQL Statement Injection' },
2153
- { payload: "1' AND '1'='1", name: 'SQL AND Injection' },
2154
- ];
2155
-
2156
- // Test each parameter with injection payloads
2157
- for (const paramName of paramNames.slice(0, 3)) { // Limit to first 3 params
2158
- // Test XSS
2159
- for (const xss of xssPayloads) {
2160
- try {
2161
- const testParams = new URLSearchParams(parsedUrl.search);
2162
- testParams.set(paramName, xss.payload);
2163
- const testUrl = `${parsedUrl.origin}${parsedUrl.pathname}?${testParams.toString()}`;
2164
-
2165
- const response = await fetch(testUrl, {
2166
- method: 'GET',
2167
- headers: { 'User-Agent': 'AgenticQE-DAST-Scanner/3.0' },
2168
- signal: AbortSignal.timeout(5000),
2169
- });
2170
-
2171
- if (response.ok) {
2172
- const text = await response.text();
2173
- const escapedPayload = xss.payload
2174
- .replace(/&/g, '&amp;')
2175
- .replace(/</g, '&lt;')
2176
- .replace(/>/g, '&gt;')
2177
- .replace(/"/g, '&quot;')
2178
- .replace(/'/g, '&#x27;');
2179
-
2180
- // Check for XSS vulnerability:
2181
- // 1. Payload reflected unescaped (definite XSS)
2182
- // 2. Payload partially escaped but critical chars remain (potential bypass)
2183
- const hasUnescapedPayload = text.includes(xss.payload);
2184
- const hasEscapedPayload = text.includes(escapedPayload);
2185
-
2186
- // Only flag if payload is reflected AND it's unescaped
2187
- if (hasUnescapedPayload && !hasEscapedPayload) {
2188
- vulnerabilities.push({
2189
- id: uuidv4(),
2190
- title: `Reflected XSS: ${xss.name}`,
2191
- description: `Parameter '${paramName}' reflects unsanitized input - payload executed without encoding`,
2192
- severity: 'critical',
2193
- category: 'xss',
2194
- location: { file: targetUrl, snippet: `Parameter: ${paramName}, Payload: ${xss.payload.substring(0, 30)}...` },
2195
- remediation: { description: 'HTML-encode all user input before rendering. Use framework auto-escaping.', estimatedEffort: 'moderate', automatable: false },
2196
- references: ['https://owasp.org/www-community/attacks/xss/', 'https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html'],
2197
- });
2198
- break; // One XSS finding per parameter is enough
2199
- }
2200
-
2201
- // Check for partial escaping (< escaped but not > or vice versa) - potential bypass
2202
- const hasPartialEscape =
2203
- (text.includes('&lt;') && text.includes('>') && text.includes(xss.payload.replace(/</g, '&lt;'))) ||
2204
- (text.includes('<') && text.includes('&gt;') && text.includes(xss.payload.replace(/>/g, '&gt;')));
2205
-
2206
- if (hasPartialEscape) {
2207
- vulnerabilities.push({
2208
- id: uuidv4(),
2209
- title: `Potential XSS: Inconsistent Encoding`,
2210
- description: `Parameter '${paramName}' has inconsistent HTML encoding - some characters escaped, others not`,
2211
- severity: 'medium',
2212
- category: 'xss',
2213
- location: { file: targetUrl, snippet: `Parameter: ${paramName}` },
2214
- remediation: { description: 'Use consistent HTML encoding for all special characters', estimatedEffort: 'minor', automatable: false },
2215
- references: ['https://owasp.org/www-community/attacks/xss/'],
2216
- });
2217
- break;
2218
- }
2219
- }
2220
- } catch {
2221
- // Request failed - target may be blocking
2222
- }
2223
- }
2224
-
2225
- // Test SQLi (look for error-based indicators)
2226
- for (const sqli of sqliPayloads) {
2227
- try {
2228
- const testParams = new URLSearchParams(parsedUrl.search);
2229
- testParams.set(paramName, sqli.payload);
2230
- const testUrl = `${parsedUrl.origin}${parsedUrl.pathname}?${testParams.toString()}`;
2231
-
2232
- const response = await fetch(testUrl, {
2233
- method: 'GET',
2234
- headers: { 'User-Agent': 'AgenticQE-DAST-Scanner/3.0' },
2235
- signal: AbortSignal.timeout(5000),
2236
- });
2237
-
2238
- const text = await response.text();
2239
- // Look for SQL error indicators
2240
- const sqlErrorPatterns = [
2241
- /SQL syntax.*MySQL/i,
2242
- /Warning.*mysql/i,
2243
- /PostgreSQL.*ERROR/i,
2244
- /ORA-\d{5}/i,
2245
- /SQLite.*error/i,
2246
- /SQLITE_ERROR/i,
2247
- /unclosed quotation mark/i,
2248
- /quoted string not properly terminated/i,
2249
- ];
2250
-
2251
- for (const pattern of sqlErrorPatterns) {
2252
- if (pattern.test(text)) {
2253
- vulnerabilities.push({
2254
- id: uuidv4(),
2255
- title: `SQL Injection: ${sqli.name}`,
2256
- description: `Parameter '${paramName}' appears vulnerable to SQL injection - database error message exposed`,
2257
- severity: 'critical',
2258
- category: 'injection',
2259
- location: { file: targetUrl, snippet: `Parameter: ${paramName}` },
2260
- remediation: { description: 'Use parameterized queries or prepared statements', estimatedEffort: 'moderate', automatable: false },
2261
- references: ['https://owasp.org/www-community/attacks/SQL_Injection'],
2262
- });
2263
- break;
2264
- }
2265
- }
2266
- } catch {
2267
- // Request failed
2268
- }
2269
- }
2270
- }
2271
- }
2272
-
2273
- /**
2274
- * Analyze HTML forms for security issues
2275
- * Checks for CSRF protection, autocomplete settings, and action targets
2276
- */
2277
- private async analyzeFormsForSecurityIssues(
2278
- html: string,
2279
- baseUrl: string,
2280
- vulnerabilities: Vulnerability[]
2281
- ): Promise<void> {
2282
- // Extract forms using regex
2283
- const formPattern = /<form[^>]*>([\s\S]*?)<\/form>/gi;
2284
- let formMatch;
2285
- let formIndex = 0;
2286
-
2287
- while ((formMatch = formPattern.exec(html)) !== null && formIndex < 10) {
2288
- formIndex++;
2289
- const formHtml = formMatch[0];
2290
- const formContent = formMatch[1];
2291
-
2292
- // Check for CSRF token
2293
- const hasCsrfToken =
2294
- /name=["']?csrf/i.test(formContent) ||
2295
- /name=["']?_token/i.test(formContent) ||
2296
- /name=["']?authenticity_token/i.test(formContent) ||
2297
- /name=["']?__RequestVerificationToken/i.test(formContent);
2298
-
2299
- // Check form method
2300
- const isPostForm = /method=["']?post/i.test(formHtml);
2301
-
2302
- if (isPostForm && !hasCsrfToken) {
2303
- vulnerabilities.push({
2304
- id: uuidv4(),
2305
- title: 'Missing CSRF Token',
2306
- description: `POST form #${formIndex} does not appear to have CSRF protection`,
2307
- severity: 'medium',
2308
- category: 'broken-auth',
2309
- location: { file: baseUrl, snippet: `Form #${formIndex}` },
2310
- remediation: { description: 'Add CSRF token to all state-changing forms', estimatedEffort: 'minor', automatable: false },
2311
- references: ['https://owasp.org/www-community/attacks/csrf'],
2312
- });
2313
- }
2314
-
2315
- // Check for password fields without autocomplete=off
2316
- if (/type=["']?password/i.test(formContent)) {
2317
- const hasAutocompleteOff =
2318
- /autocomplete=["']?(off|new-password)/i.test(formContent) ||
2319
- /autocomplete=["']?(off|new-password)/i.test(formHtml);
2320
-
2321
- if (!hasAutocompleteOff) {
2322
- vulnerabilities.push({
2323
- id: uuidv4(),
2324
- title: 'Password Field Allows Autocomplete',
2325
- description: `Form #${formIndex} has password field that may be cached by browser`,
2326
- severity: 'low',
2327
- category: 'sensitive-data',
2328
- location: { file: baseUrl, snippet: `Form #${formIndex}` },
2329
- remediation: { description: 'Add autocomplete="new-password" to password fields', estimatedEffort: 'trivial', automatable: true },
2330
- references: ['https://owasp.org/www-project-web-security-testing-guide/'],
2331
- });
2332
- }
2333
- }
2334
-
2335
- // Check for insecure form action
2336
- const actionMatch = /action=["']?([^"'\s>]+)/i.exec(formHtml);
2337
- if (actionMatch) {
2338
- const action = actionMatch[1];
2339
- if (action.startsWith('http://') && !action.includes('localhost') && !action.includes('127.0.0.1')) {
2340
- vulnerabilities.push({
2341
- id: uuidv4(),
2342
- title: 'Form Submits to Insecure HTTP',
2343
- description: `Form #${formIndex} submits data over insecure HTTP: ${action}`,
2344
- severity: 'high',
2345
- category: 'sensitive-data',
2346
- location: { file: baseUrl, snippet: `Action: ${action}` },
2347
- remediation: { description: 'Change form action to use HTTPS', estimatedEffort: 'trivial', automatable: true },
2348
- references: ['https://owasp.org/www-project-web-security-testing-guide/'],
2349
- });
2350
- }
2351
- }
2352
- }
2353
- }
2354
- }