api-tests-coverage 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (288) hide show
  1. package/README.md +703 -0
  2. package/config.yaml.example +227 -0
  3. package/dist/action/src/index.d.ts +2 -0
  4. package/dist/action/src/index.d.ts.map +1 -0
  5. package/dist/action/src/index.js +349 -0
  6. package/dist/action/src/prComment.d.ts +34 -0
  7. package/dist/action/src/prComment.d.ts.map +1 -0
  8. package/dist/action/src/prComment.js +146 -0
  9. package/dist/src/ast/astAnalysisOrchestrator.d.ts +36 -0
  10. package/dist/src/ast/astAnalysisOrchestrator.d.ts.map +1 -0
  11. package/dist/src/ast/astAnalysisOrchestrator.js +123 -0
  12. package/dist/src/ast/astTypes.d.ts +105 -0
  13. package/dist/src/ast/astTypes.d.ts.map +1 -0
  14. package/dist/src/ast/astTypes.js +9 -0
  15. package/dist/src/ast/languageAnalyzer.d.ts +46 -0
  16. package/dist/src/ast/languageAnalyzer.d.ts.map +1 -0
  17. package/dist/src/ast/languageAnalyzer.js +9 -0
  18. package/dist/src/ast/languageCapabilities.d.ts +24 -0
  19. package/dist/src/ast/languageCapabilities.d.ts.map +1 -0
  20. package/dist/src/ast/languageCapabilities.js +92 -0
  21. package/dist/src/ast/parseFile.d.ts +16 -0
  22. package/dist/src/ast/parseFile.d.ts.map +1 -0
  23. package/dist/src/ast/parseFile.js +65 -0
  24. package/dist/src/ast/parserRegistry.d.ts +39 -0
  25. package/dist/src/ast/parserRegistry.d.ts.map +1 -0
  26. package/dist/src/ast/parserRegistry.js +66 -0
  27. package/dist/src/buildSummary.d.ts +26 -0
  28. package/dist/src/buildSummary.d.ts.map +1 -0
  29. package/dist/src/buildSummary.js +193 -0
  30. package/dist/src/businessCoverage.d.ts +68 -0
  31. package/dist/src/businessCoverage.d.ts.map +1 -0
  32. package/dist/src/businessCoverage.js +290 -0
  33. package/dist/src/compatibilityCoverage.d.ts +83 -0
  34. package/dist/src/compatibilityCoverage.d.ts.map +1 -0
  35. package/dist/src/compatibilityCoverage.js +501 -0
  36. package/dist/src/config/defaultConfig.d.ts +9 -0
  37. package/dist/src/config/defaultConfig.d.ts.map +1 -0
  38. package/dist/src/config/defaultConfig.js +97 -0
  39. package/dist/src/config/index.d.ts +12 -0
  40. package/dist/src/config/index.d.ts.map +1 -0
  41. package/dist/src/config/index.js +37 -0
  42. package/dist/src/config/loadConfig.d.ts +29 -0
  43. package/dist/src/config/loadConfig.d.ts.map +1 -0
  44. package/dist/src/config/loadConfig.js +135 -0
  45. package/dist/src/config/mergeConfig.d.ts +15 -0
  46. package/dist/src/config/mergeConfig.d.ts.map +1 -0
  47. package/dist/src/config/mergeConfig.js +57 -0
  48. package/dist/src/config/schema.d.ts +15 -0
  49. package/dist/src/config/schema.d.ts.map +1 -0
  50. package/dist/src/config/schema.js +30 -0
  51. package/dist/src/config/types.d.ts +175 -0
  52. package/dist/src/config/types.d.ts.map +1 -0
  53. package/dist/src/config/types.js +9 -0
  54. package/dist/src/config/validateConfig.d.ts +22 -0
  55. package/dist/src/config/validateConfig.d.ts.map +1 -0
  56. package/dist/src/config/validateConfig.js +171 -0
  57. package/dist/src/config.d.ts +168 -0
  58. package/dist/src/config.d.ts.map +1 -0
  59. package/dist/src/config.js +204 -0
  60. package/dist/src/coverage/deep-analysis/callGraph.d.ts +67 -0
  61. package/dist/src/coverage/deep-analysis/callGraph.d.ts.map +1 -0
  62. package/dist/src/coverage/deep-analysis/callGraph.js +275 -0
  63. package/dist/src/coverage/deep-analysis/deepEndpointResolver.d.ts +23 -0
  64. package/dist/src/coverage/deep-analysis/deepEndpointResolver.d.ts.map +1 -0
  65. package/dist/src/coverage/deep-analysis/deepEndpointResolver.js +394 -0
  66. package/dist/src/coverage/deep-analysis/index.d.ts +17 -0
  67. package/dist/src/coverage/deep-analysis/index.d.ts.map +1 -0
  68. package/dist/src/coverage/deep-analysis/index.js +63 -0
  69. package/dist/src/coverage/deep-analysis/resolveAssertions.d.ts +60 -0
  70. package/dist/src/coverage/deep-analysis/resolveAssertions.d.ts.map +1 -0
  71. package/dist/src/coverage/deep-analysis/resolveAssertions.js +121 -0
  72. package/dist/src/coverage/deep-analysis/resolveConstants.d.ts +36 -0
  73. package/dist/src/coverage/deep-analysis/resolveConstants.d.ts.map +1 -0
  74. package/dist/src/coverage/deep-analysis/resolveConstants.js +92 -0
  75. package/dist/src/coverage/deep-analysis/resolveEnums.d.ts +55 -0
  76. package/dist/src/coverage/deep-analysis/resolveEnums.d.ts.map +1 -0
  77. package/dist/src/coverage/deep-analysis/resolveEnums.js +152 -0
  78. package/dist/src/coverage/deep-analysis/resolveMethodChains.d.ts +70 -0
  79. package/dist/src/coverage/deep-analysis/resolveMethodChains.d.ts.map +1 -0
  80. package/dist/src/coverage/deep-analysis/resolveMethodChains.js +152 -0
  81. package/dist/src/coverage/deep-analysis/resolvePaths.d.ts +80 -0
  82. package/dist/src/coverage/deep-analysis/resolvePaths.d.ts.map +1 -0
  83. package/dist/src/coverage/deep-analysis/resolvePaths.js +216 -0
  84. package/dist/src/coverage/deep-analysis/resolveRequestWrappers.d.ts +71 -0
  85. package/dist/src/coverage/deep-analysis/resolveRequestWrappers.d.ts.map +1 -0
  86. package/dist/src/coverage/deep-analysis/resolveRequestWrappers.js +226 -0
  87. package/dist/src/coverage/deep-analysis/symbolTable.d.ts +58 -0
  88. package/dist/src/coverage/deep-analysis/symbolTable.d.ts.map +1 -0
  89. package/dist/src/coverage/deep-analysis/symbolTable.js +230 -0
  90. package/dist/src/coverage/deep-analysis/types.d.ts +122 -0
  91. package/dist/src/coverage/deep-analysis/types.d.ts.map +1 -0
  92. package/dist/src/coverage/deep-analysis/types.js +21 -0
  93. package/dist/src/discovery/fileClassifier.d.ts +50 -0
  94. package/dist/src/discovery/fileClassifier.d.ts.map +1 -0
  95. package/dist/src/discovery/fileClassifier.js +238 -0
  96. package/dist/src/discovery/projectDiscovery.d.ts +66 -0
  97. package/dist/src/discovery/projectDiscovery.d.ts.map +1 -0
  98. package/dist/src/discovery/projectDiscovery.js +287 -0
  99. package/dist/src/endpointCoverage.d.ts +70 -0
  100. package/dist/src/endpointCoverage.d.ts.map +1 -0
  101. package/dist/src/endpointCoverage.js +381 -0
  102. package/dist/src/errorCoverage.d.ts +93 -0
  103. package/dist/src/errorCoverage.d.ts.map +1 -0
  104. package/dist/src/errorCoverage.js +698 -0
  105. package/dist/src/index.d.ts +3 -0
  106. package/dist/src/index.d.ts.map +1 -0
  107. package/dist/src/index.js +1441 -0
  108. package/dist/src/inference/businessRuleInference.d.ts +63 -0
  109. package/dist/src/inference/businessRuleInference.d.ts.map +1 -0
  110. package/dist/src/inference/businessRuleInference.js +268 -0
  111. package/dist/src/inference/integrationFlowInference.d.ts +56 -0
  112. package/dist/src/inference/integrationFlowInference.d.ts.map +1 -0
  113. package/dist/src/inference/integrationFlowInference.js +266 -0
  114. package/dist/src/integrationCoverage.d.ts +72 -0
  115. package/dist/src/integrationCoverage.d.ts.map +1 -0
  116. package/dist/src/integrationCoverage.js +317 -0
  117. package/dist/src/intelligence/index.d.ts +20 -0
  118. package/dist/src/intelligence/index.d.ts.map +1 -0
  119. package/dist/src/intelligence/index.js +105 -0
  120. package/dist/src/intelligence/linkageEngine.d.ts +20 -0
  121. package/dist/src/intelligence/linkageEngine.d.ts.map +1 -0
  122. package/dist/src/intelligence/linkageEngine.js +522 -0
  123. package/dist/src/intelligence/markdownReporter.d.ts +12 -0
  124. package/dist/src/intelligence/markdownReporter.d.ts.map +1 -0
  125. package/dist/src/intelligence/markdownReporter.js +265 -0
  126. package/dist/src/intelligence/riskScoring.d.ts +53 -0
  127. package/dist/src/intelligence/riskScoring.d.ts.map +1 -0
  128. package/dist/src/intelligence/riskScoring.js +181 -0
  129. package/dist/src/intelligence/types.d.ts +121 -0
  130. package/dist/src/intelligence/types.d.ts.map +1 -0
  131. package/dist/src/intelligence/types.js +8 -0
  132. package/dist/src/languageDetection.d.ts +100 -0
  133. package/dist/src/languageDetection.d.ts.map +1 -0
  134. package/dist/src/languageDetection.js +349 -0
  135. package/dist/src/languages/java/index.d.ts +16 -0
  136. package/dist/src/languages/java/index.d.ts.map +1 -0
  137. package/dist/src/languages/java/index.js +103 -0
  138. package/dist/src/languages/java/parser.d.ts +7 -0
  139. package/dist/src/languages/java/parser.d.ts.map +1 -0
  140. package/dist/src/languages/java/parser.js +50 -0
  141. package/dist/src/languages/java/semanticBuilder.d.ts +21 -0
  142. package/dist/src/languages/java/semanticBuilder.d.ts.map +1 -0
  143. package/dist/src/languages/java/semanticBuilder.js +358 -0
  144. package/dist/src/languages/javascript/annotationExtractor.d.ts +20 -0
  145. package/dist/src/languages/javascript/annotationExtractor.d.ts.map +1 -0
  146. package/dist/src/languages/javascript/annotationExtractor.js +94 -0
  147. package/dist/src/languages/javascript/assertionResolver.d.ts +18 -0
  148. package/dist/src/languages/javascript/assertionResolver.d.ts.map +1 -0
  149. package/dist/src/languages/javascript/assertionResolver.js +150 -0
  150. package/dist/src/languages/javascript/callResolver.d.ts +23 -0
  151. package/dist/src/languages/javascript/callResolver.d.ts.map +1 -0
  152. package/dist/src/languages/javascript/callResolver.js +236 -0
  153. package/dist/src/languages/javascript/httpInteractionExtractor.d.ts +23 -0
  154. package/dist/src/languages/javascript/httpInteractionExtractor.d.ts.map +1 -0
  155. package/dist/src/languages/javascript/httpInteractionExtractor.js +205 -0
  156. package/dist/src/languages/javascript/index.d.ts +20 -0
  157. package/dist/src/languages/javascript/index.d.ts.map +1 -0
  158. package/dist/src/languages/javascript/index.js +136 -0
  159. package/dist/src/languages/javascript/parser.d.ts +14 -0
  160. package/dist/src/languages/javascript/parser.d.ts.map +1 -0
  161. package/dist/src/languages/javascript/parser.js +38 -0
  162. package/dist/src/languages/javascript/symbolResolver.d.ts +31 -0
  163. package/dist/src/languages/javascript/symbolResolver.d.ts.map +1 -0
  164. package/dist/src/languages/javascript/symbolResolver.js +183 -0
  165. package/dist/src/languages/kotlin/index.d.ts +16 -0
  166. package/dist/src/languages/kotlin/index.d.ts.map +1 -0
  167. package/dist/src/languages/kotlin/index.js +151 -0
  168. package/dist/src/languages/kotlin/parser.d.ts +11 -0
  169. package/dist/src/languages/kotlin/parser.d.ts.map +1 -0
  170. package/dist/src/languages/kotlin/parser.js +74 -0
  171. package/dist/src/languages/python/index.d.ts +15 -0
  172. package/dist/src/languages/python/index.d.ts.map +1 -0
  173. package/dist/src/languages/python/index.js +293 -0
  174. package/dist/src/languages/ruby/index.d.ts +15 -0
  175. package/dist/src/languages/ruby/index.d.ts.map +1 -0
  176. package/dist/src/languages/ruby/index.js +274 -0
  177. package/dist/src/languages/shared/treeSitterUtils.d.ts +43 -0
  178. package/dist/src/languages/shared/treeSitterUtils.d.ts.map +1 -0
  179. package/dist/src/languages/shared/treeSitterUtils.js +100 -0
  180. package/dist/src/languages/typescript/index.d.ts +14 -0
  181. package/dist/src/languages/typescript/index.d.ts.map +1 -0
  182. package/dist/src/languages/typescript/index.js +25 -0
  183. package/dist/src/lib/index.d.ts +228 -0
  184. package/dist/src/lib/index.d.ts.map +1 -0
  185. package/dist/src/lib/index.js +486 -0
  186. package/dist/src/mcp/client/index.d.ts +37 -0
  187. package/dist/src/mcp/client/index.d.ts.map +1 -0
  188. package/dist/src/mcp/client/index.js +235 -0
  189. package/dist/src/mcp/config.d.ts +50 -0
  190. package/dist/src/mcp/config.d.ts.map +1 -0
  191. package/dist/src/mcp/config.js +125 -0
  192. package/dist/src/mcp/events.d.ts +24 -0
  193. package/dist/src/mcp/events.d.ts.map +1 -0
  194. package/dist/src/mcp/events.js +48 -0
  195. package/dist/src/mcp/fallback/index.d.ts +50 -0
  196. package/dist/src/mcp/fallback/index.d.ts.map +1 -0
  197. package/dist/src/mcp/fallback/index.js +216 -0
  198. package/dist/src/mcp/index.d.ts +67 -0
  199. package/dist/src/mcp/index.d.ts.map +1 -0
  200. package/dist/src/mcp/index.js +212 -0
  201. package/dist/src/mcp/normalizer.d.ts +21 -0
  202. package/dist/src/mcp/normalizer.d.ts.map +1 -0
  203. package/dist/src/mcp/normalizer.js +99 -0
  204. package/dist/src/mcp/prompts/index.d.ts +86 -0
  205. package/dist/src/mcp/prompts/index.d.ts.map +1 -0
  206. package/dist/src/mcp/prompts/index.js +304 -0
  207. package/dist/src/mcp/templates/index.d.ts +35 -0
  208. package/dist/src/mcp/templates/index.d.ts.map +1 -0
  209. package/dist/src/mcp/templates/index.js +143 -0
  210. package/dist/src/mcp/testing/mock-server/index.d.ts +47 -0
  211. package/dist/src/mcp/testing/mock-server/index.d.ts.map +1 -0
  212. package/dist/src/mcp/testing/mock-server/index.js +157 -0
  213. package/dist/src/mcp/types.d.ts +127 -0
  214. package/dist/src/mcp/types.d.ts.map +1 -0
  215. package/dist/src/mcp/types.js +8 -0
  216. package/dist/src/observability.d.ts +138 -0
  217. package/dist/src/observability.d.ts.map +1 -0
  218. package/dist/src/observability.js +519 -0
  219. package/dist/src/parameterCoverage.d.ts +75 -0
  220. package/dist/src/parameterCoverage.d.ts.map +1 -0
  221. package/dist/src/parameterCoverage.js +629 -0
  222. package/dist/src/perfResilienceCoverage.d.ts +155 -0
  223. package/dist/src/perfResilienceCoverage.d.ts.map +1 -0
  224. package/dist/src/perfResilienceCoverage.js +670 -0
  225. package/dist/src/pluginLoader.d.ts +51 -0
  226. package/dist/src/pluginLoader.d.ts.map +1 -0
  227. package/dist/src/pluginLoader.js +72 -0
  228. package/dist/src/publishing.d.ts +63 -0
  229. package/dist/src/publishing.d.ts.map +1 -0
  230. package/dist/src/publishing.js +379 -0
  231. package/dist/src/qualityGate.d.ts +58 -0
  232. package/dist/src/qualityGate.d.ts.map +1 -0
  233. package/dist/src/qualityGate.js +118 -0
  234. package/dist/src/reporting.d.ts +41 -0
  235. package/dist/src/reporting.d.ts.map +1 -0
  236. package/dist/src/reporting.js +278 -0
  237. package/dist/src/screenshots.d.ts +71 -0
  238. package/dist/src/screenshots.d.ts.map +1 -0
  239. package/dist/src/screenshots.js +141 -0
  240. package/dist/src/security/gate/index.d.ts +11 -0
  241. package/dist/src/security/gate/index.d.ts.map +1 -0
  242. package/dist/src/security/gate/index.js +65 -0
  243. package/dist/src/security/index.d.ts +30 -0
  244. package/dist/src/security/index.d.ts.map +1 -0
  245. package/dist/src/security/index.js +342 -0
  246. package/dist/src/security/normalizers/semgrep.d.ts +10 -0
  247. package/dist/src/security/normalizers/semgrep.d.ts.map +1 -0
  248. package/dist/src/security/normalizers/semgrep.js +104 -0
  249. package/dist/src/security/normalizers/trivy.d.ts +10 -0
  250. package/dist/src/security/normalizers/trivy.d.ts.map +1 -0
  251. package/dist/src/security/normalizers/trivy.js +78 -0
  252. package/dist/src/security/normalizers/zap.d.ts +10 -0
  253. package/dist/src/security/normalizers/zap.d.ts.map +1 -0
  254. package/dist/src/security/normalizers/zap.js +104 -0
  255. package/dist/src/security/scanners/semgrep.d.ts +6 -0
  256. package/dist/src/security/scanners/semgrep.d.ts.map +1 -0
  257. package/dist/src/security/scanners/semgrep.js +125 -0
  258. package/dist/src/security/scanners/trivy.d.ts +6 -0
  259. package/dist/src/security/scanners/trivy.d.ts.map +1 -0
  260. package/dist/src/security/scanners/trivy.js +115 -0
  261. package/dist/src/security/scanners/zap.d.ts +6 -0
  262. package/dist/src/security/scanners/zap.d.ts.map +1 -0
  263. package/dist/src/security/scanners/zap.js +135 -0
  264. package/dist/src/security/types.d.ts +146 -0
  265. package/dist/src/security/types.d.ts.map +1 -0
  266. package/dist/src/security/types.js +6 -0
  267. package/dist/src/securityCoverage.d.ts +116 -0
  268. package/dist/src/securityCoverage.d.ts.map +1 -0
  269. package/dist/src/securityCoverage.js +725 -0
  270. package/dist/src/summary/buildSummary.d.ts +28 -0
  271. package/dist/src/summary/buildSummary.d.ts.map +1 -0
  272. package/dist/src/summary/buildSummary.js +257 -0
  273. package/dist/src/summary/evaluateMetrics.d.ts +31 -0
  274. package/dist/src/summary/evaluateMetrics.d.ts.map +1 -0
  275. package/dist/src/summary/evaluateMetrics.js +118 -0
  276. package/dist/src/summary/index.d.ts +10 -0
  277. package/dist/src/summary/index.d.ts.map +1 -0
  278. package/dist/src/summary/index.js +22 -0
  279. package/dist/src/summary/markdownRenderer.d.ts +139 -0
  280. package/dist/src/summary/markdownRenderer.d.ts.map +1 -0
  281. package/dist/src/summary/markdownRenderer.js +459 -0
  282. package/dist/src/summary/prSummary.d.ts +24 -0
  283. package/dist/src/summary/prSummary.d.ts.map +1 -0
  284. package/dist/src/summary/prSummary.js +233 -0
  285. package/dist/src/summary/summaryTypes.d.ts +35 -0
  286. package/dist/src/summary/summaryTypes.d.ts.map +1 -0
  287. package/dist/src/summary/summaryTypes.js +27 -0
  288. package/package.json +84 -0
