torusguard 0.9.2

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 (236) hide show
  1. package/.torusguard/.manifest.json +95 -0
  2. package/.torusguard/ARCHITECTURE.md +168 -0
  3. package/.torusguard/TORUSGUARD.md +145 -0
  4. package/.torusguard/agents/auditor.md +41 -0
  5. package/.torusguard/agents/profiler.md +49 -0
  6. package/.torusguard/agents/remediator.md +41 -0
  7. package/.torusguard/agents/reviewer.md +39 -0
  8. package/.torusguard/agents/validator.md +46 -0
  9. package/.torusguard/config/scope.json +24 -0
  10. package/.torusguard/config/slash-commands.json +102 -0
  11. package/.torusguard/config/torusguard.json +30 -0
  12. package/.torusguard/references/django-security.md +43 -0
  13. package/.torusguard/references/drf-security.md +20 -0
  14. package/.torusguard/references/express-security.md +103 -0
  15. package/.torusguard/references/fastapi-security.md +20 -0
  16. package/.torusguard/references/firebase-security.md +78 -0
  17. package/.torusguard/references/flask-security.md +20 -0
  18. package/.torusguard/references/nextjs-security.md +96 -0
  19. package/.torusguard/references/react-vite-security.md +97 -0
  20. package/.torusguard/references/sqlalchemy-security.md +16 -0
  21. package/.torusguard/references/supabase-security.md +84 -0
  22. package/.torusguard/rules/README.md +62 -0
  23. package/.torusguard/rules/TORUSGUARD.md +145 -0
  24. package/.torusguard/rules/active/.gitkeep +0 -0
  25. package/.torusguard/rules/active/TG-DIFF-001.md +20 -0
  26. package/.torusguard/rules/active/TG-DIFF-002.md +20 -0
  27. package/.torusguard/rules/active/TG-DIFF-003.md +19 -0
  28. package/.torusguard/runs/.gitkeep +0 -0
  29. package/.torusguard/schemas/authorization.schema.json +81 -0
  30. package/.torusguard/schemas/confidence.schema.json +72 -0
  31. package/.torusguard/schemas/evidence.schema.json +66 -0
  32. package/.torusguard/schemas/finding.schema.json +164 -0
  33. package/.torusguard/schemas/provenance.schema.json +46 -0
  34. package/.torusguard/schemas/remediation.schema.json +59 -0
  35. package/.torusguard/schemas/retest.schema.json +53 -0
  36. package/.torusguard/schemas/runtime-evidence.schema.json +72 -0
  37. package/.torusguard/scripts/__pycache__/diff_guard.cpython-311.pyc +0 -0
  38. package/.torusguard/scripts/__pycache__/monorepo_detector.cpython-311.pyc +0 -0
  39. package/.torusguard/scripts/diff_guard.py +171 -0
  40. package/.torusguard/scripts/finding_scorer.py +86 -0
  41. package/.torusguard/scripts/manifest_builder.py +130 -0
  42. package/.torusguard/scripts/monorepo_detector.py +164 -0
  43. package/.torusguard/scripts/run_manager.py +89 -0
  44. package/.torusguard/scripts/safety_gate.py +64 -0
  45. package/.torusguard/scripts/sarif_exporter.py +116 -0
  46. package/.torusguard/scripts/stack_detect.py +152 -0
  47. package/.torusguard/skills/torusguard/SKILL.md +37 -0
  48. package/.torusguard/skills/torusguard/bootstrap.py +158 -0
  49. package/.torusguard/skills/torusguard/references/auth-and-sessions.md +56 -0
  50. package/.torusguard/skills/torusguard/references/business-logic-and-abuse.md +23 -0
  51. package/.torusguard/skills/torusguard/references/cache-and-sensitive-responses.md +10 -0
  52. package/.torusguard/skills/torusguard/references/client-code-exposure.md +55 -0
  53. package/.torusguard/skills/torusguard/references/csrf-and-cross-origin.md +11 -0
  54. package/.torusguard/skills/torusguard/references/dependency-and-supply-chain.md +22 -0
  55. package/.torusguard/skills/torusguard/references/django-security.md +43 -0
  56. package/.torusguard/skills/torusguard/references/drf-security.md +20 -0
  57. package/.torusguard/skills/torusguard/references/fastapi-security.md +20 -0
  58. package/.torusguard/skills/torusguard/references/flask-security.md +20 -0
  59. package/.torusguard/skills/torusguard/references/frontend-no-db.md +53 -0
  60. package/.torusguard/skills/torusguard/references/graphql-security.md +12 -0
  61. package/.torusguard/skills/torusguard/references/input-and-injection.md +51 -0
  62. package/.torusguard/skills/torusguard/references/mass-assignment-and-property-auth.md +22 -0
  63. package/.torusguard/skills/torusguard/references/platform-hardening.md +56 -0
  64. package/.torusguard/skills/torusguard/references/python-dependencies.md +16 -0
  65. package/.torusguard/skills/torusguard/references/python-security-overview.md +12 -0
  66. package/.torusguard/skills/torusguard/references/rate-limit-and-abuse.md +57 -0
  67. package/.torusguard/skills/torusguard/references/secrets-and-config.md +64 -0
  68. package/.torusguard/skills/torusguard/references/sqlalchemy-security.md +16 -0
  69. package/.torusguard/skills/torusguard/references/ssrf-and-outbound-requests.md +46 -0
  70. package/.torusguard/skills/torusguard/references/webhook-security.md +15 -0
  71. package/.torusguard/skills/torusguard/references/websocket-security.md +12 -0
  72. package/.torusguard/skills/torusguard-apply/SKILL.md +46 -0
  73. package/.torusguard/skills/torusguard-audit/SKILL.md +70 -0
  74. package/.torusguard/skills/torusguard-authorize/SKILL.md +47 -0
  75. package/.torusguard/skills/torusguard-exploit-check/SKILL.md +64 -0
  76. package/.torusguard/skills/torusguard-full/SKILL.md +70 -0
  77. package/.torusguard/skills/torusguard-harden/SKILL.md +63 -0
  78. package/.torusguard/skills/torusguard-init/SKILL.md +52 -0
  79. package/.torusguard/skills/torusguard-recheck/SKILL.md +53 -0
  80. package/.torusguard/skills/torusguard-report/SKILL.md +54 -0
  81. package/.torusguard/skills/torusguard-status/SKILL.md +42 -0
  82. package/.torusguard/skills/torusguard-verify/SKILL.md +55 -0
  83. package/.torusguard/skills/torusguard-web-validate/SKILL.md +64 -0
  84. package/.torusguard/templates/audit-report.template.md +54 -0
  85. package/.torusguard/templates/authorization.template.md +34 -0
  86. package/.torusguard/templates/finding-card.template.md +32 -0
  87. package/.torusguard/templates/remediation-bundle.template.md +35 -0
  88. package/.torusguard/workflows/apply.md +95 -0
  89. package/.torusguard/workflows/audit.md +93 -0
  90. package/.torusguard/workflows/authorize.md +95 -0
  91. package/.torusguard/workflows/exploit-check.md +97 -0
  92. package/.torusguard/workflows/harden.md +93 -0
  93. package/.torusguard/workflows/init.md +95 -0
  94. package/.torusguard/workflows/recheck.md +95 -0
  95. package/.torusguard/workflows/report.md +95 -0
  96. package/.torusguard/workflows/status.md +95 -0
  97. package/.torusguard/workflows/verify.md +95 -0
  98. package/.torusguard/workflows/web-validate.md +95 -0
  99. package/LICENSE +21 -0
  100. package/README.md +319 -0
  101. package/bin/torusguard.js +110 -0
  102. package/install.py +98 -0
  103. package/package.json +48 -0
  104. package/skills/torusguard/SKILL.md +41 -0
  105. package/skills/torusguard/__pycache__/bootstrap.cpython-311.pyc +0 -0
  106. package/skills/torusguard/bootstrap.py +256 -0
  107. package/skills/torusguard/payload/.manifest.json +95 -0
  108. package/skills/torusguard/payload/ARCHITECTURE.md +168 -0
  109. package/skills/torusguard/payload/TORUSGUARD.md +145 -0
  110. package/skills/torusguard/payload/agents/auditor.md +41 -0
  111. package/skills/torusguard/payload/agents/profiler.md +49 -0
  112. package/skills/torusguard/payload/agents/remediator.md +41 -0
  113. package/skills/torusguard/payload/agents/reviewer.md +39 -0
  114. package/skills/torusguard/payload/agents/validator.md +46 -0
  115. package/skills/torusguard/payload/config/scope.json +24 -0
  116. package/skills/torusguard/payload/config/slash-commands.json +102 -0
  117. package/skills/torusguard/payload/config/torusguard.json +30 -0
  118. package/skills/torusguard/payload/references/django-security.md +43 -0
  119. package/skills/torusguard/payload/references/drf-security.md +20 -0
  120. package/skills/torusguard/payload/references/express-security.md +103 -0
  121. package/skills/torusguard/payload/references/fastapi-security.md +20 -0
  122. package/skills/torusguard/payload/references/firebase-security.md +78 -0
  123. package/skills/torusguard/payload/references/flask-security.md +20 -0
  124. package/skills/torusguard/payload/references/nextjs-security.md +96 -0
  125. package/skills/torusguard/payload/references/react-vite-security.md +97 -0
  126. package/skills/torusguard/payload/references/sqlalchemy-security.md +16 -0
  127. package/skills/torusguard/payload/references/supabase-security.md +84 -0
  128. package/skills/torusguard/payload/rules/README.md +62 -0
  129. package/skills/torusguard/payload/rules/TORUSGUARD.md +145 -0
  130. package/skills/torusguard/payload/rules/active/.gitkeep +0 -0
  131. package/skills/torusguard/payload/rules/active/TG-DIFF-001.md +20 -0
  132. package/skills/torusguard/payload/rules/active/TG-DIFF-002.md +20 -0
  133. package/skills/torusguard/payload/rules/active/TG-DIFF-003.md +19 -0
  134. package/skills/torusguard/payload/schemas/authorization.schema.json +81 -0
  135. package/skills/torusguard/payload/schemas/confidence.schema.json +72 -0
  136. package/skills/torusguard/payload/schemas/evidence.schema.json +66 -0
  137. package/skills/torusguard/payload/schemas/finding.schema.json +164 -0
  138. package/skills/torusguard/payload/schemas/provenance.schema.json +46 -0
  139. package/skills/torusguard/payload/schemas/remediation.schema.json +59 -0
  140. package/skills/torusguard/payload/schemas/retest.schema.json +53 -0
  141. package/skills/torusguard/payload/schemas/runtime-evidence.schema.json +72 -0
  142. package/skills/torusguard/payload/scripts/diff_guard.py +171 -0
  143. package/skills/torusguard/payload/scripts/finding_scorer.py +86 -0
  144. package/skills/torusguard/payload/scripts/manifest_builder.py +130 -0
  145. package/skills/torusguard/payload/scripts/monorepo_detector.py +164 -0
  146. package/skills/torusguard/payload/scripts/run_manager.py +89 -0
  147. package/skills/torusguard/payload/scripts/safety_gate.py +64 -0
  148. package/skills/torusguard/payload/scripts/sarif_exporter.py +116 -0
  149. package/skills/torusguard/payload/scripts/stack_detect.py +152 -0
  150. package/skills/torusguard/payload/skills/torusguard/SKILL.md +37 -0
  151. package/skills/torusguard/payload/skills/torusguard/bootstrap.py +158 -0
  152. package/skills/torusguard/payload/skills/torusguard/references/auth-and-sessions.md +56 -0
  153. package/skills/torusguard/payload/skills/torusguard/references/business-logic-and-abuse.md +23 -0
  154. package/skills/torusguard/payload/skills/torusguard/references/cache-and-sensitive-responses.md +10 -0
  155. package/skills/torusguard/payload/skills/torusguard/references/client-code-exposure.md +55 -0
  156. package/skills/torusguard/payload/skills/torusguard/references/csrf-and-cross-origin.md +11 -0
  157. package/skills/torusguard/payload/skills/torusguard/references/dependency-and-supply-chain.md +22 -0
  158. package/skills/torusguard/payload/skills/torusguard/references/django-security.md +43 -0
  159. package/skills/torusguard/payload/skills/torusguard/references/drf-security.md +20 -0
  160. package/skills/torusguard/payload/skills/torusguard/references/fastapi-security.md +20 -0
  161. package/skills/torusguard/payload/skills/torusguard/references/flask-security.md +20 -0
  162. package/skills/torusguard/payload/skills/torusguard/references/frontend-no-db.md +53 -0
  163. package/skills/torusguard/payload/skills/torusguard/references/graphql-security.md +12 -0
  164. package/skills/torusguard/payload/skills/torusguard/references/input-and-injection.md +51 -0
  165. package/skills/torusguard/payload/skills/torusguard/references/mass-assignment-and-property-auth.md +22 -0
  166. package/skills/torusguard/payload/skills/torusguard/references/platform-hardening.md +56 -0
  167. package/skills/torusguard/payload/skills/torusguard/references/python-dependencies.md +16 -0
  168. package/skills/torusguard/payload/skills/torusguard/references/python-security-overview.md +12 -0
  169. package/skills/torusguard/payload/skills/torusguard/references/rate-limit-and-abuse.md +57 -0
  170. package/skills/torusguard/payload/skills/torusguard/references/secrets-and-config.md +64 -0
  171. package/skills/torusguard/payload/skills/torusguard/references/sqlalchemy-security.md +16 -0
  172. package/skills/torusguard/payload/skills/torusguard/references/ssrf-and-outbound-requests.md +46 -0
  173. package/skills/torusguard/payload/skills/torusguard/references/webhook-security.md +15 -0
  174. package/skills/torusguard/payload/skills/torusguard/references/websocket-security.md +12 -0
  175. package/skills/torusguard/payload/skills/torusguard-apply/SKILL.md +46 -0
  176. package/skills/torusguard/payload/skills/torusguard-audit/SKILL.md +70 -0
  177. package/skills/torusguard/payload/skills/torusguard-authorize/SKILL.md +47 -0
  178. package/skills/torusguard/payload/skills/torusguard-exploit-check/SKILL.md +64 -0
  179. package/skills/torusguard/payload/skills/torusguard-full/SKILL.md +70 -0
  180. package/skills/torusguard/payload/skills/torusguard-harden/SKILL.md +63 -0
  181. package/skills/torusguard/payload/skills/torusguard-init/SKILL.md +52 -0
  182. package/skills/torusguard/payload/skills/torusguard-recheck/SKILL.md +53 -0
  183. package/skills/torusguard/payload/skills/torusguard-report/SKILL.md +54 -0
  184. package/skills/torusguard/payload/skills/torusguard-status/SKILL.md +42 -0
  185. package/skills/torusguard/payload/skills/torusguard-verify/SKILL.md +55 -0
  186. package/skills/torusguard/payload/skills/torusguard-web-validate/SKILL.md +64 -0
  187. package/skills/torusguard/payload/templates/audit-report.template.md +54 -0
  188. package/skills/torusguard/payload/templates/authorization.template.md +34 -0
  189. package/skills/torusguard/payload/templates/finding-card.template.md +32 -0
  190. package/skills/torusguard/payload/templates/remediation-bundle.template.md +35 -0
  191. package/skills/torusguard/payload/workflows/apply.md +95 -0
  192. package/skills/torusguard/payload/workflows/audit.md +93 -0
  193. package/skills/torusguard/payload/workflows/authorize.md +95 -0
  194. package/skills/torusguard/payload/workflows/exploit-check.md +97 -0
  195. package/skills/torusguard/payload/workflows/harden.md +93 -0
  196. package/skills/torusguard/payload/workflows/init.md +95 -0
  197. package/skills/torusguard/payload/workflows/recheck.md +95 -0
  198. package/skills/torusguard/payload/workflows/report.md +95 -0
  199. package/skills/torusguard/payload/workflows/status.md +95 -0
  200. package/skills/torusguard/payload/workflows/verify.md +95 -0
  201. package/skills/torusguard/payload/workflows/web-validate.md +95 -0
  202. package/skills/torusguard/references/auth-and-sessions.md +56 -0
  203. package/skills/torusguard/references/business-logic-and-abuse.md +23 -0
  204. package/skills/torusguard/references/cache-and-sensitive-responses.md +10 -0
  205. package/skills/torusguard/references/client-code-exposure.md +55 -0
  206. package/skills/torusguard/references/csrf-and-cross-origin.md +11 -0
  207. package/skills/torusguard/references/dependency-and-supply-chain.md +22 -0
  208. package/skills/torusguard/references/django-security.md +43 -0
  209. package/skills/torusguard/references/drf-security.md +20 -0
  210. package/skills/torusguard/references/fastapi-security.md +20 -0
  211. package/skills/torusguard/references/flask-security.md +20 -0
  212. package/skills/torusguard/references/frontend-no-db.md +53 -0
  213. package/skills/torusguard/references/graphql-security.md +12 -0
  214. package/skills/torusguard/references/input-and-injection.md +51 -0
  215. package/skills/torusguard/references/mass-assignment-and-property-auth.md +22 -0
  216. package/skills/torusguard/references/platform-hardening.md +56 -0
  217. package/skills/torusguard/references/python-dependencies.md +16 -0
  218. package/skills/torusguard/references/python-security-overview.md +12 -0
  219. package/skills/torusguard/references/rate-limit-and-abuse.md +57 -0
  220. package/skills/torusguard/references/secrets-and-config.md +64 -0
  221. package/skills/torusguard/references/sqlalchemy-security.md +16 -0
  222. package/skills/torusguard/references/ssrf-and-outbound-requests.md +46 -0
  223. package/skills/torusguard/references/webhook-security.md +15 -0
  224. package/skills/torusguard/references/websocket-security.md +12 -0
  225. package/skills/torusguard-apply/SKILL.md +46 -0
  226. package/skills/torusguard-audit/SKILL.md +70 -0
  227. package/skills/torusguard-authorize/SKILL.md +47 -0
  228. package/skills/torusguard-exploit-check/SKILL.md +64 -0
  229. package/skills/torusguard-full/SKILL.md +70 -0
  230. package/skills/torusguard-harden/SKILL.md +63 -0
  231. package/skills/torusguard-init/SKILL.md +52 -0
  232. package/skills/torusguard-recheck/SKILL.md +53 -0
  233. package/skills/torusguard-report/SKILL.md +54 -0
  234. package/skills/torusguard-status/SKILL.md +42 -0
  235. package/skills/torusguard-verify/SKILL.md +55 -0
  236. package/skills/torusguard-web-validate/SKILL.md +64 -0
