torusguard 0.9.5 → 1.3.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.
- package/.torusguard/.manifest.json +98 -79
- package/.torusguard/config/torusguard.json +1 -1
- package/.torusguard/references/csharp-security.md +41 -0
- package/.torusguard/references/go-security.md +41 -0
- package/.torusguard/references/java-security.md +40 -0
- package/.torusguard/references/polyglot-security-matrix.md +25 -0
- package/.torusguard/references/rust-security.md +40 -0
- package/.torusguard/rules/custom/.gitkeep +1 -0
- package/.torusguard/rules/custom/README.md +30 -0
- package/.torusguard/runs/report-latest.html +328 -0
- package/.torusguard/schemas/golden-recipe.schema.json +75 -0
- package/.torusguard/schemas/memory-context.schema.json +95 -0
- package/.torusguard/schemas/memory-event.schema.json +70 -0
- package/.torusguard/schemas/memory-pattern.schema.json +65 -0
- package/.torusguard/scripts/diff_guard.py +202 -15
- package/.torusguard/scripts/finding_scorer.py +199 -86
- package/.torusguard/scripts/html_reporter.py +628 -0
- package/.torusguard/scripts/manifest_builder.py +7 -5
- package/.torusguard/scripts/memory_engine.py +1334 -0
- package/.torusguard/scripts/monorepo_detector.py +123 -10
- package/.torusguard/scripts/rules_sync.py +321 -0
- package/.torusguard/scripts/run_manager.py +171 -89
- package/.torusguard/scripts/stack_detect.py +458 -26
- package/.torusguard/skills/torusguard/SKILL.md +4 -3
- package/.torusguard/skills/torusguard/bootstrap.py +344 -56
- package/.torusguard/skills/torusguard/references/csharp-security.md +41 -0
- package/.torusguard/skills/torusguard/references/go-security.md +41 -0
- package/.torusguard/skills/torusguard/references/java-security.md +40 -0
- package/.torusguard/skills/torusguard/references/polyglot-security-matrix.md +25 -0
- package/.torusguard/skills/torusguard/references/rust-security.md +40 -0
- package/.torusguard/skills/torusguard-audit/SKILL.md +25 -25
- package/.torusguard/skills/torusguard-harden/SKILL.md +3 -3
- package/.torusguard/skills/torusguard-recheck/SKILL.md +3 -3
- package/.torusguard/workflows/memory.md +53 -0
- package/README.md +307 -401
- package/bin/torusguard.js +204 -6
- package/package.json +1 -1
- package/skills/torusguard/SKILL.md +4 -3
- package/skills/torusguard/bootstrap.py +68 -4
- package/skills/torusguard/payload/.manifest.json +98 -79
- package/skills/torusguard/payload/config/torusguard.json +1 -1
- package/skills/torusguard/payload/references/csharp-security.md +41 -0
- package/skills/torusguard/payload/references/go-security.md +41 -0
- package/skills/torusguard/payload/references/java-security.md +40 -0
- package/skills/torusguard/payload/references/polyglot-security-matrix.md +25 -0
- package/skills/torusguard/payload/references/rust-security.md +40 -0
- package/skills/torusguard/payload/rules/custom/.gitkeep +1 -0
- package/skills/torusguard/payload/rules/custom/README.md +30 -0
- package/skills/torusguard/payload/schemas/golden-recipe.schema.json +75 -0
- package/skills/torusguard/payload/schemas/memory-context.schema.json +95 -0
- package/skills/torusguard/payload/schemas/memory-event.schema.json +70 -0
- package/skills/torusguard/payload/schemas/memory-pattern.schema.json +65 -0
- package/skills/torusguard/payload/scripts/diff_guard.py +202 -15
- package/skills/torusguard/payload/scripts/finding_scorer.py +199 -86
- package/skills/torusguard/payload/scripts/html_reporter.py +628 -0
- package/skills/torusguard/payload/scripts/manifest_builder.py +7 -5
- package/skills/torusguard/payload/scripts/memory_engine.py +1334 -0
- package/skills/torusguard/payload/scripts/monorepo_detector.py +123 -10
- package/skills/torusguard/payload/scripts/rules_sync.py +321 -0
- package/skills/torusguard/payload/scripts/run_manager.py +171 -89
- package/skills/torusguard/payload/scripts/stack_detect.py +458 -26
- package/skills/torusguard/payload/skills/torusguard/SKILL.md +4 -3
- package/skills/torusguard/payload/skills/torusguard/bootstrap.py +344 -56
- package/skills/torusguard/payload/skills/torusguard/references/csharp-security.md +41 -0
- package/skills/torusguard/payload/skills/torusguard/references/go-security.md +41 -0
- package/skills/torusguard/payload/skills/torusguard/references/java-security.md +40 -0
- package/skills/torusguard/payload/skills/torusguard/references/polyglot-security-matrix.md +25 -0
- package/skills/torusguard/payload/skills/torusguard/references/rust-security.md +40 -0
- package/skills/torusguard/payload/skills/torusguard-audit/SKILL.md +25 -25
- package/skills/torusguard/payload/skills/torusguard-harden/SKILL.md +3 -3
- package/skills/torusguard/payload/skills/torusguard-recheck/SKILL.md +3 -3
- package/skills/torusguard/payload/workflows/memory.md +53 -0
- package/skills/torusguard-audit/SKILL.md +25 -25
- package/skills/torusguard-harden/SKILL.md +3 -3
- package/skills/torusguard-recheck/SKILL.md +3 -3
- package/.torusguard/scripts/__pycache__/diff_guard.cpython-311.pyc +0 -0
- package/.torusguard/scripts/__pycache__/monorepo_detector.cpython-311.pyc +0 -0
- package/skills/torusguard/__pycache__/bootstrap.cpython-311.pyc +0 -0
- package/skills/torusguard/payload/scripts/__pycache__/diff_guard.cpython-311.pyc +0 -0
- package/skills/torusguard/payload/scripts/__pycache__/monorepo_detector.cpython-311.pyc +0 -0
|
@@ -1,89 +1,171 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
|
-
"""
|
|
3
|
-
TorusGuard Run Folder Lifecycle Manager
|
|
4
|
-
Creates isolated run folders, tracks manifest.json state,
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
import
|
|
9
|
-
import
|
|
10
|
-
import
|
|
11
|
-
|
|
12
|
-
from
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
"
|
|
24
|
-
"
|
|
25
|
-
"
|
|
26
|
-
"
|
|
27
|
-
"
|
|
28
|
-
"
|
|
29
|
-
"
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
runs.append(
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
TorusGuard Run Folder Lifecycle Manager (v1.0.0)
|
|
4
|
+
Creates isolated run folders, tracks manifest.json state, enumerates execution history,
|
|
5
|
+
and bridges completed run findings to the persistent security memory engine.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import sys
|
|
9
|
+
import json
|
|
10
|
+
import datetime
|
|
11
|
+
import argparse
|
|
12
|
+
from pathlib import Path
|
|
13
|
+
from typing import Dict, Any, List, Optional
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def create_run(base_dir: Path, command: str, target_name: str = "project") -> Path:
|
|
17
|
+
timestamp = datetime.datetime.utcnow().strftime("%Y%m%d-%H%M%S")
|
|
18
|
+
run_id = f"run-{timestamp}-{command}"
|
|
19
|
+
run_folder = base_dir / run_id
|
|
20
|
+
run_folder.mkdir(parents=True, exist_ok=True)
|
|
21
|
+
|
|
22
|
+
manifest = {
|
|
23
|
+
"run_id": run_id,
|
|
24
|
+
"command": command,
|
|
25
|
+
"target_name": target_name,
|
|
26
|
+
"created_at": datetime.datetime.utcnow().isoformat() + "Z",
|
|
27
|
+
"status": "in_progress",
|
|
28
|
+
"torusguard_version": "1.0.0",
|
|
29
|
+
"findings_count": 0,
|
|
30
|
+
"confirmed_fixed_count": 0,
|
|
31
|
+
"regressed_count": 0
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
manifest_path = run_folder / "manifest.json"
|
|
35
|
+
with open(manifest_path, "w", encoding="utf-8") as f:
|
|
36
|
+
json.dump(manifest, f, indent=2)
|
|
37
|
+
|
|
38
|
+
return run_folder
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def list_runs(base_dir: Path) -> List[Dict[str, Any]]:
|
|
42
|
+
runs = []
|
|
43
|
+
if not base_dir.is_dir():
|
|
44
|
+
return runs
|
|
45
|
+
|
|
46
|
+
for d in sorted(base_dir.iterdir(), reverse=True):
|
|
47
|
+
if d.is_dir() and d.name.startswith("run-"):
|
|
48
|
+
manifest_file = d / "manifest.json"
|
|
49
|
+
if manifest_file.is_file():
|
|
50
|
+
try:
|
|
51
|
+
with open(manifest_file, "r", encoding="utf-8") as f:
|
|
52
|
+
data = json.load(f)
|
|
53
|
+
runs.append(data)
|
|
54
|
+
except Exception:
|
|
55
|
+
runs.append({"run_id": d.name, "status": "corrupted"})
|
|
56
|
+
else:
|
|
57
|
+
runs.append({"run_id": d.name, "status": "unmanifested"})
|
|
58
|
+
return runs
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def sync_run_to_memory(run_folder: Path, findings: Optional[List[Dict[str, Any]]] = None) -> int:
|
|
62
|
+
"""
|
|
63
|
+
Sync findings from a completed run into the .torusguard/memory/ engine.
|
|
64
|
+
Records events based on command type (audit -> audit_finding, apply -> fix_applied, recheck -> fix_verified).
|
|
65
|
+
"""
|
|
66
|
+
manifest_file = run_folder / "manifest.json"
|
|
67
|
+
if not manifest_file.is_file():
|
|
68
|
+
return 0
|
|
69
|
+
|
|
70
|
+
try:
|
|
71
|
+
with open(manifest_file, "r", encoding="utf-8") as f:
|
|
72
|
+
manifest = json.load(f)
|
|
73
|
+
except Exception:
|
|
74
|
+
return 0
|
|
75
|
+
|
|
76
|
+
command = manifest.get("command", "audit")
|
|
77
|
+
|
|
78
|
+
# If findings not explicitly provided, try reading findings.json in run_folder
|
|
79
|
+
actual_findings = findings
|
|
80
|
+
if actual_findings is None:
|
|
81
|
+
findings_file = run_folder / "findings.json"
|
|
82
|
+
if findings_file.is_file():
|
|
83
|
+
try:
|
|
84
|
+
with open(findings_file, "r", encoding="utf-8") as f:
|
|
85
|
+
actual_findings = json.load(f)
|
|
86
|
+
except Exception:
|
|
87
|
+
actual_findings = []
|
|
88
|
+
|
|
89
|
+
if not actual_findings or not isinstance(actual_findings, list):
|
|
90
|
+
return 0
|
|
91
|
+
|
|
92
|
+
# Import memory_engine in-process
|
|
93
|
+
try:
|
|
94
|
+
scripts_dir = Path(__file__).resolve().parent
|
|
95
|
+
if str(scripts_dir) not in sys.path:
|
|
96
|
+
sys.path.insert(0, str(scripts_dir))
|
|
97
|
+
import memory_engine
|
|
98
|
+
|
|
99
|
+
recorded_count = 0
|
|
100
|
+
for f in actual_findings:
|
|
101
|
+
rule_id = f.get("rule_id") or f.get("id")
|
|
102
|
+
if not rule_id:
|
|
103
|
+
continue
|
|
104
|
+
|
|
105
|
+
event_type = "audit_finding"
|
|
106
|
+
if command in ("harden", "apply"):
|
|
107
|
+
event_type = "fix_applied"
|
|
108
|
+
elif command in ("recheck", "verify"):
|
|
109
|
+
event_type = "fix_verified"
|
|
110
|
+
|
|
111
|
+
data = {
|
|
112
|
+
"rule_id": rule_id,
|
|
113
|
+
"file_path": f.get("file_path") or f.get("file"),
|
|
114
|
+
"line_number": f.get("line_number") or f.get("line"),
|
|
115
|
+
"severity": (f.get("severity") or "medium").lower(),
|
|
116
|
+
"confidence_score": f.get("confidence_score") or f.get("confidence", 70),
|
|
117
|
+
"code_hash": f.get("code_hash"),
|
|
118
|
+
"fix_strategy": f.get("fix_strategy") or f.get("strategy"),
|
|
119
|
+
"verification_result": f.get("verification_result") or f.get("result", "fixed"),
|
|
120
|
+
"suppression_reason": f.get("suppression_reason")
|
|
121
|
+
}
|
|
122
|
+
memory_engine.record_event(event_type, data)
|
|
123
|
+
recorded_count += 1
|
|
124
|
+
|
|
125
|
+
if recorded_count > 0:
|
|
126
|
+
memory_engine.distill_patterns()
|
|
127
|
+
|
|
128
|
+
return recorded_count
|
|
129
|
+
except Exception as e:
|
|
130
|
+
# Non-blocking: memory failure should never crash a run
|
|
131
|
+
return 0
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
def main():
|
|
135
|
+
parser = argparse.ArgumentParser(description="TorusGuard Run Manager")
|
|
136
|
+
subparsers = parser.add_subparsers(dest="subcommand")
|
|
137
|
+
|
|
138
|
+
create_p = subparsers.add_parser("create")
|
|
139
|
+
create_p.add_argument("--command", "-c", default="audit", help="TorusGuard command (audit, web-validate, harden, etc.)")
|
|
140
|
+
create_p.add_argument("--target", "-t", default="project", help="Target project name")
|
|
141
|
+
create_p.add_argument("--dir", "-d", default=".torusguard/runs", help="Base runs directory")
|
|
142
|
+
|
|
143
|
+
list_p = subparsers.add_parser("list")
|
|
144
|
+
list_p.add_argument("--dir", "-d", default=".torusguard/runs", help="Base runs directory")
|
|
145
|
+
list_p.add_argument("--json", action="store_true", help="Output JSON")
|
|
146
|
+
|
|
147
|
+
sync_p = subparsers.add_parser("sync-memory")
|
|
148
|
+
sync_p.add_argument("--run-folder", "-r", required=True, help="Path to run folder")
|
|
149
|
+
|
|
150
|
+
args = parser.parse_args()
|
|
151
|
+
|
|
152
|
+
if args.subcommand == "create":
|
|
153
|
+
folder = create_run(Path(args.dir), args.command, args.target)
|
|
154
|
+
print(f"Created run folder: {folder}")
|
|
155
|
+
elif args.subcommand == "list":
|
|
156
|
+
runs = list_runs(Path(args.dir))
|
|
157
|
+
if args.json:
|
|
158
|
+
print(json.dumps(runs, indent=2))
|
|
159
|
+
else:
|
|
160
|
+
print(f"Total Runs Found: {len(runs)}")
|
|
161
|
+
for r in runs:
|
|
162
|
+
print(f" - {r.get('run_id')}: command={r.get('command')}, status={r.get('status')}")
|
|
163
|
+
elif args.subcommand == "sync-memory":
|
|
164
|
+
count = sync_run_to_memory(Path(args.run_folder))
|
|
165
|
+
print(f"Synced {count} findings from run to memory.")
|
|
166
|
+
else:
|
|
167
|
+
parser.print_help()
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
if __name__ == "__main__":
|
|
171
|
+
main()
|