@@ -0,0 +1,65 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.evaluateSecurityGate = evaluateSecurityGate;
4
+ // ─── Gate evaluation ──────────────────────────────────────────────────────────
5
+ /**
6
+ * Count findings matching specific criteria.
7
+ */
8
+ function countFindings(findings, predicate) {
9
+ return findings.filter(predicate).length;
10
+ }
11
+ /**
12
+ * Evaluate the security gate against normalized findings.
13
+ * Returns a SecurityGateResult with pass/fail status and detailed reasons.
14
+ */
15
+ function evaluateSecurityGate(findings, config) {
16
+ const reasons = [];
17
+ const counts = {
18
+ critical: countFindings(findings, (f) => f.severity === 'CRITICAL'),
19
+ high: countFindings(findings, (f) => f.severity === 'HIGH'),
20
+ medium: countFindings(findings, (f) => f.severity === 'MEDIUM'),
21
+ low: countFindings(findings, (f) => f.severity === 'LOW'),
22
+ secrets: countFindings(findings, (f) => f.category === 'secret'),
23
+ misconfigHigh: countFindings(findings, (f) => f.category === 'misconfig' && (f.severity === 'HIGH' || f.severity === 'CRITICAL')),
24
+ criticalVulns: countFindings(findings, (f) => f.category === 'sca' && f.severity === 'CRITICAL'),
25
+ highVulns: countFindings(findings, (f) => f.category === 'sca' && f.severity === 'HIGH'),
26
+ };
27
+ // ── failOnCritical ────────────────────────────────────────────────────────
28
+ if (config.failOnCritical && counts.critical > 0) {
29
+ reasons.push(`${counts.critical} CRITICAL finding(s) found (failOnCritical=true)`);
30
+ }
31
+ // ── failOnHigh ────────────────────────────────────────────────────────────
32
+ if (config.failOnHigh && counts.high > 0) {
33
+ reasons.push(`${counts.high} HIGH finding(s) found (failOnHigh=true)`);
34
+ }
35
+ // ── maxMedium ─────────────────────────────────────────────────────────────
36
+ if (config.maxMedium !== undefined && counts.medium > config.maxMedium) {
37
+ reasons.push(`${counts.medium} MEDIUM finding(s) found, exceeds maxMedium=${config.maxMedium}`);
38
+ }
39
+ // ── maxLow ────────────────────────────────────────────────────────────────
40
+ if (config.maxLow !== undefined && counts.low > config.maxLow) {
41
+ reasons.push(`${counts.low} LOW finding(s) found, exceeds maxLow=${config.maxLow}`);
42
+ }
43
+ // ── maxSecrets ────────────────────────────────────────────────────────────
44
+ if (config.maxSecrets !== undefined && counts.secrets > config.maxSecrets) {
45
+ reasons.push(`${counts.secrets} secret(s) found, exceeds maxSecrets=${config.maxSecrets}`);
46
+ }
47
+ // ── maxMisconfigHigh ─────────────────────────────────────────────────────
48
+ if (config.maxMisconfigHigh !== undefined && counts.misconfigHigh > config.maxMisconfigHigh) {
49
+ reasons.push(`${counts.misconfigHigh} HIGH/CRITICAL misconfiguration(s) found, exceeds maxMisconfigHigh=${config.maxMisconfigHigh}`);
50
+ }
51
+ // ── maxCriticalVulns ─────────────────────────────────────────────────────
52
+ if (config.maxCriticalVulns !== undefined && counts.criticalVulns > config.maxCriticalVulns) {
53
+ reasons.push(`${counts.criticalVulns} CRITICAL vulnerability(ies) found, exceeds maxCriticalVulns=${config.maxCriticalVulns}`);
54
+ }
55
+ // ── maxHighVulns ─────────────────────────────────────────────────────────
56
+ if (config.maxHighVulns !== undefined && counts.highVulns > config.maxHighVulns) {
57
+ reasons.push(`${counts.highVulns} HIGH vulnerability(ies) found, exceeds maxHighVulns=${config.maxHighVulns}`);
58
+ }
59
+ return {
60
+ passed: reasons.length === 0,
61
+ reasons,
62
+ thresholds: config,
63
+ counts,
64
+ };
65
+ }
@@ -0,0 +1,30 @@
1
+ import { SecurityScanConfig, SecurityScanSummary, ScannerResult } from './types';
2
+ export * from './types';
3
+ export { normalizeSemgrepOutput } from './normalizers/semgrep';
4
+ export { normalizeTrivyOutput } from './normalizers/trivy';
5
+ export { normalizeZapOutput } from './normalizers/zap';
6
+ export { evaluateSecurityGate } from './gate/index';
7
+ /**
8
+ * Run all configured security scanners and collect findings.
9
+ */
10
+ export declare function runSecurityScanners(config: SecurityScanConfig): Promise<ScannerResult[]>;
11
+ /**
12
+ * Build a SecurityScanSummary from scanner results.
13
+ */
14
+ export declare function buildSecurityScanSummary(results: ScannerResult[], config: SecurityScanConfig): SecurityScanSummary;
15
+ /**
16
+ * Generate all security scan reports in the given directory.
17
+ */
18
+ export declare function generateSecurityScanReports(summary: SecurityScanSummary, reportsDir: string): void;
19
+ /**
20
+ * Run the complete security scan workflow:
21
+ * 1. Execute configured scanners
22
+ * 2. Normalize findings
23
+ * 3. Build summary
24
+ * 4. Evaluate gate
25
+ * 5. Generate reports
26
+ *
27
+ * Returns the SecurityScanSummary for further use.
28
+ */
29
+ export declare function runSecurityScan(config: SecurityScanConfig, reportsDir?: string): Promise<SecurityScanSummary>;
30
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/security/index.ts"],"names":[],"mappings":"AAOA,OAAO,EACL,kBAAkB,EAClB,mBAAmB,EAKnB,aAAa,EACd,MAAM,SAAS,CAAC;AAQjB,cAAc,SAAS,CAAC;AACxB,OAAO,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAC/D,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AAIpD;;GAEG;AACH,wBAAsB,mBAAmB,CACvC,MAAM,EAAE,kBAAkB,GACzB,OAAO,CAAC,aAAa,EAAE,CAAC,CAkB1B;AAID;;GAEG;AACH,wBAAgB,wBAAwB,CACtC,OAAO,EAAE,aAAa,EAAE,EACxB,MAAM,EAAE,kBAAkB,GACzB,mBAAmB,CAoDrB;AAID;;GAEG;AACH,wBAAgB,2BAA2B,CACzC,OAAO,EAAE,mBAAmB,EAC5B,UAAU,EAAE,MAAM,GACjB,IAAI,CA2EN;AAuKD;;;;;;;;;GASG;AACH,wBAAsB,eAAe,CACnC,MAAM,EAAE,kBAAkB,EAC1B,UAAU,GAAE,MAAkB,GAC7B,OAAO,CAAC,mBAAmB,CAAC,CAM9B"}
@@ -0,0 +1,342 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
36
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.evaluateSecurityGate = exports.normalizeZapOutput = exports.normalizeTrivyOutput = exports.normalizeSemgrepOutput = void 0;
40
+ exports.runSecurityScanners = runSecurityScanners;
41
+ exports.buildSecurityScanSummary = buildSecurityScanSummary;
42
+ exports.generateSecurityScanReports = generateSecurityScanReports;
43
+ exports.runSecurityScan = runSecurityScan;
44
+ /**
45
+ * Security scanning orchestrator.
46
+ * Coordinates scanner execution, normalization, report generation,
47
+ * and security gate evaluation.
48
+ */
49
+ const fs = __importStar(require("fs"));
50
+ const path = __importStar(require("path"));
51
+ const semgrep_1 = require("./scanners/semgrep");
52
+ const trivy_1 = require("./scanners/trivy");
53
+ const zap_1 = require("./scanners/zap");
54
+ const index_1 = require("./gate/index");
55
+ // ─── Re-exports ───────────────────────────────────────────────────────────────
56
+ __exportStar(require("./types"), exports);
57
+ var semgrep_2 = require("./normalizers/semgrep");
58
+ Object.defineProperty(exports, "normalizeSemgrepOutput", { enumerable: true, get: function () { return semgrep_2.normalizeSemgrepOutput; } });
59
+ var trivy_2 = require("./normalizers/trivy");
60
+ Object.defineProperty(exports, "normalizeTrivyOutput", { enumerable: true, get: function () { return trivy_2.normalizeTrivyOutput; } });
61
+ var zap_2 = require("./normalizers/zap");
62
+ Object.defineProperty(exports, "normalizeZapOutput", { enumerable: true, get: function () { return zap_2.normalizeZapOutput; } });
63
+ var index_2 = require("./gate/index");
64
+ Object.defineProperty(exports, "evaluateSecurityGate", { enumerable: true, get: function () { return index_2.evaluateSecurityGate; } });
65
+ // ─── Scanner orchestration ────────────────────────────────────────────────────
66
+ /**
67
+ * Run all configured security scanners and collect findings.
68
+ */
69
+ async function runSecurityScanners(config) {
70
+ var _a, _b, _c, _d, _e;
71
+ const workspace = path.resolve((_a = config.workspace) !== null && _a !== void 0 ? _a : '.');
72
+ const results = [];
73
+ const scanners = (_b = config.scanners) !== null && _b !== void 0 ? _b : {};
74
+ if ((_c = scanners.semgrep) === null || _c === void 0 ? void 0 : _c.enabled) {
75
+ results.push(await (0, semgrep_1.runSemgrep)(scanners.semgrep, workspace));
76
+ }
77
+ if ((_d = scanners.trivy) === null || _d === void 0 ? void 0 : _d.enabled) {
78
+ results.push(await (0, trivy_1.runTrivy)(scanners.trivy, workspace));
79
+ }
80
+ if ((_e = scanners.zap) === null || _e === void 0 ? void 0 : _e.enabled) {
81
+ results.push(await (0, zap_1.runZap)(scanners.zap));
82
+ }
83
+ return results;
84
+ }
85
+ // ─── Summary builder ──────────────────────────────────────────────────────────
86
+ /**
87
+ * Build a SecurityScanSummary from scanner results.
88
+ */
89
+ function buildSecurityScanSummary(results, config) {
90
+ var _a, _b, _c;
91
+ const allFindings = results.flatMap((r) => r.findings);
92
+ const scannersRun = results
93
+ .filter((r) => r.success || r.findings.length > 0)
94
+ .map((r) => r.scanner);
95
+ const bySeverity = {
96
+ LOW: 0,
97
+ MEDIUM: 0,
98
+ HIGH: 0,
99
+ CRITICAL: 0,
100
+ };
101
+ const byCategory = {
102
+ sast: 0,
103
+ sca: 0,
104
+ secret: 0,
105
+ misconfig: 0,
106
+ dast: 0,
107
+ auth: 0,
108
+ injection: 0,
109
+ 'data-exposure': 0,
110
+ crypto: 0,
111
+ unknown: 0,
112
+ };
113
+ const byScanner = {
114
+ semgrep: 0,
115
+ trivy: 0,
116
+ zap: 0,
117
+ gitleaks: 0,
118
+ other: 0,
119
+ };
120
+ for (const finding of allFindings) {
121
+ bySeverity[finding.severity] = ((_a = bySeverity[finding.severity]) !== null && _a !== void 0 ? _a : 0) + 1;
122
+ byCategory[finding.category] = ((_b = byCategory[finding.category]) !== null && _b !== void 0 ? _b : 0) + 1;
123
+ byScanner[finding.scanner] = ((_c = byScanner[finding.scanner]) !== null && _c !== void 0 ? _c : 0) + 1;
124
+ }
125
+ const gateResult = config.gate
126
+ ? (0, index_1.evaluateSecurityGate)(allFindings, config.gate)
127
+ : undefined;
128
+ return {
129
+ scannersRun,
130
+ totalFindings: allFindings.length,
131
+ bySeverity,
132
+ byCategory,
133
+ byScanner,
134
+ findings: allFindings,
135
+ gateResult,
136
+ };
137
+ }
138
+ // ─── Report generation ────────────────────────────────────────────────────────
139
+ /**
140
+ * Generate all security scan reports in the given directory.
141
+ */
142
+ function generateSecurityScanReports(summary, reportsDir) {
143
+ if (!fs.existsSync(reportsDir)) {
144
+ fs.mkdirSync(reportsDir, { recursive: true });
145
+ }
146
+ const { findings } = summary;
147
+ // ── security-scan-summary.json ────────────────────────────────────────────
148
+ const summaryJson = {
149
+ scannersRun: summary.scannersRun,
150
+ totalFindings: summary.totalFindings,
151
+ bySeverity: summary.bySeverity,
152
+ byCategory: summary.byCategory,
153
+ byScanner: summary.byScanner,
154
+ gateResult: summary.gateResult,
155
+ };
156
+ fs.writeFileSync(path.join(reportsDir, 'security-scan-summary.json'), JSON.stringify(summaryJson, null, 2), 'utf-8');
157
+ // ── security-sast.json ────────────────────────────────────────────────────
158
+ const sast = findings.filter((f) => f.scanner === 'semgrep' || f.category === 'sast' || f.category === 'injection');
159
+ fs.writeFileSync(path.join(reportsDir, 'security-sast.json'), JSON.stringify(sast, null, 2), 'utf-8');
160
+ // ── security-dependencies.json ────────────────────────────────────────────
161
+ const deps = findings.filter((f) => f.category === 'sca');
162
+ fs.writeFileSync(path.join(reportsDir, 'security-dependencies.json'), JSON.stringify(deps, null, 2), 'utf-8');
163
+ // ── security-secrets.json ─────────────────────────────────────────────────
164
+ const secrets = findings.filter((f) => f.category === 'secret');
165
+ fs.writeFileSync(path.join(reportsDir, 'security-secrets.json'), JSON.stringify(secrets, null, 2), 'utf-8');
166
+ // ── security-misconfig.json ───────────────────────────────────────────────
167
+ const misconfig = findings.filter((f) => f.category === 'misconfig');
168
+ fs.writeFileSync(path.join(reportsDir, 'security-misconfig.json'), JSON.stringify(misconfig, null, 2), 'utf-8');
169
+ // ── security-dast.json ────────────────────────────────────────────────────
170
+ const dast = findings.filter((f) => f.scanner === 'zap' || f.category === 'dast');
171
+ fs.writeFileSync(path.join(reportsDir, 'security-dast.json'), JSON.stringify(dast, null, 2), 'utf-8');
172
+ // ── security-ai-summary.md ────────────────────────────────────────────────
173
+ const md = buildAiSummaryMarkdown(summary);
174
+ fs.writeFileSync(path.join(reportsDir, 'security-ai-summary.md'), md, 'utf-8');
175
+ // ── security-scan-summary.html ────────────────────────────────────────────
176
+ const html = buildSummaryHtml(summary);
177
+ fs.writeFileSync(path.join(reportsDir, 'security-scan-summary.html'), html, 'utf-8');
178
+ }
179
+ // ─── AI-friendly Markdown report ──────────────────────────────────────────────
180
+ function buildAiSummaryMarkdown(summary) {
181
+ const { findings, gateResult } = summary;
182
+ const gate = gateResult ? (gateResult.passed ? '✅ PASSED' : '❌ FAILED') : 'Not configured';
183
+ const topSecrets = findings.filter((f) => f.category === 'secret').slice(0, 5);
184
+ const topCritical = findings
185
+ .filter((f) => f.severity === 'CRITICAL' || f.severity === 'HIGH')
186
+ .slice(0, 10);
187
+ const listFindings = (items) => items.length === 0
188
+ ? '- None\n'
189
+ : items
190
+ .map((f) => { var _a; return `- **[${f.severity}]** ${f.title}${f.filePath ? ` — \`${f.filePath}\`` : ''}${f.packageName ? ` (${f.packageName} ${(_a = f.installedVersion) !== null && _a !== void 0 ? _a : ''})` : ''}`; })
191
+ .join('\n') + '\n';
192
+ return `# Security Scan AI Summary
193
+
194
+ ## Scanners Executed
195
+ ${summary.scannersRun.length > 0 ? summary.scannersRun.map((s) => `- ${s}`).join('\n') : '- None'}
196
+
197
+ ## Security Gate
198
+ **Status:** ${gate}
199
+ ${gateResult && !gateResult.passed ? `\n**Failure reasons:**\n${gateResult.reasons.map((r) => `- ${r}`).join('\n')}` : ''}
200
+
201
+ ## Findings Summary
202
+
203
+ | Severity | Count |
204
+ |----------|-------|
205
+ | CRITICAL | ${summary.bySeverity.CRITICAL} |
206
+ | HIGH | ${summary.bySeverity.HIGH} |
207
+ | MEDIUM | ${summary.bySeverity.MEDIUM} |
208
+ | LOW | ${summary.bySeverity.LOW} |
209
+
210
+ | Category | Count |
211
+ |----------|-------|
212
+ ${Object.entries(summary.byCategory)
213
+ .filter(([, v]) => v > 0)
214
+ .map(([k, v]) => `| ${k} | ${v} |`)
215
+ .join('\n')}
216
+
217
+ ## Top Risks
218
+
219
+ ### Secrets Found (${findings.filter((f) => f.category === 'secret').length})
220
+ ${listFindings(topSecrets)}
221
+
222
+ ### Critical / High Findings (${topCritical.length} shown)
223
+ ${listFindings(topCritical)}
224
+
225
+ ## Recommended Remediation Order
226
+
227
+ 1. **Secrets** — revoke and rotate immediately (${findings.filter((f) => f.category === 'secret').length} found)
228
+ 2. **Critical Vulnerabilities** — patch or mitigate (${summary.bySeverity.CRITICAL} found)
229
+ 3. **Auth Flaws** — fix authentication/authorization issues (${summary.byCategory.auth} found)
230
+ 4. **Injection Risks** — fix injection vulnerabilities (${summary.byCategory.injection} found)
231
+ 5. **Misconfigurations** — resolve HIGH/CRITICAL misconfigurations (${summary.byCategory.misconfig} found)
232
+ 6. **Medium Findings** — address remaining MEDIUM issues (${summary.bySeverity.MEDIUM} found)
233
+ `;
234
+ }
235
+ // ─── HTML summary report ──────────────────────────────────────────────────────
236
+ function buildSummaryHtml(summary) {
237
+ const gateStatus = summary.gateResult
238
+ ? summary.gateResult.passed
239
+ ? '<span style="color:green">✅ PASSED</span>'
240
+ : `<span style="color:red">❌ FAILED</span>`
241
+ : '<span style="color:gray">Not configured</span>';
242
+ const gateReasons = summary.gateResult && !summary.gateResult.passed
243
+ ? `<ul>${summary.gateResult.reasons.map((r) => `<li>${r}</li>`).join('')}</ul>`
244
+ : '';
245
+ const severityRows = ['CRITICAL', 'HIGH', 'MEDIUM', 'LOW']
246
+ .map((s) => {
247
+ const count = summary.bySeverity[s];
248
+ const cls = s === 'CRITICAL' ? 'bad' : s === 'HIGH' ? 'bad' : s === 'MEDIUM' ? 'warn' : '';
249
+ return `<tr class="${cls}"><td>${s}</td><td>${count}</td></tr>`;
250
+ })
251
+ .join('\n');
252
+ const categoryRows = Object.entries(summary.byCategory)
253
+ .filter(([, v]) => v > 0)
254
+ .map(([k, v]) => `<tr><td>${k}</td><td>${v}</td></tr>`)
255
+ .join('\n');
256
+ const findingRows = summary.findings
257
+ .slice(0, 200)
258
+ .map((f) => {
259
+ var _a;
260
+ const cls = f.severity === 'CRITICAL' || f.severity === 'HIGH'
261
+ ? 'bad'
262
+ : f.severity === 'MEDIUM'
263
+ ? 'warn'
264
+ : '';
265
+ const file = f.filePath ? `<code>${f.filePath}${f.lineStart ? `:${f.lineStart}` : ''}</code>` : '—';
266
+ const pkg = f.packageName ? `${f.packageName} ${(_a = f.installedVersion) !== null && _a !== void 0 ? _a : ''}` : '—';
267
+ return `<tr class="${cls}">
268
+ <td>${f.scanner}</td>
269
+ <td>${f.severity}</td>
270
+ <td>${f.category}</td>
271
+ <td>${f.title}</td>
272
+ <td>${file}</td>
273
+ <td>${pkg}</td>
274
+ </tr>`;
275
+ })
276
+ .join('\n');
277
+ return `<!DOCTYPE html>
278
+ <html lang="en">
279
+ <head>
280
+ <meta charset="UTF-8">
281
+ <title>Security Scan Summary</title>
282
+ <style>
283
+ body { font-family: sans-serif; padding: 2rem; }
284
+ h1, h2 { margin-bottom: 0.5rem; }
285
+ .gate { font-size: 1.2rem; margin-bottom: 1rem; }
286
+ table { border-collapse: collapse; width: 100%; margin-bottom: 2rem; }
287
+ th, td { border: 1px solid #ccc; padding: 0.5rem 1rem; text-align: left; }
288
+ th { background: #f0f0f0; }
289
+ tr.bad { background: #ffe6e6; }
290
+ tr.warn { background: #fff9e6; }
291
+ </style>
292
+ </head>
293
+ <body>
294
+ <h1>Security Scan Summary</h1>
295
+ <div class="gate">
296
+ Security Gate: ${gateStatus}
297
+ ${gateReasons}
298
+ </div>
299
+
300
+ <h2>Scanners Run</h2>
301
+ <p>${summary.scannersRun.length > 0 ? summary.scannersRun.join(', ') : 'None'}</p>
302
+
303
+ <h2>Findings by Severity</h2>
304
+ <table>
305
+ <thead><tr><th>Severity</th><th>Count</th></tr></thead>
306
+ <tbody>${severityRows}</tbody>
307
+ </table>
308
+
309
+ <h2>Findings by Category</h2>
310
+ <table>
311
+ <thead><tr><th>Category</th><th>Count</th></tr></thead>
312
+ <tbody>${categoryRows || '<tr><td colspan="2">No findings</td></tr>'}</tbody>
313
+ </table>
314
+
315
+ <h2>Findings Detail (up to 200)</h2>
316
+ <table>
317
+ <thead>
318
+ <tr><th>Scanner</th><th>Severity</th><th>Category</th><th>Title</th><th>File</th><th>Package</th></tr>
319
+ </thead>
320
+ <tbody>${findingRows || '<tr><td colspan="6">No findings</td></tr>'}</tbody>
321
+ </table>
322
+ </body>
323
+ </html>`;
324
+ }
325
+ // ─── Full security scan workflow ───────────────────────────────────────────────
326
+ /**
327
+ * Run the complete security scan workflow:
328
+ * 1. Execute configured scanners
329
+ * 2. Normalize findings
330
+ * 3. Build summary
331
+ * 4. Evaluate gate
332
+ * 5. Generate reports
333
+ *
334
+ * Returns the SecurityScanSummary for further use.
335
+ */
336
+ async function runSecurityScan(config, reportsDir = 'reports') {
337
+ const results = await runSecurityScanners(config);
338
+ const summary = buildSecurityScanSummary(results, config);
339
+ const resolvedDir = path.resolve(reportsDir);
340
+ generateSecurityScanReports(summary, resolvedDir);
341
+ return summary;
342
+ }
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Semgrep output normalizer.
3
+ * Converts Semgrep JSON findings to the common SecurityFinding model.
4
+ */
5
+ import { SecurityFinding } from '../types';
6
+ /**
7
+ * Parse a Semgrep JSON output buffer and return normalized SecurityFindings.
8
+ */
9
+ export declare function normalizeSemgrepOutput(raw: unknown): SecurityFinding[];
10
+ //# sourceMappingURL=semgrep.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"semgrep.d.ts","sourceRoot":"","sources":["../../../../src/security/normalizers/semgrep.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EACL,eAAe,EAGhB,MAAM,UAAU,CAAC;AAqHlB;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,OAAO,GAAG,eAAe,EAAE,CAuBtE"}
@@ -0,0 +1,104 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.normalizeSemgrepOutput = normalizeSemgrepOutput;
4
+ // ─── Severity mapping ─────────────────────────────────────────────────────────
5
+ function mapSemgrepSeverity(severity) {
6
+ switch ((severity !== null && severity !== void 0 ? severity : '').toUpperCase()) {
7
+ case 'CRITICAL':
8
+ return 'CRITICAL';
9
+ case 'ERROR':
10
+ return 'HIGH';
11
+ case 'WARNING':
12
+ case 'WARN':
13
+ return 'MEDIUM';
14
+ case 'INFO':
15
+ case 'NOTE':
16
+ return 'LOW';
17
+ default:
18
+ return 'MEDIUM';
19
+ }
20
+ }
21
+ // ─── Category mapping ─────────────────────────────────────────────────────────
22
+ function mapSemgrepCategory(checkId, metadata) {
23
+ var _a;
24
+ const cat = ((_a = metadata === null || metadata === void 0 ? void 0 : metadata.category) !== null && _a !== void 0 ? _a : '').toLowerCase();
25
+ if (cat === 'security') {
26
+ // Derive more specific category from the rule ID and CWE/OWASP tags
27
+ const idLower = checkId.toLowerCase();
28
+ const cwes = normaliseTags(metadata === null || metadata === void 0 ? void 0 : metadata.cwe);
29
+ const owasp = normaliseTags(metadata === null || metadata === void 0 ? void 0 : metadata.owasp);
30
+ if (cwes.some((c) => c.includes('89') || c.includes('943')) ||
31
+ idLower.includes('injection') ||
32
+ idLower.includes('sqli') ||
33
+ idLower.includes('xss')) {
34
+ return 'injection';
35
+ }
36
+ if (cwes.some((c) => c.includes('798') || c.includes('259') || c.includes('321')) ||
37
+ idLower.includes('hardcoded') ||
38
+ idLower.includes('secret') ||
39
+ idLower.includes('password')) {
40
+ return 'secret';
41
+ }
42
+ if (cwes.some((c) => c.includes('287') || c.includes('306') || c.includes('384')) ||
43
+ idLower.includes('auth')) {
44
+ return 'auth';
45
+ }
46
+ if (cwes.some((c) => c.includes('311') || c.includes('319') || c.includes('327')) ||
47
+ idLower.includes('crypto') ||
48
+ idLower.includes('cipher') ||
49
+ idLower.includes('tls') ||
50
+ idLower.includes('ssl')) {
51
+ return 'crypto';
52
+ }
53
+ if (owasp.some((o) => o.includes('A3') || o.includes('sensitive'))) {
54
+ return 'data-exposure';
55
+ }
56
+ return 'sast';
57
+ }
58
+ if (cat.includes('secret') || cat.includes('credential'))
59
+ return 'secret';
60
+ if (cat.includes('inject'))
61
+ return 'injection';
62
+ if (cat.includes('auth'))
63
+ return 'auth';
64
+ if (cat.includes('crypto') || cat.includes('cipher'))
65
+ return 'crypto';
66
+ if (cat.includes('exposure') || cat.includes('disclosure'))
67
+ return 'data-exposure';
68
+ if (cat.includes('config') || cat.includes('misconfiguration'))
69
+ return 'misconfig';
70
+ return 'sast';
71
+ }
72
+ function normaliseTags(value) {
73
+ if (!value)
74
+ return [];
75
+ return Array.isArray(value) ? value : [value];
76
+ }
77
+ // ─── Normalizer ───────────────────────────────────────────────────────────────
78
+ /**
79
+ * Parse a Semgrep JSON output buffer and return normalized SecurityFindings.
80
+ */
81
+ function normalizeSemgrepOutput(raw) {
82
+ var _a;
83
+ const data = raw;
84
+ const results = (_a = data.results) !== null && _a !== void 0 ? _a : [];
85
+ return results.map((r) => {
86
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
87
+ const cwe = normaliseTags((_b = (_a = r.extra) === null || _a === void 0 ? void 0 : _a.metadata) === null || _b === void 0 ? void 0 : _b.cwe);
88
+ const owasp = normaliseTags((_d = (_c = r.extra) === null || _c === void 0 ? void 0 : _c.metadata) === null || _d === void 0 ? void 0 : _d.owasp);
89
+ return {
90
+ scanner: 'semgrep',
91
+ category: mapSemgrepCategory(r.checkId, (_e = r.extra) === null || _e === void 0 ? void 0 : _e.metadata),
92
+ severity: mapSemgrepSeverity((_f = r.extra) === null || _f === void 0 ? void 0 : _f.severity),
93
+ title: (_h = (_g = r.extra) === null || _g === void 0 ? void 0 : _g.message) !== null && _h !== void 0 ? _h : r.checkId,
94
+ description: (_j = r.extra) === null || _j === void 0 ? void 0 : _j.lines,
95
+ ruleId: r.checkId,
96
+ cwe: cwe.length > 0 ? cwe : undefined,
97
+ owasp: owasp.length > 0 ? owasp : undefined,
98
+ filePath: r.path,
99
+ lineStart: (_k = r.start) === null || _k === void 0 ? void 0 : _k.line,
100
+ lineEnd: (_l = r.end) === null || _l === void 0 ? void 0 : _l.line,
101
+ scannerNativePayload: r,
102
+ };
103
+ });
104
+ }
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Trivy output normalizer.
3
+ * Converts Trivy JSON findings to the common SecurityFinding model.
4
+ */
5
+ import { SecurityFinding } from '../types';
6
+ /**
7
+ * Parse Trivy JSON output and return normalized SecurityFindings.
8
+ */
9
+ export declare function normalizeTrivyOutput(raw: unknown): SecurityFinding[];
10
+ //# sourceMappingURL=trivy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"trivy.d.ts","sourceRoot":"","sources":["../../../../src/security/normalizers/trivy.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EACL,eAAe,EAGhB,MAAM,UAAU,CAAC;AAqFlB;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,OAAO,GAAG,eAAe,EAAE,CAgEpE"}
@@ -0,0 +1,78 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.normalizeTrivyOutput = normalizeTrivyOutput;
4
+ // ─── Severity mapping ─────────────────────────────────────────────────────────
5
+ function mapTrivySeverity(severity) {
6
+ switch ((severity !== null && severity !== void 0 ? severity : '').toUpperCase()) {
7
+ case 'CRITICAL': return 'CRITICAL';
8
+ case 'HIGH': return 'HIGH';
9
+ case 'MEDIUM': return 'MEDIUM';
10
+ case 'LOW':
11
+ case 'UNKNOWN':
12
+ default: return 'LOW';
13
+ }
14
+ }
15
+ // ─── Normalizer ───────────────────────────────────────────────────────────────
16
+ /**
17
+ * Parse Trivy JSON output and return normalized SecurityFindings.
18
+ */
19
+ function normalizeTrivyOutput(raw) {
20
+ var _a, _b, _c, _d, _e, _f, _g;
21
+ const data = raw;
22
+ const results = (_a = data.Results) !== null && _a !== void 0 ? _a : [];
23
+ const findings = [];
24
+ for (const result of results) {
25
+ const filePath = result.Target;
26
+ // ── Vulnerabilities ──────────────────────────────────────────────────────
27
+ for (const vuln of (_b = result.Vulnerabilities) !== null && _b !== void 0 ? _b : []) {
28
+ const category = 'sca';
29
+ findings.push({
30
+ scanner: 'trivy',
31
+ category,
32
+ severity: mapTrivySeverity(vuln.Severity),
33
+ title: (_c = vuln.Title) !== null && _c !== void 0 ? _c : vuln.VulnerabilityID,
34
+ description: vuln.Description,
35
+ ruleId: vuln.VulnerabilityID,
36
+ cve: [vuln.VulnerabilityID],
37
+ cwe: vuln.CweIDs,
38
+ filePath,
39
+ packageName: vuln.PkgName,
40
+ installedVersion: vuln.InstalledVersion,
41
+ fixedVersion: vuln.FixedVersion,
42
+ scannerNativePayload: vuln,
43
+ });
44
+ }
45
+ // ── Secrets ──────────────────────────────────────────────────────────────
46
+ for (const secret of (_d = result.Secrets) !== null && _d !== void 0 ? _d : []) {
47
+ findings.push({
48
+ scanner: 'trivy',
49
+ category: 'secret',
50
+ severity: mapTrivySeverity(secret.Severity),
51
+ title: secret.Title,
52
+ description: secret.Match,
53
+ ruleId: secret.RuleID,
54
+ filePath,
55
+ lineStart: secret.StartLine,
56
+ lineEnd: secret.EndLine,
57
+ secretType: secret.Category,
58
+ scannerNativePayload: secret,
59
+ });
60
+ }
61
+ // ── Misconfigurations ────────────────────────────────────────────────────
62
+ for (const mis of (_e = result.Misconfigurations) !== null && _e !== void 0 ? _e : []) {
63
+ findings.push({
64
+ scanner: 'trivy',
65
+ category: 'misconfig',
66
+ severity: mapTrivySeverity(mis.Severity),
67
+ title: mis.Title,
68
+ description: mis.Description,
69
+ ruleId: mis.ID,
70
+ filePath,
71
+ lineStart: (_f = mis.CauseMetadata) === null || _f === void 0 ? void 0 : _f.StartLine,
72
+ lineEnd: (_g = mis.CauseMetadata) === null || _g === void 0 ? void 0 : _g.EndLine,
73
+ scannerNativePayload: mis,
74
+ });
75
+ }
76
+ }
77
+ return findings;
78
+ }