@@ -0,0 +1,130 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ TorusGuard Cryptographic Manifest Builder & Verifier
4
+ Generates or validates SHA-256 integrity digests for all .torusguard files.
5
+ """
6
+
7
+ import os
8
+ import sys
9
+ import json
10
+ import hashlib
11
+ import argparse
12
+ from pathlib import Path
13
+
14
+
15
+ def compute_file_sha256(filepath):
16
+ """Compute SHA-256 digest of a file in binary mode."""
17
+ hasher = hashlib.sha256()
18
+ with open(filepath, "rb") as fh:
19
+ while chunk := fh.read(65536):
20
+ hasher.update(chunk)
21
+ return hasher.hexdigest()
22
+
23
+
24
+ def scan_workspace_files(base_dir):
25
+ """Scan all files inside .torusguard, ignoring runs, pyc, and gitkeep."""
26
+ base_dir = Path(base_dir).resolve()
27
+ file_map = {}
28
+
29
+ for root, dirs, files in os.walk(base_dir):
30
+ if "runs" in dirs:
31
+ dirs.remove("runs")
32
+ if "__pycache__" in dirs:
33
+ dirs.remove("__pycache__")
34
+
35
+ for f in sorted(files):
36
+ if f in [".manifest.json", ".gitkeep"] or f.endswith(".pyc"):
37
+ continue
38
+ full_path = Path(root) / f
39
+ rel_path = full_path.relative_to(base_dir).as_posix()
40
+ file_map[rel_path] = compute_file_sha256(full_path)
41
+
42
+ return file_map
43
+
44
+
45
+ def check_manifest(base_dir):
46
+ """Check disk files against existing .manifest.json."""
47
+ base_dir = Path(base_dir).resolve()
48
+ manifest_file = base_dir / ".manifest.json"
49
+
50
+ if not manifest_file.exists():
51
+ print(f"[ERROR] Missing manifest file: {manifest_file}")
52
+ return False
53
+
54
+ with open(manifest_file, "r", encoding="utf-8") as fh:
55
+ expected = json.load(fh)
56
+
57
+ current = scan_workspace_files(base_dir)
58
+
59
+ # Files expected to change during user initialization/configuration
60
+ USER_CONFIGS = {"config/torusguard.json", "config/scope.json"}
61
+
62
+ missing = set(expected.keys()) - set(current.keys())
63
+ added = set(current.keys()) - set(expected.keys())
64
+ altered_core = [k for k in expected if k in current and expected[k] != current[k] and k not in USER_CONFIGS]
65
+ altered_configs = [k for k in expected if k in current and expected[k] != current[k] and k in USER_CONFIGS]
66
+
67
+ print("================================================================================")
68
+ print("TORUSGUARD INTEGRITY MANIFEST VERIFICATION")
69
+ print("================================================================================")
70
+ print(f"Directory: {base_dir}")
71
+ print(f"Indexed Files: {len(expected)}")
72
+
73
+ if missing:
74
+ print(f"\n[FAIL] Missing files ({len(missing)}):")
75
+ for m in sorted(missing):
76
+ print(f" - {m}")
77
+
78
+ if altered_core:
79
+ print(f"\n[FAIL] Altered / Tampered core files ({len(altered_core)}):")
80
+ for a in sorted(altered_core):
81
+ print(f" - {a}")
82
+
83
+ if altered_configs:
84
+ print(f"\n[INFO] Tailored user project configs ({len(altered_configs)}):")
85
+ for ac in sorted(altered_configs):
86
+ print(f" * {ac}")
87
+
88
+ if added:
89
+ print(f"\n[INFO] Untracked new files ({len(added)}):")
90
+ for ad in sorted(added):
91
+ print(f" + {ad}")
92
+
93
+ if not missing and not altered_core:
94
+ print("\n[PASS] 100% of workspace files match cryptographic SHA-256 signatures cleanly.")
95
+ print("================================================================================")
96
+ return True
97
+
98
+ print("\n================================================================================")
99
+ print("INTEGRITY VERIFICATION FAILED")
100
+ print("================================================================================")
101
+ return False
102
+
103
+
104
+ def write_manifest(base_dir):
105
+ """Write freshly computed manifest to .torusguard/.manifest.json."""
106
+ base_dir = Path(base_dir).resolve()
107
+ manifest_file = base_dir / ".manifest.json"
108
+
109
+ current = scan_workspace_files(base_dir)
110
+ with open(manifest_file, "w", encoding="utf-8") as fh:
111
+ json.dump(current, fh, indent=2)
112
+
113
+ print(f"[SUCCESS] Wrote {len(current)} entries to {manifest_file}")
114
+ return True
115
+
116
+
117
+ if __name__ == "__main__":
118
+ parser = argparse.ArgumentParser(description="TorusGuard Manifest Builder & Verifier")
119
+ parser.add_argument("--dir", default=".torusguard", help="Target .torusguard directory")
120
+ parser.add_argument("--write", action="store_true", help="Generate and write manifest")
121
+ parser.add_argument("--check", action="store_true", help="Check workspace against manifest")
122
+ args = parser.parse_args()
123
+
124
+ if args.write:
125
+ success = write_manifest(args.dir)
126
+ else:
127
+ # Default to --check
128
+ success = check_manifest(args.dir)
129
+
130
+ sys.exit(0 if success else 1)
@@ -0,0 +1,164 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ TorusGuard Monorepo & Multi-Package Workspace Detector (v0.9.3)
4
+ Discovers and profiles sub-projects across Turborepo, pnpm, npm, and Python workspaces.
5
+ Pure Python 3.10+ standard library (zero external dependencies).
6
+ """
7
+
8
+ import sys
9
+ import os
10
+ import json
11
+ import re
12
+ import argparse
13
+ from pathlib import Path
14
+ from typing import Dict, List, Any, Optional
15
+
16
+
17
+ def detect_package_info(abs_pkg_dir: Path, root: Path) -> Dict[str, Any]:
18
+ """Inspects a single directory to detect language and framework."""
19
+ rel_path = str(abs_pkg_dir.relative_to(root)).replace('\\', '/')
20
+ name = abs_pkg_dir.name
21
+ language = "unknown"
22
+ framework = "generic"
23
+
24
+ pkg_dir = abs_pkg_dir
25
+
26
+ # Check typescript / javascript
27
+ package_json = pkg_dir / "package.json"
28
+ if package_json.is_file() or list(pkg_dir.glob("*.ts")) or list(pkg_dir.glob("*.js")):
29
+ language = "typescript"
30
+ if package_json.is_file():
31
+ try:
32
+ with open(package_json, "r", encoding="utf-8") as f:
33
+ pj = json.load(f)
34
+ name = pj.get("name", name)
35
+ deps = {**pj.get("dependencies", {}), **pj.get("devDependencies", {})}
36
+ if "next" in deps:
37
+ framework = "nextjs"
38
+ elif "express" in deps:
39
+ framework = "express"
40
+ elif "react" in deps:
41
+ framework = "react"
42
+ elif "vue" in deps or "nuxt" in deps:
43
+ framework = "vue"
44
+ except Exception:
45
+ pass
46
+ elif list(pkg_dir.glob("*next*")) or "next" in pkg_dir.name:
47
+ framework = "nextjs"
48
+
49
+ # Check python
50
+ pyproject = pkg_dir / "pyproject.toml"
51
+ reqs = pkg_dir / "requirements.txt"
52
+ if pyproject.is_file() or reqs.is_file() or list(pkg_dir.glob("*.py")):
53
+ if language == "unknown":
54
+ language = "python"
55
+ content = ""
56
+ if pyproject.is_file():
57
+ content += pyproject.read_text(encoding="utf-8", errors="replace").lower()
58
+ if reqs.is_file():
59
+ content += reqs.read_text(encoding="utf-8", errors="replace").lower()
60
+ for pyf in pkg_dir.glob("*.py"):
61
+ content += pyf.read_text(encoding="utf-8", errors="replace").lower()
62
+
63
+ if "fastapi" in content or "fastapi" in pkg_dir.name:
64
+ framework = "fastapi"
65
+ elif "django" in content or "django" in pkg_dir.name:
66
+ framework = "django"
67
+ elif "flask" in content or "flask" in pkg_dir.name:
68
+ framework = "flask"
69
+
70
+ return {
71
+ "name": name,
72
+ "path": rel_path,
73
+ "language": language,
74
+ "framework": framework
75
+ }
76
+
77
+
78
+ def scan_workspace(root_dir: str = ".") -> Dict[str, Any]:
79
+ """Scans root directory for monorepo configuration and sub-packages."""
80
+ root = Path(root_dir).resolve()
81
+ monorepo_type = "single-project"
82
+ sub_packages: List[Dict[str, Any]] = []
83
+
84
+ # 1. Turborepo
85
+ if (root / "turbo.json").is_file():
86
+ monorepo_type = "turborepo"
87
+
88
+ # 2. pnpm workspace
89
+ pnpm_ws = root / "pnpm-workspace.yaml"
90
+ if pnpm_ws.is_file():
91
+ monorepo_type = "pnpm-workspace"
92
+
93
+ # 3. npm / yarn workspaces
94
+ root_pj = root / "package.json"
95
+ if root_pj.is_file():
96
+ try:
97
+ with open(root_pj, "r", encoding="utf-8") as f:
98
+ data = json.load(f)
99
+ if "workspaces" in data:
100
+ monorepo_type = "npm/yarn-workspaces"
101
+ except Exception:
102
+ pass
103
+
104
+ # Scan common monorepo container directories and direct project subfolders
105
+ candidate_folders = ["apps", "packages", "services", "libs", "modules"]
106
+ found_dirs = []
107
+
108
+ for cf in candidate_folders:
109
+ container = root / cf
110
+ if container.is_dir():
111
+ for child in container.iterdir():
112
+ if child.is_dir() and not child.name.startswith(('.', '_')):
113
+ if any((child / m).exists() for m in ["package.json", "pyproject.toml", "requirements.txt", "setup.py", "Cargo.toml", "main.py"]):
114
+ found_dirs.append(child)
115
+
116
+ # Also scan direct subdirectories if not already captured
117
+ for child in root.iterdir():
118
+ if child.is_dir() and not child.name.startswith(('.', '_')) and child.name not in candidate_folders:
119
+ if any((child / m).exists() for m in ["package.json", "pyproject.toml", "requirements.txt", "setup.py", "Cargo.toml", "main.py", "actions.ts"]):
120
+ if child not in found_dirs:
121
+ found_dirs.append(child)
122
+
123
+ if found_dirs:
124
+ if monorepo_type == "single-project":
125
+ monorepo_type = "multi-package-directory"
126
+ for d in found_dirs:
127
+ sub_packages.append(detect_package_info(d, root))
128
+
129
+ # If no monorepo sub-packages found, treat root as primary
130
+ if not sub_packages:
131
+ sub_packages.append(detect_package_info(root, root))
132
+
133
+ return {
134
+ "root": str(root).replace('\\', '/'),
135
+ "monorepo_type": monorepo_type,
136
+ "is_monorepo": monorepo_type != "single-project",
137
+ "package_count": len(sub_packages),
138
+ "packages": sub_packages
139
+ }
140
+
141
+
142
+ def main():
143
+ parser = argparse.ArgumentParser(description="TorusGuard Monorepo & Multi-Package Detector")
144
+ parser.add_argument("--scan", default=".", help="Root directory to scan (default: .)")
145
+ parser.add_argument("--write", action="store_true", help="Write to .torusguard/config/workspaces.json")
146
+ parser.add_argument("--json", action="store_true", help="Output JSON to stdout")
147
+ args = parser.parse_args()
148
+
149
+ res = scan_workspace(args.scan)
150
+
151
+ if args.write:
152
+ config_dir = Path(args.scan) / ".torusguard" / "config"
153
+ config_dir.mkdir(parents=True, exist_ok=True)
154
+ out_file = config_dir / "workspaces.json"
155
+ with open(out_file, "w", encoding="utf-8") as f:
156
+ json.dump(res, f, indent=2)
157
+ print(f"[SUCCESS] Wrote workspace registry to {out_file}")
158
+
159
+ if args.json or not args.write:
160
+ print(json.dumps(res, indent=2))
161
+
162
+
163
+ if __name__ == "__main__":
164
+ main()
@@ -0,0 +1,89 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ TorusGuard Run Folder Lifecycle Manager
4
+ Creates isolated run folders, tracks manifest.json state, and enumerates execution history.
5
+ """
6
+
7
+ import sys
8
+ import json
9
+ import datetime
10
+ import argparse
11
+ from pathlib import Path
12
+ from typing import Dict, Any, List
13
+
14
+ def create_run(base_dir: Path, command: str, target_name: str = "project") -> Path:
15
+ timestamp = datetime.datetime.utcnow().strftime("%Y%m%d-%H%M%S")
16
+ run_id = f"run-{timestamp}-{command}"
17
+ run_folder = base_dir / run_id
18
+ run_folder.mkdir(parents=True, exist_ok=True)
19
+
20
+ manifest = {
21
+ "run_id": run_id,
22
+ "command": command,
23
+ "target_name": target_name,
24
+ "created_at": datetime.datetime.utcnow().isoformat() + "Z",
25
+ "status": "in_progress",
26
+ "torusguard_version": "0.8.0",
27
+ "findings_count": 0,
28
+ "confirmed_fixed_count": 0,
29
+ "regressed_count": 0
30
+ }
31
+
32
+ manifest_path = run_folder / "manifest.json"
33
+ with open(manifest_path, "w", encoding="utf-8") as f:
34
+ json.dump(manifest, f, indent=2)
35
+
36
+ return run_folder
37
+
38
+
39
+ def list_runs(base_dir: Path) -> List[Dict[str, Any]]:
40
+ runs = []
41
+ if not base_dir.is_dir():
42
+ return runs
43
+
44
+ for d in sorted(base_dir.iterdir(), reverse=True):
45
+ if d.is_dir() and d.name.startswith("run-"):
46
+ manifest_file = d / "manifest.json"
47
+ if manifest_file.is_file():
48
+ try:
49
+ with open(manifest_file, "r", encoding="utf-8") as f:
50
+ data = json.load(f)
51
+ runs.append(data)
52
+ except Exception:
53
+ runs.append({"run_id": d.name, "status": "corrupted"})
54
+ else:
55
+ runs.append({"run_id": d.name, "status": "unmanifested"})
56
+ return runs
57
+
58
+
59
+ def main():
60
+ parser = argparse.ArgumentParser(description="TorusGuard Run Manager")
61
+ subparsers = parser.add_subparsers(dest="subcommand")
62
+
63
+ create_p = subparsers.add_parser("create")
64
+ create_p.add_argument("--command", "-c", default="audit", help="TorusGuard command (audit, web-validate, harden, etc.)")
65
+ create_p.add_argument("--target", "-t", default="project", help="Target project name")
66
+ create_p.add_argument("--dir", "-d", default=".torusguard/runs", help="Base runs directory")
67
+
68
+ list_p = subparsers.add_parser("list")
69
+ list_p.add_argument("--dir", "-d", default=".torusguard/runs", help="Base runs directory")
70
+ list_p.add_argument("--json", action="store_true", help="Output JSON")
71
+
72
+ args = parser.parse_args()
73
+
74
+ if args.subcommand == "create":
75
+ folder = create_run(Path(args.dir), args.command, args.target)
76
+ print(f"Created run folder: {folder}")
77
+ elif args.subcommand == "list":
78
+ runs = list_runs(Path(args.dir))
79
+ if args.json:
80
+ print(json.dumps(runs, indent=2))
81
+ else:
82
+ print(f"Total Runs Found: {len(runs)}")
83
+ for r in runs:
84
+ print(f" - {r.get('run_id')}: command={r.get('command')}, status={r.get('status')}")
85
+ else:
86
+ parser.print_help()
87
+
88
+ if __name__ == "__main__":
89
+ main()
@@ -0,0 +1,64 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ TorusGuard Runtime Safety Gate Evaluator
4
+ Evaluates prospective HTTP/browser validation probes against non-destruction policies.
5
+ """
6
+
7
+ import sys
8
+ import json
9
+ import argparse
10
+ from typing import Dict, Any, Tuple
11
+
12
+ def evaluate_safety_gate(method: str, path: str, body: str = "") -> Tuple[str, str]:
13
+ """
14
+ Returns (decision, rationale)
15
+ Decisions:
16
+ - Auto-Allowed
17
+ - Approval Required
18
+ - Manual Only (Blocked)
19
+ """
20
+ method_upper = method.upper()
21
+
22
+ # Block destructive verbs
23
+ if method_upper in ("DELETE", "DROP"):
24
+ return "Manual Only", f"Method '{method_upper}' is destructive and strictly blocked from automated runtime validation."
25
+
26
+ # Block sensitive administrative paths
27
+ destructive_keywords = ["/admin/delete", "/shutdown", "/drop-database", "/purge", "/reset-system"]
28
+ for kw in destructive_keywords:
29
+ if kw in path.lower():
30
+ return "Manual Only", f"Path '{path}' targets destructive administrative endpoint '{kw}'."
31
+
32
+ # Safe read methods
33
+ if method_upper in ("GET", "HEAD", "OPTIONS"):
34
+ return "Auto-Allowed", f"Read-only method '{method_upper}' with non-destructive path."
35
+
36
+ # State-changing methods (POST, PUT, PATCH)
37
+ if method_upper in ("POST", "PUT", "PATCH"):
38
+ # Check if safe canary marker exists
39
+ if "tg-canary" in body.lower() or "torusguard" in body.lower():
40
+ return "Approval Required", f"State-changing method '{method_upper}' contains benign TorusGuard test marker; requires user approval."
41
+ else:
42
+ return "Approval Required", f"State-changing method '{method_upper}' requires operator approval before execution."
43
+
44
+ return "Approval Required", f"Unknown probe profile for {method_upper} {path}."
45
+
46
+
47
+ def main():
48
+ parser = argparse.ArgumentParser(description="TorusGuard Safety Gate Evaluator")
49
+ parser.add_argument("--method", "-m", default="GET", help="HTTP Method")
50
+ parser.add_argument("--path", "-p", default="/api/test", help="Endpoint path")
51
+ parser.add_argument("--body", "-b", default="", help="Request payload body")
52
+ parser.add_argument("--json", action="store_true", help="Output JSON")
53
+ args = parser.parse_args()
54
+
55
+ decision, rationale = evaluate_safety_gate(args.method, args.path, args.body)
56
+
57
+ if args.json:
58
+ print(json.dumps({"decision": decision, "rationale": rationale}, indent=2))
59
+ else:
60
+ print(f"Safety Decision: {decision}")
61
+ print(f"Rationale: {rationale}")
62
+
63
+ if __name__ == "__main__":
64
+ main()
@@ -0,0 +1,116 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ TorusGuard OASIS SARIF v2.1.0 Exporter
4
+ Converts normalized TorusGuard findings into standard SARIF v2.1.0 format with
5
+ GitHub Code Scanning multi-analysis category separation and partialFingerprints deduplication.
6
+ """
7
+
8
+ import sys
9
+ import json
10
+ import hashlib
11
+ import argparse
12
+ from typing import List, Dict, Any
13
+
14
+ def generate_sarif(findings: List[Dict[str, Any]], run_id: str = "default", category: str = "torusguard/static") -> Dict[str, Any]:
15
+ rules_map: Dict[str, Dict[str, Any]] = {}
16
+ results: List[Dict[str, Any]] = []
17
+
18
+ for f in findings:
19
+ rule_id = f.get("rule_id", "TG-GEN-001")
20
+ if rule_id not in rules_map:
21
+ rules_map[rule_id] = {
22
+ "id": rule_id,
23
+ "name": f.get("title", rule_id),
24
+ "shortDescription": {"text": f.get("title", rule_id)},
25
+ "fullDescription": {"text": f.get("description", f.get("title", rule_id))},
26
+ "defaultConfiguration": {
27
+ "level": "error" if f.get("severity") in ("Critical", "High") else "warning"
28
+ },
29
+ "properties": {
30
+ "tags": ["security", "torusguard", f.get("category", "general")]
31
+ }
32
+ }
33
+
34
+ target = f.get("target", {})
35
+ file_path = target.get("file_path", "unknown")
36
+ line = target.get("start_line", 1)
37
+
38
+ # Generate deduplication fingerprint
39
+ seed = f"{rule_id}:{file_path}:{line}"
40
+ line_hash = hashlib.sha256(seed.encode("utf-8")).hexdigest()[:16]
41
+
42
+ result: Dict[str, Any] = {
43
+ "ruleId": rule_id,
44
+ "message": {"text": f.get("title", "TorusGuard Security Finding")},
45
+ "level": "error" if f.get("severity") in ("Critical", "High") else "warning",
46
+ "locations": [
47
+ {
48
+ "physicalLocation": {
49
+ "artifactLocation": {
50
+ "uri": file_path,
51
+ "uriBaseId": "%SRCROOT%"
52
+ },
53
+ "region": {
54
+ "startLine": line,
55
+ "startColumn": 1
56
+ }
57
+ }
58
+ }
59
+ ],
60
+ "partialFingerprints": {
61
+ "primaryLocationLineHash": line_hash
62
+ },
63
+ "properties": {
64
+ "confidence": f.get("confidence", 70),
65
+ "status": f.get("status", "Confirmed"),
66
+ "finding_id": f.get("finding_id", "TG-FIND-UNKNOWN")
67
+ }
68
+ }
69
+ results.append(result)
70
+
71
+ sarif = {
72
+ "$schema": "https://raw.githubusercontent.com/oasis-tcs/sarif-spec/master/Schemata/sarif-schema-2.1.0.json",
73
+ "version": "2.1.0",
74
+ "runs": [
75
+ {
76
+ "tool": {
77
+ "driver": {
78
+ "name": "TorusGuard",
79
+ "semanticVersion": "0.8.0",
80
+ "informationUri": "https://github.com/githubmofo/TorusGuard",
81
+ "rules": list(rules_map.values())
82
+ }
83
+ },
84
+ "automationDetails": {
85
+ "id": f"{category}/{run_id}"
86
+ },
87
+ "results": results
88
+ }
89
+ ]
90
+ }
91
+ return sarif
92
+
93
+
94
+ def main():
95
+ parser = argparse.ArgumentParser(description="TorusGuard SARIF v2.1.0 Exporter")
96
+ parser.add_argument("--input", "-i", help="Path to findings JSON file")
97
+ parser.add_argument("--output", "-o", help="Output path for sarif.json")
98
+ parser.add_argument("--run-id", default="run-default", help="Unique execution Run ID")
99
+ args = parser.parse_args()
100
+
101
+ findings = []
102
+ if args.input:
103
+ with open(args.input, "r", encoding="utf-8") as f:
104
+ findings = json.load(f)
105
+
106
+ sarif = generate_sarif(findings, run_id=args.run_id)
107
+
108
+ if args.output:
109
+ with open(args.output, "w", encoding="utf-8") as f:
110
+ json.dump(sarif, f, indent=2)
111
+ print(f"SARIF log written to: {args.output}")
112
+ else:
113
+ print(json.dumps(sarif, indent=2))
114
+
115
+ if __name__ == "__main__":
116
+ main()