@vk.amogh/trace 2.1.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 (249) hide show
  1. package/README.md +208 -0
  2. package/bin/trace.js +112 -0
  3. package/package.json +46 -0
  4. package/pyproject.toml +39 -0
  5. package/src/trace_engine/__init__.py +8 -0
  6. package/src/trace_engine/__pycache__/__init__.cpython-311.pyc +0 -0
  7. package/src/trace_engine/__pycache__/cli.cpython-311.pyc +0 -0
  8. package/src/trace_engine/__pycache__/doctor.cpython-311.pyc +0 -0
  9. package/src/trace_engine/__pycache__/interactive.cpython-311.pyc +0 -0
  10. package/src/trace_engine/__pycache__/verify.cpython-311.pyc +0 -0
  11. package/src/trace_engine/ai/__init__.py +7 -0
  12. package/src/trace_engine/ai/__pycache__/__init__.cpython-311.pyc +0 -0
  13. package/src/trace_engine/ai/__pycache__/base.cpython-311.pyc +0 -0
  14. package/src/trace_engine/ai/__pycache__/ollama.cpython-311.pyc +0 -0
  15. package/src/trace_engine/ai/__pycache__/planner.cpython-311.pyc +0 -0
  16. package/src/trace_engine/ai/base.py +23 -0
  17. package/src/trace_engine/ai/ollama.py +50 -0
  18. package/src/trace_engine/ai/planner.py +40 -0
  19. package/src/trace_engine/apm/__init__.py +18 -0
  20. package/src/trace_engine/apm/__pycache__/__init__.cpython-311.pyc +0 -0
  21. package/src/trace_engine/apm/__pycache__/builder.cpython-311.pyc +0 -0
  22. package/src/trace_engine/apm/__pycache__/edges.cpython-311.pyc +0 -0
  23. package/src/trace_engine/apm/__pycache__/model.cpython-311.pyc +0 -0
  24. package/src/trace_engine/apm/__pycache__/nodes.cpython-311.pyc +0 -0
  25. package/src/trace_engine/apm/__pycache__/serialization.cpython-311.pyc +0 -0
  26. package/src/trace_engine/apm/builder.py +208 -0
  27. package/src/trace_engine/apm/edges.py +25 -0
  28. package/src/trace_engine/apm/model.py +107 -0
  29. package/src/trace_engine/apm/nodes.py +27 -0
  30. package/src/trace_engine/apm/serialization.py +105 -0
  31. package/src/trace_engine/benchmark/__init__.py +5 -0
  32. package/src/trace_engine/benchmark/__pycache__/__init__.cpython-311.pyc +0 -0
  33. package/src/trace_engine/benchmark/__pycache__/owasp.cpython-311.pyc +0 -0
  34. package/src/trace_engine/benchmark/owasp.py +183 -0
  35. package/src/trace_engine/cli.py +1184 -0
  36. package/src/trace_engine/config/__init__.py +35 -0
  37. package/src/trace_engine/config/__pycache__/__init__.cpython-311.pyc +0 -0
  38. package/src/trace_engine/config/__pycache__/defaults.cpython-311.pyc +0 -0
  39. package/src/trace_engine/config/__pycache__/loader.cpython-311.pyc +0 -0
  40. package/src/trace_engine/config/__pycache__/settings.cpython-311.pyc +0 -0
  41. package/src/trace_engine/config/defaults.py +48 -0
  42. package/src/trace_engine/config/loader.py +64 -0
  43. package/src/trace_engine/config/settings.py +72 -0
  44. package/src/trace_engine/doctor.py +250 -0
  45. package/src/trace_engine/findings/__init__.py +15 -0
  46. package/src/trace_engine/findings/__pycache__/__init__.cpython-311.pyc +0 -0
  47. package/src/trace_engine/findings/__pycache__/correlate.cpython-311.pyc +0 -0
  48. package/src/trace_engine/findings/__pycache__/model.cpython-311.pyc +0 -0
  49. package/src/trace_engine/findings/__pycache__/recommendations.cpython-311.pyc +0 -0
  50. package/src/trace_engine/findings/__pycache__/store.cpython-311.pyc +0 -0
  51. package/src/trace_engine/findings/correlate.py +103 -0
  52. package/src/trace_engine/findings/model.py +40 -0
  53. package/src/trace_engine/findings/recommendations.py +35 -0
  54. package/src/trace_engine/findings/store.py +39 -0
  55. package/src/trace_engine/framework/__init__.py +58 -0
  56. package/src/trace_engine/framework/__pycache__/__init__.cpython-311.pyc +0 -0
  57. package/src/trace_engine/framework/__pycache__/base.cpython-311.pyc +0 -0
  58. package/src/trace_engine/framework/__pycache__/csharp.cpython-311.pyc +0 -0
  59. package/src/trace_engine/framework/__pycache__/dart.cpython-311.pyc +0 -0
  60. package/src/trace_engine/framework/__pycache__/django.cpython-311.pyc +0 -0
  61. package/src/trace_engine/framework/__pycache__/express.cpython-311.pyc +0 -0
  62. package/src/trace_engine/framework/__pycache__/fastapi.cpython-311.pyc +0 -0
  63. package/src/trace_engine/framework/__pycache__/flask.cpython-311.pyc +0 -0
  64. package/src/trace_engine/framework/__pycache__/go.cpython-311.pyc +0 -0
  65. package/src/trace_engine/framework/__pycache__/nextjs.cpython-311.pyc +0 -0
  66. package/src/trace_engine/framework/__pycache__/php.cpython-311.pyc +0 -0
  67. package/src/trace_engine/framework/__pycache__/react_router.cpython-311.pyc +0 -0
  68. package/src/trace_engine/framework/__pycache__/ruby.cpython-311.pyc +0 -0
  69. package/src/trace_engine/framework/__pycache__/rust.cpython-311.pyc +0 -0
  70. package/src/trace_engine/framework/__pycache__/springboot.cpython-311.pyc +0 -0
  71. package/src/trace_engine/framework/base.py +49 -0
  72. package/src/trace_engine/framework/csharp.py +111 -0
  73. package/src/trace_engine/framework/dart.py +152 -0
  74. package/src/trace_engine/framework/django.py +188 -0
  75. package/src/trace_engine/framework/express.py +82 -0
  76. package/src/trace_engine/framework/fastapi.py +135 -0
  77. package/src/trace_engine/framework/flask.py +108 -0
  78. package/src/trace_engine/framework/go.py +94 -0
  79. package/src/trace_engine/framework/nextjs.py +200 -0
  80. package/src/trace_engine/framework/php.py +98 -0
  81. package/src/trace_engine/framework/react_router.py +331 -0
  82. package/src/trace_engine/framework/ruby.py +69 -0
  83. package/src/trace_engine/framework/rust.py +101 -0
  84. package/src/trace_engine/framework/springboot.py +145 -0
  85. package/src/trace_engine/harness/__init__.py +19 -0
  86. package/src/trace_engine/harness/__pycache__/__init__.cpython-311.pyc +0 -0
  87. package/src/trace_engine/harness/__pycache__/benchmark.cpython-311.pyc +0 -0
  88. package/src/trace_engine/harness/__pycache__/context.cpython-311.pyc +0 -0
  89. package/src/trace_engine/harness/__pycache__/engine.cpython-311.pyc +0 -0
  90. package/src/trace_engine/harness/__pycache__/patcher.cpython-311.pyc +0 -0
  91. package/src/trace_engine/harness/__pycache__/remediators.cpython-311.pyc +0 -0
  92. package/src/trace_engine/harness/benchmark.py +55 -0
  93. package/src/trace_engine/harness/context.py +49 -0
  94. package/src/trace_engine/harness/engine.py +187 -0
  95. package/src/trace_engine/harness/patcher.py +143 -0
  96. package/src/trace_engine/harness/remediators.py +307 -0
  97. package/src/trace_engine/ingest/__init__.py +15 -0
  98. package/src/trace_engine/ingest/__pycache__/__init__.cpython-311.pyc +0 -0
  99. package/src/trace_engine/ingest/__pycache__/files.cpython-311.pyc +0 -0
  100. package/src/trace_engine/ingest/__pycache__/hashing.cpython-311.pyc +0 -0
  101. package/src/trace_engine/ingest/__pycache__/ignore.cpython-311.pyc +0 -0
  102. package/src/trace_engine/ingest/__pycache__/repository.cpython-311.pyc +0 -0
  103. package/src/trace_engine/ingest/files.py +60 -0
  104. package/src/trace_engine/ingest/hashing.py +21 -0
  105. package/src/trace_engine/ingest/ignore.py +108 -0
  106. package/src/trace_engine/ingest/repository.py +50 -0
  107. package/src/trace_engine/intelligence/__init__.py +15 -0
  108. package/src/trace_engine/intelligence/__pycache__/__init__.cpython-311.pyc +0 -0
  109. package/src/trace_engine/intelligence/__pycache__/evaluation.cpython-311.pyc +0 -0
  110. package/src/trace_engine/intelligence/__pycache__/orchestrator.cpython-311.pyc +0 -0
  111. package/src/trace_engine/intelligence/__pycache__/tracebench.cpython-311.pyc +0 -0
  112. package/src/trace_engine/intelligence/evaluation.py +828 -0
  113. package/src/trace_engine/intelligence/laya/__init__.py +19 -0
  114. package/src/trace_engine/intelligence/laya/__pycache__/__init__.cpython-311.pyc +0 -0
  115. package/src/trace_engine/intelligence/laya/__pycache__/prompts.cpython-311.pyc +0 -0
  116. package/src/trace_engine/intelligence/laya/__pycache__/router.cpython-311.pyc +0 -0
  117. package/src/trace_engine/intelligence/laya/__pycache__/schemas.cpython-311.pyc +0 -0
  118. package/src/trace_engine/intelligence/laya/__pycache__/telemetry.cpython-311.pyc +0 -0
  119. package/src/trace_engine/intelligence/laya/__pycache__/thresholds.cpython-311.pyc +0 -0
  120. package/src/trace_engine/intelligence/laya/prompts.py +67 -0
  121. package/src/trace_engine/intelligence/laya/router.py +352 -0
  122. package/src/trace_engine/intelligence/laya/schemas.py +56 -0
  123. package/src/trace_engine/intelligence/laya/telemetry.py +48 -0
  124. package/src/trace_engine/intelligence/laya/thresholds.py +12 -0
  125. package/src/trace_engine/intelligence/orchestrator.py +130 -0
  126. package/src/trace_engine/intelligence/securebert/__init__.py +6 -0
  127. package/src/trace_engine/intelligence/securebert/__pycache__/__init__.cpython-311.pyc +0 -0
  128. package/src/trace_engine/intelligence/securebert/__pycache__/cache.cpython-311.pyc +0 -0
  129. package/src/trace_engine/intelligence/securebert/__pycache__/classifier.cpython-311.pyc +0 -0
  130. package/src/trace_engine/intelligence/securebert/cache.py +37 -0
  131. package/src/trace_engine/intelligence/securebert/classifier.py +240 -0
  132. package/src/trace_engine/intelligence/tracebench.py +61 -0
  133. package/src/trace_engine/intelligence/training/__init__.py +21 -0
  134. package/src/trace_engine/intelligence/training/__pycache__/__init__.cpython-311.pyc +0 -0
  135. package/src/trace_engine/intelligence/training/__pycache__/dataset.cpython-311.pyc +0 -0
  136. package/src/trace_engine/intelligence/training/__pycache__/dataset_importers.cpython-311.pyc +0 -0
  137. package/src/trace_engine/intelligence/training/__pycache__/laya_trainer.cpython-311.pyc +0 -0
  138. package/src/trace_engine/intelligence/training/__pycache__/lora_system2.cpython-311.pyc +0 -0
  139. package/src/trace_engine/intelligence/training/__pycache__/morefixes_pipeline.cpython-311.pyc +0 -0
  140. package/src/trace_engine/intelligence/training/__pycache__/slicer.cpython-311.pyc +0 -0
  141. package/src/trace_engine/intelligence/training/__pycache__/train_all.cpython-311.pyc +0 -0
  142. package/src/trace_engine/intelligence/training/__pycache__/trainer.cpython-311.pyc +0 -0
  143. package/src/trace_engine/intelligence/training/dataset.py +320 -0
  144. package/src/trace_engine/intelligence/training/dataset_importers.py +349 -0
  145. package/src/trace_engine/intelligence/training/laya_trainer.py +678 -0
  146. package/src/trace_engine/intelligence/training/lora_system2.py +162 -0
  147. package/src/trace_engine/intelligence/training/morefixes_pipeline.py +463 -0
  148. package/src/trace_engine/intelligence/training/slicer.py +129 -0
  149. package/src/trace_engine/intelligence/training/train_all.py +1009 -0
  150. package/src/trace_engine/intelligence/training/trainer.py +321 -0
  151. package/src/trace_engine/interactive.py +623 -0
  152. package/src/trace_engine/mcp/__init__.py +6 -0
  153. package/src/trace_engine/mcp/__pycache__/__init__.cpython-311.pyc +0 -0
  154. package/src/trace_engine/mcp/__pycache__/config.cpython-311.pyc +0 -0
  155. package/src/trace_engine/mcp/__pycache__/server.cpython-311.pyc +0 -0
  156. package/src/trace_engine/mcp/config.py +42 -0
  157. package/src/trace_engine/mcp/server.py +398 -0
  158. package/src/trace_engine/output/__init__.py +28 -0
  159. package/src/trace_engine/output/__pycache__/__init__.cpython-311.pyc +0 -0
  160. package/src/trace_engine/output/__pycache__/html.cpython-311.pyc +0 -0
  161. package/src/trace_engine/output/__pycache__/markdown.cpython-311.pyc +0 -0
  162. package/src/trace_engine/output/__pycache__/sarif.cpython-311.pyc +0 -0
  163. package/src/trace_engine/output/__pycache__/terminal.cpython-311.pyc +0 -0
  164. package/src/trace_engine/output/html.py +142 -0
  165. package/src/trace_engine/output/markdown.py +65 -0
  166. package/src/trace_engine/output/sarif.py +180 -0
  167. package/src/trace_engine/output/terminal.py +537 -0
  168. package/src/trace_engine/parsing/__init__.py +26 -0
  169. package/src/trace_engine/parsing/__pycache__/__init__.cpython-311.pyc +0 -0
  170. package/src/trace_engine/parsing/__pycache__/calls.cpython-311.pyc +0 -0
  171. package/src/trace_engine/parsing/__pycache__/language.cpython-311.pyc +0 -0
  172. package/src/trace_engine/parsing/__pycache__/locations.cpython-311.pyc +0 -0
  173. package/src/trace_engine/parsing/__pycache__/parser.cpython-311.pyc +0 -0
  174. package/src/trace_engine/parsing/__pycache__/symbols.cpython-311.pyc +0 -0
  175. package/src/trace_engine/parsing/calls.py +14 -0
  176. package/src/trace_engine/parsing/language.py +24 -0
  177. package/src/trace_engine/parsing/locations.py +17 -0
  178. package/src/trace_engine/parsing/parser.py +465 -0
  179. package/src/trace_engine/parsing/symbols.py +45 -0
  180. package/src/trace_engine/plugin/__init__.py +157 -0
  181. package/src/trace_engine/plugin/__pycache__/__init__.cpython-311.pyc +0 -0
  182. package/src/trace_engine/plugin/__pycache__/evaluator.cpython-311.pyc +0 -0
  183. package/src/trace_engine/plugin/__pycache__/swebench_adapter.cpython-311.pyc +0 -0
  184. package/src/trace_engine/plugin/__pycache__/task.cpython-311.pyc +0 -0
  185. package/src/trace_engine/plugin/bundle/hooks.json +24 -0
  186. package/src/trace_engine/plugin/bundle/mcp_config.json +11 -0
  187. package/src/trace_engine/plugin/bundle/plugin.json +20 -0
  188. package/src/trace_engine/plugin/bundle/rules/security_remediation.md +40 -0
  189. package/src/trace_engine/plugin/bundle/skills/trace-security-harness/SKILL.md +118 -0
  190. package/src/trace_engine/plugin/evaluator.py +105 -0
  191. package/src/trace_engine/plugin/swebench_adapter.py +96 -0
  192. package/src/trace_engine/plugin/task.py +48 -0
  193. package/src/trace_engine/policy/__init__.py +5 -0
  194. package/src/trace_engine/policy/__pycache__/__init__.cpython-311.pyc +0 -0
  195. package/src/trace_engine/policy/__pycache__/scope.cpython-311.pyc +0 -0
  196. package/src/trace_engine/policy/scope.py +80 -0
  197. package/src/trace_engine/runtime/__init__.py +7 -0
  198. package/src/trace_engine/runtime/__pycache__/__init__.cpython-311.pyc +0 -0
  199. package/src/trace_engine/runtime/__pycache__/client.cpython-311.pyc +0 -0
  200. package/src/trace_engine/runtime/__pycache__/observations.cpython-311.pyc +0 -0
  201. package/src/trace_engine/runtime/__pycache__/target.cpython-311.pyc +0 -0
  202. package/src/trace_engine/runtime/client.py +81 -0
  203. package/src/trace_engine/runtime/observations.py +18 -0
  204. package/src/trace_engine/runtime/target.py +23 -0
  205. package/src/trace_engine/security/__init__.py +16 -0
  206. package/src/trace_engine/security/__pycache__/__init__.cpython-311.pyc +0 -0
  207. package/src/trace_engine/security/__pycache__/fusion.cpython-311.pyc +0 -0
  208. package/src/trace_engine/security/__pycache__/hypotheses.cpython-311.pyc +0 -0
  209. package/src/trace_engine/security/__pycache__/signals.cpython-311.pyc +0 -0
  210. package/src/trace_engine/security/__pycache__/timing.cpython-311.pyc +0 -0
  211. package/src/trace_engine/security/fusion.py +126 -0
  212. package/src/trace_engine/security/hypotheses.py +251 -0
  213. package/src/trace_engine/security/signals.py +28 -0
  214. package/src/trace_engine/security/timing.py +132 -0
  215. package/src/trace_engine/testpacks/__init__.py +18 -0
  216. package/src/trace_engine/testpacks/__pycache__/__init__.cpython-311.pyc +0 -0
  217. package/src/trace_engine/testpacks/__pycache__/authentication.cpython-311.pyc +0 -0
  218. package/src/trace_engine/testpacks/__pycache__/base.cpython-311.pyc +0 -0
  219. package/src/trace_engine/testpacks/__pycache__/bfla.cpython-311.pyc +0 -0
  220. package/src/trace_engine/testpacks/__pycache__/bola.cpython-311.pyc +0 -0
  221. package/src/trace_engine/testpacks/__pycache__/cors.cpython-311.pyc +0 -0
  222. package/src/trace_engine/testpacks/__pycache__/deserialization.cpython-311.pyc +0 -0
  223. package/src/trace_engine/testpacks/__pycache__/injection.cpython-311.pyc +0 -0
  224. package/src/trace_engine/testpacks/__pycache__/mass_assignment.cpython-311.pyc +0 -0
  225. package/src/trace_engine/testpacks/__pycache__/path_traversal.cpython-311.pyc +0 -0
  226. package/src/trace_engine/testpacks/__pycache__/registry.cpython-311.pyc +0 -0
  227. package/src/trace_engine/testpacks/__pycache__/ssrf.cpython-311.pyc +0 -0
  228. package/src/trace_engine/testpacks/__pycache__/ssti.cpython-311.pyc +0 -0
  229. package/src/trace_engine/testpacks/authentication.py +60 -0
  230. package/src/trace_engine/testpacks/base.py +63 -0
  231. package/src/trace_engine/testpacks/bfla.py +70 -0
  232. package/src/trace_engine/testpacks/bola.py +94 -0
  233. package/src/trace_engine/testpacks/cors.py +85 -0
  234. package/src/trace_engine/testpacks/deserialization.py +86 -0
  235. package/src/trace_engine/testpacks/injection.py +179 -0
  236. package/src/trace_engine/testpacks/mass_assignment.py +70 -0
  237. package/src/trace_engine/testpacks/path_traversal.py +117 -0
  238. package/src/trace_engine/testpacks/registry.py +44 -0
  239. package/src/trace_engine/testpacks/ssrf.py +85 -0
  240. package/src/trace_engine/testpacks/ssti.py +96 -0
  241. package/src/trace_engine/tools/__init__.py +6 -0
  242. package/src/trace_engine/tools/__pycache__/__init__.cpython-311.pyc +0 -0
  243. package/src/trace_engine/tools/__pycache__/adapters.cpython-311.pyc +0 -0
  244. package/src/trace_engine/tools/__pycache__/base.cpython-311.pyc +0 -0
  245. package/src/trace_engine/tools/__pycache__/registry.cpython-311.pyc +0 -0
  246. package/src/trace_engine/tools/adapters.py +111 -0
  247. package/src/trace_engine/tools/base.py +68 -0
  248. package/src/trace_engine/tools/registry.py +36 -0
  249. package/src/trace_engine/verify.py +156 -0
