@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,35 @@
1
+ """TRACE configuration module."""
2
+
3
+ from trace_engine.config.settings import (
4
+ TraceConfig,
5
+ ProjectSettings,
6
+ AISettings,
7
+ TargetSettings,
8
+ RuntimeSettings,
9
+ AnalysisSettings,
10
+ TestsSettings,
11
+ ToolsSettings,
12
+ )
13
+ from trace_engine.config.loader import (
14
+ get_trace_dir,
15
+ get_config_path,
16
+ init_trace_dir,
17
+ load_config,
18
+ save_config,
19
+ )
20
+
21
+ __all__ = [
22
+ "TraceConfig",
23
+ "ProjectSettings",
24
+ "AISettings",
25
+ "TargetSettings",
26
+ "RuntimeSettings",
27
+ "AnalysisSettings",
28
+ "TestsSettings",
29
+ "ToolsSettings",
30
+ "get_trace_dir",
31
+ "get_config_path",
32
+ "init_trace_dir",
33
+ "load_config",
34
+ "save_config",
35
+ ]
@@ -0,0 +1,48 @@
1
+ """Default configuration values for TRACE."""
2
+
3
+ DEFAULT_CONFIG_TOML = """# TRACE Configuration File
4
+ # Threat Reconnaissance & Attack-path Correlation Engine
5
+
6
+ [project]
7
+ name = "default-project"
8
+ version = "1.0.0"
9
+ mode = "local"
10
+
11
+ [ai]
12
+ provider = "ollama"
13
+ model = "qwen2.5-coder:latest"
14
+ temperature = 0.1
15
+ endpoint = "http://127.0.0.1:11434"
16
+
17
+ [target]
18
+ url = "http://127.0.0.1:8000"
19
+ scope_mode = "local"
20
+ allowed_hosts = ["localhost", "127.0.0.1", "0.0.0.0", "::1"]
21
+ allowed_ports = [80, 443, 3000, 5000, 8000, 8080, 18080]
22
+
23
+ [runtime]
24
+ max_requests = 250
25
+ concurrency = 2
26
+ rate_limit_per_second = 5
27
+ timeout_seconds = 8
28
+ max_redirects = 3
29
+ destructive_tests = false
30
+
31
+ [analysis]
32
+ max_graph_hops = 3
33
+ max_source_context_lines = 120
34
+ enable_tree_sitter = true
35
+
36
+ [tests]
37
+ enabled = [
38
+ "bola",
39
+ "bfla",
40
+ "authentication",
41
+ "ssrf",
42
+ "injection",
43
+ "mass_assignment"
44
+ ]
45
+
46
+ [tools]
47
+ enabled = ["schemathesis", "nuclei", "zap", "trufflehog"]
48
+ """
@@ -0,0 +1,64 @@
1
+ """Configuration loader for TRACE."""
2
+
3
+ import os
4
+ from pathlib import Path
5
+ from typing import Optional
6
+ import tomllib
7
+ import tomli_w
8
+
9
+ from trace_engine.config.settings import TraceConfig
10
+ from trace_engine.config.defaults import DEFAULT_CONFIG_TOML
11
+
12
+
13
+ def get_trace_dir(repo_path: Path) -> Path:
14
+ """Get the .trace directory path within the given repository."""
15
+ return repo_path.resolve() / ".trace"
16
+
17
+
18
+ def get_config_path(repo_path: Path) -> Path:
19
+ """Get the path to config.toml in the .trace directory."""
20
+ return get_trace_dir(repo_path) / "config.toml"
21
+
22
+
23
+ def init_trace_dir(repo_path: Path, project_name: Optional[str] = None) -> Path:
24
+ """Initialize .trace directory structure in repository."""
25
+ trace_dir = get_trace_dir(repo_path)
26
+ trace_dir.mkdir(parents=True, exist_ok=True)
27
+
28
+ (trace_dir / "cache").mkdir(exist_ok=True)
29
+ (trace_dir / "runs").mkdir(exist_ok=True)
30
+ (trace_dir / "reports").mkdir(exist_ok=True)
31
+
32
+ config_file = trace_dir / "config.toml"
33
+ if not config_file.exists():
34
+ content = DEFAULT_CONFIG_TOML
35
+ if project_name:
36
+ content = content.replace('name = "default-project"', f'name = "{project_name}"')
37
+ config_file.write_text(content, encoding="utf-8")
38
+
39
+ return trace_dir
40
+
41
+
42
+ def load_config(repo_path: Path) -> TraceConfig:
43
+ """Load configuration from .trace/config.toml or return default configuration."""
44
+ config_file = get_config_path(repo_path)
45
+ if not config_file.exists():
46
+ return TraceConfig()
47
+
48
+ try:
49
+ with open(config_file, "rb") as f:
50
+ data = tomllib.load(f)
51
+ return TraceConfig.model_validate(data)
52
+ except Exception:
53
+ return TraceConfig()
54
+
55
+
56
+ def save_config(repo_path: Path, config: TraceConfig) -> None:
57
+ """Save configuration to .trace/config.toml."""
58
+ trace_dir = get_trace_dir(repo_path)
59
+ trace_dir.mkdir(parents=True, exist_ok=True)
60
+ config_file = trace_dir / "config.toml"
61
+
62
+ data = config.model_dump()
63
+ with open(config_file, "wb") as f:
64
+ tomli_w.dump(data, f)
@@ -0,0 +1,72 @@
1
+ """Configuration settings for TRACE using Pydantic."""
2
+
3
+ from typing import List, Optional
4
+ from pydantic import BaseModel, Field
5
+
6
+
7
+ class ProjectSettings(BaseModel):
8
+ name: str = "default-project"
9
+ version: str = "1.0.0"
10
+ mode: str = "local"
11
+
12
+
13
+ class AISettings(BaseModel):
14
+ provider: str = "ollama"
15
+ model: str = "qwen2.5-coder:latest"
16
+ temperature: float = 0.1
17
+ endpoint: str = "http://127.0.0.1:11434"
18
+
19
+
20
+ class TargetSettings(BaseModel):
21
+ url: str = "http://127.0.0.1:8000"
22
+ scope_mode: str = "local"
23
+ allowed_hosts: List[str] = Field(
24
+ default_factory=lambda: ["localhost", "127.0.0.1", "0.0.0.0", "::1"]
25
+ )
26
+ allowed_ports: List[int] = Field(
27
+ default_factory=lambda: [80, 443, 3000, 5000, 8000, 8080, 18080]
28
+ )
29
+
30
+
31
+ class RuntimeSettings(BaseModel):
32
+ max_requests: int = 250
33
+ concurrency: int = 2
34
+ rate_limit_per_second: int = 5
35
+ timeout_seconds: float = 8.0
36
+ max_redirects: int = 3
37
+ destructive_tests: bool = False
38
+
39
+
40
+ class AnalysisSettings(BaseModel):
41
+ max_graph_hops: int = 3
42
+ max_source_context_lines: int = 120
43
+ enable_tree_sitter: bool = True
44
+
45
+
46
+ class TestsSettings(BaseModel):
47
+ enabled: List[str] = Field(
48
+ default_factory=lambda: [
49
+ "bola",
50
+ "bfla",
51
+ "authentication",
52
+ "ssrf",
53
+ "injection",
54
+ "mass_assignment",
55
+ ]
56
+ )
57
+
58
+
59
+ class ToolsSettings(BaseModel):
60
+ enabled: List[str] = Field(
61
+ default_factory=lambda: ["schemathesis", "nuclei", "zap", "trufflehog"]
62
+ )
63
+
64
+
65
+ class TraceConfig(BaseModel):
66
+ project: ProjectSettings = Field(default_factory=ProjectSettings)
67
+ ai: AISettings = Field(default_factory=AISettings)
68
+ target: TargetSettings = Field(default_factory=TargetSettings)
69
+ runtime: RuntimeSettings = Field(default_factory=RuntimeSettings)
70
+ analysis: AnalysisSettings = Field(default_factory=AnalysisSettings)
71
+ tests: TestsSettings = Field(default_factory=TestsSettings)
72
+ tools: ToolsSettings = Field(default_factory=ToolsSettings)
@@ -0,0 +1,250 @@
1
+ """Environment diagnostics and system readiness check (trace doctor)."""
2
+
3
+ import sys
4
+ import sqlite3
5
+ import shutil
6
+ from typing import List, Dict, Any
7
+ from pydantic import BaseModel
8
+
9
+ from trace_engine.tools.registry import default_tool_registry
10
+ from trace_engine.ai.ollama import OllamaProvider
11
+
12
+
13
+ class CheckItem(BaseModel):
14
+ name: str
15
+ status: bool # True for pass, False for fail/missing
16
+ category: str
17
+ details: str
18
+ critical: bool = False
19
+
20
+
21
+ class DoctorReport(BaseModel):
22
+ items: List[CheckItem]
23
+ all_critical_passed: bool
24
+
25
+
26
+ def run_doctor() -> DoctorReport:
27
+ """Runs system diagnostics across runtime, AI, tools, and dependencies."""
28
+ items: List[CheckItem] = []
29
+
30
+ # 1. Python version
31
+ py_ver = f"{sys.version_info.major}.{sys.version_info.minor}.{sys.version_info.micro}"
32
+ py_ok = sys.version_info >= (3, 11)
33
+ items.append(
34
+ CheckItem(
35
+ name=f"Python {py_ver}",
36
+ status=py_ok,
37
+ category="Core Runtime",
38
+ details="Requires Python >= 3.11",
39
+ critical=True,
40
+ )
41
+ )
42
+
43
+ # 2. SQLite
44
+ try:
45
+ conn = sqlite3.connect(":memory:")
46
+ conn.close()
47
+ items.append(
48
+ CheckItem(
49
+ name="SQLite 3",
50
+ status=True,
51
+ category="Core Runtime",
52
+ details=f"SQLite version {sqlite3.sqlite_version}",
53
+ critical=True,
54
+ )
55
+ )
56
+ except Exception as e:
57
+ items.append(
58
+ CheckItem(
59
+ name="SQLite 3",
60
+ status=False,
61
+ category="Core Runtime",
62
+ details=str(e),
63
+ critical=True,
64
+ )
65
+ )
66
+
67
+ # 3. Tree-sitter
68
+ try:
69
+ import tree_sitter_language_pack
70
+ items.append(
71
+ CheckItem(
72
+ name="Tree-sitter AST",
73
+ status=True,
74
+ category="Code Analysis",
75
+ details="Multi-language AST parsing enabled",
76
+ critical=True,
77
+ )
78
+ )
79
+ except Exception as e:
80
+ items.append(
81
+ CheckItem(
82
+ name="Tree-sitter AST",
83
+ status=False,
84
+ category="Code Analysis",
85
+ details="Fallback AST mode active",
86
+ critical=False,
87
+ )
88
+ )
89
+
90
+ # 4. NetworkX
91
+ try:
92
+ import networkx as nx
93
+ items.append(
94
+ CheckItem(
95
+ name="NetworkX APM",
96
+ status=True,
97
+ category="Attack-Path Model",
98
+ details=f"Graph engine v{nx.__version__}",
99
+ critical=True,
100
+ )
101
+ )
102
+ except Exception as e:
103
+ items.append(
104
+ CheckItem(
105
+ name="NetworkX APM",
106
+ status=False,
107
+ category="Attack-Path Model",
108
+ details=str(e),
109
+ critical=True,
110
+ )
111
+ )
112
+
113
+ # 5. HTTPX
114
+ try:
115
+ import httpx
116
+ items.append(
117
+ CheckItem(
118
+ name="HTTPX Client",
119
+ status=True,
120
+ category="Runtime Testing",
121
+ details=f"HTTP engine v{httpx.__version__}",
122
+ critical=True,
123
+ )
124
+ )
125
+ except Exception as e:
126
+ items.append(
127
+ CheckItem(
128
+ name="HTTPX Client",
129
+ status=False,
130
+ category="Runtime Testing",
131
+ details=str(e),
132
+ critical=True,
133
+ )
134
+ )
135
+
136
+ # 6. Local AI (Ollama)
137
+ ollama = OllamaProvider()
138
+ ollama_ok = ollama.is_available()
139
+ items.append(
140
+ CheckItem(
141
+ name="Ollama LLM",
142
+ status=ollama_ok,
143
+ category="AI Inference",
144
+ details="Connected at http://127.0.0.1:11434" if ollama_ok else "Not reachable (using deterministic planner)",
145
+ critical=False,
146
+ )
147
+ )
148
+
149
+ # 7. PyTorch & Transformers
150
+ try:
151
+ import torch
152
+ import transformers
153
+ items.append(
154
+ CheckItem(
155
+ name="PyTorch",
156
+ status=True,
157
+ category="AI Inference",
158
+ details=f"PyTorch v{torch.__version__}, Transformers v{transformers.__version__}",
159
+ critical=False,
160
+ )
161
+ )
162
+ except Exception as e:
163
+ items.append(
164
+ CheckItem(
165
+ name="PyTorch",
166
+ status=False,
167
+ category="AI Inference",
168
+ details=str(e),
169
+ critical=False,
170
+ )
171
+ )
172
+
173
+ # 8. Laya System 1 Engine
174
+ try:
175
+ import warnings
176
+ with warnings.catch_warnings():
177
+ warnings.simplefilter("ignore")
178
+ from trace_engine.intelligence.laya.router import LayaDecisionEngine
179
+ laya = LayaDecisionEngine()
180
+ laya_avail = laya.is_available()
181
+ items.append(
182
+ CheckItem(
183
+ name="Laya System 1",
184
+ status=laya_avail,
185
+ category="AI Inference",
186
+ details="Online (convaiinnovations/laya on CPU)" if laya_avail else "Standby (calibrated fallback active)",
187
+ critical=False,
188
+ )
189
+ )
190
+ except Exception as e:
191
+ items.append(
192
+ CheckItem(
193
+ name="Laya System 1",
194
+ status=False,
195
+ category="AI Inference",
196
+ details=str(e),
197
+ critical=False,
198
+ )
199
+ )
200
+
201
+ # 9. SecureBERT 2.0 Classifier
202
+ try:
203
+ from trace_engine.intelligence.securebert.classifier import SecureBERTClassifier
204
+ bert = SecureBERTClassifier()
205
+ items.append(
206
+ CheckItem(
207
+ name="SecureBERT 2.0",
208
+ status=True,
209
+ category="AI Inference",
210
+ details=f"Model: {bert.model_name}",
211
+ critical=False,
212
+ )
213
+ )
214
+ except Exception as e:
215
+ items.append(
216
+ CheckItem(
217
+ name="SecureBERT 2.0 Semantic Classifier",
218
+ status=False,
219
+ category="AI Inference",
220
+ details=str(e),
221
+ critical=False,
222
+ )
223
+ )
224
+
225
+ # 7. External Tools
226
+ for tool_info in default_tool_registry.get_all_info():
227
+ items.append(
228
+ CheckItem(
229
+ name=tool_info.name,
230
+ status=tool_info.installed,
231
+ category="Security Tool Adapters",
232
+ details=tool_info.version or f"Executable '{tool_info.command}' not found in PATH",
233
+ critical=False,
234
+ )
235
+ )
236
+
237
+ # 8. Docker
238
+ docker_installed = shutil.which("docker") is not None
239
+ items.append(
240
+ CheckItem(
241
+ name="Docker Desktop / CLI",
242
+ status=docker_installed,
243
+ category="Lab Isolation",
244
+ details="Available for isolated container labs" if docker_installed else "Not found (local process labs enabled)",
245
+ critical=False,
246
+ )
247
+ )
248
+
249
+ all_crit = all(item.status for item in items if item.critical)
250
+ return DoctorReport(items=items, all_critical_passed=all_crit)
@@ -0,0 +1,15 @@
1
+ """Findings and evidence correlation module."""
2
+
3
+ from trace_engine.findings.model import Finding, Severity, FindingConfidence
4
+ from trace_engine.findings.correlate import EvidenceCorrelator
5
+ from trace_engine.findings.store import FindingStore
6
+ from trace_engine.findings.recommendations import get_remediation_for_category
7
+
8
+ __all__ = [
9
+ "Finding",
10
+ "Severity",
11
+ "FindingConfidence",
12
+ "EvidenceCorrelator",
13
+ "FindingStore",
14
+ "get_remediation_for_category",
15
+ ]
@@ -0,0 +1,103 @@
1
+ """Evidence correlator connecting static attack paths to runtime test results."""
2
+
3
+ from typing import List, Optional
4
+ from trace_engine.security.hypotheses import SecurityHypothesis
5
+ from trace_engine.testpacks.base import TestExecutionResult
6
+ from trace_engine.findings.model import Finding, Severity, FindingConfidence
7
+ from trace_engine.findings.recommendations import get_remediation_for_category
8
+ from trace_engine.apm.model import AttackPathModel
9
+
10
+
11
+ SEVERITY_BY_CATEGORY = {
12
+ "BOLA": Severity.HIGH,
13
+ "BFLA": Severity.HIGH,
14
+ "AUTHENTICATION": Severity.CRITICAL,
15
+ "SSRF": Severity.HIGH,
16
+ "INJECTION": Severity.CRITICAL,
17
+ "MASS_ASSIGNMENT": Severity.MEDIUM,
18
+ "PATH_TRAVERSAL": Severity.HIGH,
19
+ "SSTI": Severity.CRITICAL,
20
+ "CORS": Severity.MEDIUM,
21
+ "DESERIALIZATION": Severity.CRITICAL,
22
+ }
23
+
24
+
25
+ class EvidenceCorrelator:
26
+ """Correlates static code evidence with runtime test executions using Neuro-Symbolic Bayesian Calibration."""
27
+
28
+ def correlate(
29
+ self,
30
+ hypothesis: SecurityHypothesis,
31
+ test_result: Optional[TestExecutionResult],
32
+ apm: AttackPathModel,
33
+ ) -> Optional[Finding]:
34
+ from trace_engine.security.fusion import NeuroSymbolicConfidenceEngine, ConfidenceEvidence
35
+
36
+ category_str = hypothesis.category.value
37
+
38
+ # Calculate combined confidence using Neuro-Symbolic Bayesian Fusion
39
+ evidence = ConfidenceEvidence(
40
+ symbolic_ast_score=hypothesis.confidence_prior,
41
+ dynamic_test_score=test_result.confidence if test_result else None,
42
+ is_dynamically_confirmed=bool(test_result and test_result.confirmed),
43
+ )
44
+ fused = NeuroSymbolicConfidenceEngine.fuse_evidence(evidence)
45
+ confidence = fused.confidence_level
46
+
47
+ # If not confirmed and posterior probability is below 0.40, do not generate noisy finding
48
+ if not (test_result and test_result.confirmed) and fused.posterior_probability < 0.40:
49
+ return None
50
+
51
+ # Build attack path node trail from APM
52
+ attack_path_nodes = []
53
+ if hypothesis.endpoint_id in apm.graph:
54
+ sinks = apm.find_paths_to_sinks(hypothesis.endpoint_id)
55
+ if sinks:
56
+ attack_path_nodes = sinks[0]
57
+ else:
58
+ paths = apm.find_paths_from_endpoint(hypothesis.endpoint_id, max_depth=3)
59
+ if paths:
60
+ attack_path_nodes = paths[0]
61
+
62
+ # Runtime evidence bullet points
63
+ runtime_evidence = []
64
+ if test_result:
65
+ runtime_evidence.append(test_result.summary)
66
+ for obs in test_result.observations:
67
+ runtime_evidence.append(
68
+ f"HTTP {obs.request_method} {obs.request_url} -> Status {obs.response_status} ({obs.latency_ms}ms)"
69
+ )
70
+
71
+ # Correlation explanation
72
+ if test_result and test_result.confirmed:
73
+ correlation_notes = (
74
+ f"Static Attack-Path Model identified vulnerable structure in source code, "
75
+ f"and active runtime test pack '{test_result.testpack_name}' successfully proved exploitability."
76
+ )
77
+ else:
78
+ correlation_notes = (
79
+ f"Static Attack-Path Model detected missing control boundary; runtime validation pending or inconclusive."
80
+ )
81
+
82
+ finding_id = hypothesis.id.replace("HYP-", "TR-")
83
+ severity = SEVERITY_BY_CATEGORY.get(category_str, Severity.MEDIUM)
84
+
85
+ ep_node = apm.get_node(hypothesis.endpoint_id)
86
+ source_loc = ep_node.location if ep_node else None
87
+
88
+ return Finding(
89
+ id=finding_id,
90
+ title=hypothesis.title,
91
+ category=category_str,
92
+ severity=severity,
93
+ confidence=confidence,
94
+ endpoint=hypothesis.endpoint_display,
95
+ source_location=source_loc,
96
+ attack_path=attack_path_nodes,
97
+ static_evidence=hypothesis.static_evidence,
98
+ runtime_evidence=runtime_evidence,
99
+ correlation_notes=correlation_notes,
100
+ remediation=get_remediation_for_category(category_str),
101
+ reproduction_steps=test_result.reproduction_steps if test_result else [],
102
+ observations=test_result.observations if test_result else [],
103
+ )
@@ -0,0 +1,40 @@
1
+ """Correlated security finding schema."""
2
+
3
+ from enum import Enum
4
+ from typing import List, Optional, Dict, Any
5
+ from pydantic import BaseModel, Field
6
+ from trace_engine.parsing.locations import SourceLocation
7
+ from trace_engine.runtime.observations import RuntimeObservation
8
+
9
+
10
+ class Severity(str, Enum):
11
+ CRITICAL = "CRITICAL"
12
+ HIGH = "HIGH"
13
+ MEDIUM = "MEDIUM"
14
+ LOW = "LOW"
15
+ INFO = "INFO"
16
+
17
+
18
+ class FindingConfidence(str, Enum):
19
+ CONFIRMED = "CONFIRMED"
20
+ HIGH = "HIGH"
21
+ MEDIUM = "MEDIUM"
22
+ POTENTIAL = "POTENTIAL"
23
+
24
+
25
+ class Finding(BaseModel):
26
+ """Correlated vulnerability finding supported by both static AST and runtime proof."""
27
+ id: str
28
+ title: str
29
+ category: str
30
+ severity: Severity
31
+ confidence: FindingConfidence
32
+ endpoint: str
33
+ source_location: Optional[SourceLocation] = None
34
+ attack_path: List[str] = Field(default_factory=list)
35
+ static_evidence: List[str] = Field(default_factory=list)
36
+ runtime_evidence: List[str] = Field(default_factory=list)
37
+ correlation_notes: str
38
+ remediation: str
39
+ reproduction_steps: List[str] = Field(default_factory=list)
40
+ observations: List[RuntimeObservation] = Field(default_factory=list)
@@ -0,0 +1,35 @@
1
+ """Remediation recommendations for security findings."""
2
+
3
+ REMEDIATION_MAP = {
4
+ "BOLA": (
5
+ "Enforce strict object ownership validation before returning records. "
6
+ "Query using both the object ID and the authenticated user/tenant ID (e.g. `WHERE id = :id AND user_id = :current_user.id`)."
7
+ ),
8
+ "BFLA": (
9
+ "Implement declarative role-based access control (RBAC) middleware. "
10
+ "Validate user privileges on the backend for every privileged/administrative route."
11
+ ),
12
+ "AUTHENTICATION": (
13
+ "Protect this route with authentication dependencies (e.g. `Depends(get_current_user)` or security middleware) "
14
+ "to ensure unauthorized users cannot trigger state-changing or sensitive operations."
15
+ ),
16
+ "SSRF": (
17
+ "Avoid making arbitrary outbound HTTP requests with user-controlled URLs. "
18
+ "Implement a strict destination domain whitelist and block loopback/internal IP addresses (RFC 1918)."
19
+ ),
20
+ "INJECTION": (
21
+ "Use parameterized queries, prepared statements, or ORM abstraction for all database operations. "
22
+ "Never format or concatenate raw client inputs into SQL/command strings."
23
+ ),
24
+ "MASS_ASSIGNMENT": (
25
+ "Define explicit request DTO schemas (e.g. Pydantic models with only allowed mutable fields). "
26
+ "Do not allow raw dictionary binding directly into database models."
27
+ ),
28
+ }
29
+
30
+
31
+ def get_remediation_for_category(category: str) -> str:
32
+ return REMEDIATION_MAP.get(
33
+ category.upper(),
34
+ "Review access control and input validation on this attack path.",
35
+ )