@@ -0,0 +1,65 @@
1
+ """Markdown security report generator."""
2
+
3
+ from pathlib import Path
4
+ from typing import List
5
+ from trace_engine.findings.model import Finding
6
+
7
+
8
+ def generate_markdown_report(findings: List[Finding], project_name: str = "Application") -> str:
9
+ lines = [
10
+ f"# TRACE Security Assessment Report — {project_name}",
11
+ "Threat Reconnaissance & Attack-path Correlation Engine",
12
+ "",
13
+ "## Summary",
14
+ f"- Total Correlated Findings: **{len(findings)}**",
15
+ "",
16
+ "| ID | Severity | Confidence | Category | Endpoint | Title |",
17
+ "|---|---|---|---|---|---|",
18
+ ]
19
+
20
+ for f in findings:
21
+ lines.append(
22
+ f"| {f.id} | {f.severity.value} | {f.confidence.value} | {f.category} | `{f.endpoint}` | {f.title} |"
23
+ )
24
+
25
+ lines.extend(["", "---", "", "## Finding Details", ""])
26
+
27
+ for f in findings:
28
+ lines.append(f"### [{f.id}] {f.title}")
29
+ lines.append(f"- **Category:** {f.category}")
30
+ lines.append(f"- **Severity:** {f.severity.value}")
31
+ lines.append(f"- **Confidence:** {f.confidence.value}")
32
+ lines.append(f"- **Endpoint:** `{f.endpoint}`")
33
+ if f.source_location:
34
+ lines.append(f"- **Source:** `{f.source_location}`")
35
+ lines.append("")
36
+
37
+ if f.attack_path:
38
+ lines.append("#### Attack Path Hops")
39
+ for hop in f.attack_path:
40
+ lines.append(f"1. `{hop}`")
41
+ lines.append("")
42
+
43
+ if f.static_evidence:
44
+ lines.append("#### Static AST Evidence")
45
+ for ev in f.static_evidence:
46
+ lines.append(f"- {ev}")
47
+ lines.append("")
48
+
49
+ if f.runtime_evidence:
50
+ lines.append("#### Runtime Behavioral Evidence")
51
+ for ev in f.runtime_evidence:
52
+ lines.append(f"- {ev}")
53
+ lines.append("")
54
+
55
+ if f.reproduction_steps:
56
+ lines.append("#### Reproduction Steps")
57
+ for idx, step in enumerate(f.reproduction_steps, 1):
58
+ lines.append(f"{idx}. {step}")
59
+ lines.append("")
60
+
61
+ lines.append(f"#### Remediation Guidance\n{f.remediation}\n")
62
+ lines.append("---")
63
+ lines.append("")
64
+
65
+ return "\n".join(lines)
@@ -0,0 +1,180 @@
1
+ """OASIS SARIF v2.1.0 report generator for CI/CD pipelines (GitHub Code Scanning, GitLab, SonarQube)."""
2
+
3
+ import json
4
+ from typing import List, Dict, Any, Optional
5
+ from pathlib import Path
6
+ from trace_engine.findings.model import Finding, Severity, FindingConfidence
7
+
8
+
9
+ def _severity_to_sarif_level(severity: Severity) -> str:
10
+ """Map TRACE severity to SARIF result level."""
11
+ if severity in (Severity.CRITICAL, Severity.HIGH):
12
+ return "error"
13
+ elif severity == Severity.MEDIUM:
14
+ return "warning"
15
+ else:
16
+ return "note"
17
+
18
+
19
+ def _category_to_cwe(category: str) -> Optional[str]:
20
+ """Map common TRACE categories to primary CWE IDs."""
21
+ cat_lower = category.lower()
22
+ if "sqli" in cat_lower or "sql injection" in cat_lower:
23
+ return "CWE-89"
24
+ elif "cmd_injection" in cat_lower or "command" in cat_lower:
25
+ return "CWE-78"
26
+ elif "bola" in cat_lower or "idor" in cat_lower:
27
+ return "CWE-639"
28
+ elif "bfla" in cat_lower or "privilege" in cat_lower:
29
+ return "CWE-285"
30
+ elif "ssrf" in cat_lower:
31
+ return "CWE-918"
32
+ elif "path_traversal" in cat_lower or "traversal" in cat_lower:
33
+ return "CWE-22"
34
+ elif "xss" in cat_lower:
35
+ return "CWE-79"
36
+ elif "cors" in cat_lower:
37
+ return "CWE-942"
38
+ elif "auth" in cat_lower:
39
+ return "CWE-306"
40
+ return None
41
+
42
+
43
+ def generate_sarif_report(
44
+ findings: List[Finding],
45
+ project_name: str = "TRACE Application",
46
+ workspace_root: Optional[str] = None,
47
+ ) -> Dict[str, Any]:
48
+ """Generate an OASIS SARIF v2.1.0 compliant dictionary from findings."""
49
+ rules_dict: Dict[str, Dict[str, Any]] = {}
50
+ results: List[Dict[str, Any]] = []
51
+
52
+ for f in findings:
53
+ rule_id = f"TRACE-{f.category.upper().replace(' ', '-')}"
54
+ cwe = _category_to_cwe(f.category)
55
+
56
+ if rule_id not in rules_dict:
57
+ rule_def: Dict[str, Any] = {
58
+ "id": rule_id,
59
+ "name": f.category.replace("-", " ").title(),
60
+ "shortDescription": {"text": f.title},
61
+ "fullDescription": {"text": f"Vulnerability in {f.category} detected by TRACE neuro-symbolic engine."},
62
+ "defaultConfiguration": {
63
+ "level": _severity_to_sarif_level(f.severity),
64
+ },
65
+ "properties": {
66
+ "tags": ["security", "trace-engine", f.category],
67
+ "precision": "very-high" if f.confidence == FindingConfidence.CONFIRMED else "high",
68
+ },
69
+ }
70
+ if cwe:
71
+ rule_def["properties"]["cwe"] = [cwe]
72
+ rule_def["helpUri"] = f"https://cwe.mitre.org/data/definitions/{cwe.replace('CWE-', '')}.html"
73
+ rules_dict[rule_id] = rule_def
74
+
75
+ # Build physical location
76
+ locations: List[Dict[str, Any]] = []
77
+ if f.source_location and f.source_location.file:
78
+ file_path = f.source_location.file
79
+ if workspace_root:
80
+ try:
81
+ file_path = str(Path(file_path).relative_to(workspace_root)).replace("\\", "/")
82
+ except ValueError:
83
+ file_path = file_path.replace("\\", "/")
84
+ else:
85
+ file_path = file_path.replace("\\", "/")
86
+
87
+ start_line = max(1, f.source_location.line_start or 1)
88
+ end_line = max(start_line, f.source_location.line_end or start_line)
89
+
90
+ locations.append({
91
+ "physicalLocation": {
92
+ "artifactLocation": {
93
+ "uri": file_path,
94
+ "uriBaseId": "%SRCROOT%",
95
+ },
96
+ "region": {
97
+ "startLine": start_line,
98
+ "endLine": end_line,
99
+ "startColumn": max(1, f.source_location.column_start or 1),
100
+ "endColumn": max(1, f.source_location.column_end or 1),
101
+ },
102
+ },
103
+ "message": {
104
+ "text": f"Vulnerable code slice at {f.endpoint}",
105
+ },
106
+ })
107
+
108
+ # Build code flows / attack path if present
109
+ code_flows: List[Dict[str, Any]] = []
110
+ if f.attack_path:
111
+ thread_flow_locations = []
112
+ for hop in f.attack_path:
113
+ thread_flow_locations.append({
114
+ "location": {
115
+ "message": {"text": f"Attack hop: {hop}"},
116
+ }
117
+ })
118
+ code_flows.append({
119
+ "threadFlows": [{
120
+ "locations": thread_flow_locations
121
+ }]
122
+ })
123
+
124
+ result_obj: Dict[str, Any] = {
125
+ "ruleId": rule_id,
126
+ "level": _severity_to_sarif_level(f.severity),
127
+ "message": {
128
+ "text": f"{f.title}: {f.correlation_notes}",
129
+ },
130
+ "locations": locations,
131
+ "properties": {
132
+ "trace_finding_id": f.id,
133
+ "endpoint": f.endpoint,
134
+ "confidence": f.confidence.value,
135
+ "severity": f.severity.value,
136
+ "remediation": f.remediation,
137
+ "staticEvidence": f.static_evidence,
138
+ "runtimeEvidence": f.runtime_evidence,
139
+ },
140
+ }
141
+
142
+ if code_flows:
143
+ result_obj["codeFlows"] = code_flows
144
+
145
+ results.append(result_obj)
146
+
147
+ sarif_doc = {
148
+ "$schema": "https://raw.githubusercontent.com/oasis-tcs/sarif-spec/master/Schemata/sarif-schema-2.1.0.json",
149
+ "version": "2.1.0",
150
+ "runs": [
151
+ {
152
+ "tool": {
153
+ "driver": {
154
+ "name": "TRACE Security Engine",
155
+ "version": "2.0.0",
156
+ "informationUri": "https://github.com/VK-Amogh/TRACE",
157
+ "rules": list(rules_dict.values()),
158
+ }
159
+ },
160
+ "results": results,
161
+ }
162
+ ],
163
+ }
164
+
165
+ return sarif_doc
166
+
167
+
168
+ def export_sarif_json(
169
+ findings: List[Finding],
170
+ output_path: str,
171
+ project_name: str = "TRACE Application",
172
+ workspace_root: Optional[str] = None,
173
+ ) -> str:
174
+ """Serialize findings to a SARIF v2.1.0 JSON file."""
175
+ sarif = generate_sarif_report(findings, project_name=project_name, workspace_root=workspace_root)
176
+ out = Path(output_path)
177
+ out.parent.mkdir(parents=True, exist_ok=True)
178
+ with open(out, "w", encoding="utf-8") as f:
179
+ json.dump(sarif, f, indent=2)
180
+ return str(out.resolve())