torusguard 2.1.0 → 2.1.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.
- package/.torusguard/.manifest.json +55 -5
- package/.torusguard/core/__init__.py +146 -0
- package/.torusguard/core/agent_roles.py +104 -0
- package/.torusguard/core/ast_walker.py +283 -0
- package/.torusguard/core/authorization.py +218 -0
- package/.torusguard/core/browser_verifier.py +128 -0
- package/.torusguard/core/bundle.py +141 -0
- package/.torusguard/core/call_graph.py +184 -0
- package/.torusguard/core/clustering.py +275 -0
- package/.torusguard/core/confidence.py +120 -0
- package/.torusguard/core/cross_file_taint.py +101 -0
- package/.torusguard/core/exploit_checker.py +317 -0
- package/.torusguard/core/formatter.py +351 -0
- package/.torusguard/core/governance.py +210 -0
- package/.torusguard/core/identity.py +104 -0
- package/.torusguard/core/import_resolver.py +91 -0
- package/.torusguard/core/incremental.py +102 -0
- package/.torusguard/core/lifecycle.py +137 -0
- package/.torusguard/core/models.py +425 -0
- package/.torusguard/core/parallel.py +56 -0
- package/.torusguard/core/parser.py +202 -0
- package/.torusguard/core/rechecker.py +107 -0
- package/.torusguard/core/replay_trace.py +178 -0
- package/.torusguard/core/rules_registry.py +131 -0
- package/.torusguard/core/run_folder.py +60 -0
- package/.torusguard/core/run_manager.py +163 -0
- package/.torusguard/core/runtime_evidence.py +175 -0
- package/.torusguard/core/runtime_validator.py +246 -0
- package/.torusguard/core/safety_gate.py +139 -0
- package/.torusguard/core/sarif.py +189 -0
- package/.torusguard/core/stack_profiler.py +184 -0
- package/.torusguard/core/symbol_table.py +91 -0
- package/.torusguard/core/taint.py +133 -0
- package/.torusguard/core/taint_graph.py +235 -0
- package/.torusguard/core/taint_rules.py +268 -0
- package/.torusguard/core/v070_reporter.py +102 -0
- package/.torusguard/core/v070_workflow.py +339 -0
- package/.torusguard/core/v6_reporter.py +180 -0
- package/.torusguard/core/v6_workflow.py +221 -0
- package/.torusguard/core/watcher.py +58 -0
- package/.torusguard/custom_rules/README.md +24 -0
- package/.torusguard/rules/TG-INPUT-007-unvalidated-redirect.md +53 -0
- package/.torusguard/rules/TG-INPUT-008-insecure-deserialization.md +52 -0
- package/.torusguard/scripts/__pycache__/audit_runner.cpython-314.pyc +0 -0
- package/.torusguard/scripts/__pycache__/finding_scorer.cpython-314.pyc +0 -0
- package/.torusguard/scripts/__pycache__/manifest_builder.cpython-314.pyc +0 -0
- package/.torusguard/scripts/__pycache__/rules_sync.cpython-314.pyc +0 -0
- package/.torusguard/scripts/audit_runner.py +108 -10
- package/.torusguard/scripts/deliberation_tournament.py +136 -0
- package/.torusguard/scripts/finding_scorer.py +43 -13
- package/.torusguard/scripts/reachability_analyzer.py +165 -0
- package/.torusguard/scripts/skill_profiler.py +26 -0
- package/.torusguard/scripts/stride_generator.py +198 -0
- package/.torusguard/skills/torusguard/SKILL.md +6 -2
- package/.torusguard/skills/torusguard-audit/SKILL.md +109 -84
- package/.torusguard/skills/torusguard-review/SKILL.md +27 -0
- package/.torusguard/skills/torusguard-threatmodel/SKILL.md +27 -0
- package/.torusguard/workflows/audit.md +21 -17
- package/.torusguard/workflows/review.md +11 -0
- package/.torusguard/workflows/threatmodel.md +9 -0
- package/README.md +149 -48
- package/package.json +10 -2
- package/skills/torusguard/SKILL.md +6 -2
- package/skills/torusguard/__pycache__/bootstrap.cpython-314.pyc +0 -0
- package/skills/torusguard/bootstrap.py +3 -3
- package/skills/torusguard/payload/.manifest.json +56 -7
- package/skills/torusguard/payload/core/__init__.py +146 -0
- package/skills/torusguard/payload/core/agent_roles.py +104 -0
- package/skills/torusguard/payload/core/ast_walker.py +283 -0
- package/skills/torusguard/payload/core/authorization.py +218 -0
- package/skills/torusguard/payload/core/browser_verifier.py +128 -0
- package/skills/torusguard/payload/core/bundle.py +141 -0
- package/skills/torusguard/payload/core/call_graph.py +184 -0
- package/skills/torusguard/payload/core/clustering.py +275 -0
- package/skills/torusguard/payload/core/confidence.py +120 -0
- package/skills/torusguard/payload/core/cross_file_taint.py +101 -0
- package/skills/torusguard/payload/core/exploit_checker.py +317 -0
- package/skills/torusguard/payload/core/formatter.py +351 -0
- package/skills/torusguard/payload/core/governance.py +210 -0
- package/skills/torusguard/payload/core/identity.py +104 -0
- package/skills/torusguard/payload/core/import_resolver.py +91 -0
- package/skills/torusguard/payload/core/incremental.py +102 -0
- package/skills/torusguard/payload/core/lifecycle.py +137 -0
- package/skills/torusguard/payload/core/models.py +425 -0
- package/skills/torusguard/payload/core/parallel.py +56 -0
- package/skills/torusguard/payload/core/parser.py +202 -0
- package/skills/torusguard/payload/core/rechecker.py +107 -0
- package/skills/torusguard/payload/core/replay_trace.py +178 -0
- package/skills/torusguard/payload/core/rules_registry.py +131 -0
- package/skills/torusguard/payload/core/run_folder.py +60 -0
- package/skills/torusguard/payload/core/run_manager.py +163 -0
- package/skills/torusguard/payload/core/runtime_evidence.py +175 -0
- package/skills/torusguard/payload/core/runtime_validator.py +246 -0
- package/skills/torusguard/payload/core/safety_gate.py +139 -0
- package/skills/torusguard/payload/core/sarif.py +189 -0
- package/skills/torusguard/payload/core/stack_profiler.py +184 -0
- package/skills/torusguard/payload/core/symbol_table.py +91 -0
- package/skills/torusguard/payload/core/taint.py +133 -0
- package/skills/torusguard/payload/core/taint_graph.py +235 -0
- package/skills/torusguard/payload/core/taint_rules.py +268 -0
- package/skills/torusguard/payload/core/v070_reporter.py +102 -0
- package/skills/torusguard/payload/core/v070_workflow.py +339 -0
- package/skills/torusguard/payload/core/v6_reporter.py +180 -0
- package/skills/torusguard/payload/core/v6_workflow.py +221 -0
- package/skills/torusguard/payload/core/watcher.py +58 -0
- package/skills/torusguard/payload/custom_rules/README.md +15 -0
- package/skills/torusguard/payload/rules/TG-INPUT-007-unvalidated-redirect.md +53 -0
- package/skills/torusguard/payload/rules/TG-INPUT-008-insecure-deserialization.md +52 -0
- package/skills/torusguard/payload/rules/container/TG-CONT-001-root-user-execution.md +50 -50
- package/skills/torusguard/payload/rules/container/TG-CONT-002-docker-socket-mount.md +47 -47
- package/skills/torusguard/payload/rules/container/TG-CONT-003-privileged-container-mode.md +53 -53
- package/skills/torusguard/payload/rules/container/TG-CONT-004-build-arg-secret-exposure.md +43 -43
- package/skills/torusguard/payload/rules/git/TG-GIT-001-historical-secret-in-git-commit.md +44 -44
- package/skills/torusguard/payload/rules/git/TG-GIT-002-plaintext-credentials-in-git-config.md +41 -41
- package/skills/torusguard/payload/rules/git/TG-GIT-003-sensitive-tracked-file-gitignore-breach.md +40 -40
- package/skills/torusguard/payload/rules/rag/TG-RAG-001-untrusted-rag-context-injection.md +72 -72
- package/skills/torusguard/payload/rules/rag/TG-RAG-002-autonomous-llm-tool-unsandboxed-call.md +51 -51
- package/skills/torusguard/payload/rules/rag/TG-RAG-003-unpartitioned-vector-tenant-lookup.md +51 -51
- package/skills/torusguard/payload/rules/redos/TG-REDOS-001-catastrophic-exponential-backtracking.md +46 -46
- package/skills/torusguard/payload/rules/redos/TG-REDOS-002-unbounded-nested-quantifier.md +43 -43
- package/skills/torusguard/payload/scripts/audit_runner.py +108 -10
- package/skills/torusguard/payload/scripts/deliberation_tournament.py +127 -0
- package/skills/torusguard/payload/scripts/finding_scorer.py +43 -13
- package/skills/torusguard/payload/scripts/reachability_analyzer.py +164 -0
- package/skills/torusguard/payload/scripts/stride_generator.py +196 -0
- package/skills/torusguard/payload/skills/torusguard/SKILL.md +6 -2
- package/skills/torusguard/payload/skills/torusguard/bootstrap.py +3 -3
- package/skills/torusguard/payload/skills/torusguard-ai-guard/SKILL.md +95 -95
- package/skills/torusguard/payload/skills/torusguard-audit/SKILL.md +109 -84
- package/skills/torusguard/payload/skills/torusguard-container/SKILL.md +94 -94
- package/skills/torusguard/payload/skills/torusguard-git-mine/SKILL.md +92 -92
- package/skills/torusguard/payload/skills/torusguard-ocr-scan/SKILL.md +94 -94
- package/skills/torusguard/payload/skills/torusguard-redos/SKILL.md +91 -91
- package/skills/torusguard/payload/skills/torusguard-review/SKILL.md +27 -0
- package/skills/torusguard/payload/skills/torusguard-threatmodel/SKILL.md +27 -0
- package/skills/torusguard/payload/workflows/ai-guard.md +31 -31
- package/skills/torusguard/payload/workflows/audit.md +21 -17
- package/skills/torusguard/payload/workflows/container.md +29 -29
- package/skills/torusguard/payload/workflows/git-mine.md +25 -25
- package/skills/torusguard/payload/workflows/ocr-scan.md +25 -25
- package/skills/torusguard/payload/workflows/redos.md +27 -27
- package/skills/torusguard/payload/workflows/review.md +11 -0
- package/skills/torusguard/payload/workflows/threatmodel.md +9 -0
- package/skills/torusguard/payload/workflows/torusguard-audit.md +35 -55
- package/skills/torusguard/references/csharp-security.md +41 -41
- package/skills/torusguard/references/go-security.md +41 -41
- package/skills/torusguard/references/java-security.md +40 -40
- package/skills/torusguard/references/polyglot-security-matrix.md +25 -25
- package/skills/torusguard/references/rust-security.md +40 -40
- package/skills/torusguard-audit/SKILL.md +107 -83
- package/skills/torusguard-review/SKILL.md +27 -0
- package/skills/torusguard-threatmodel/SKILL.md +27 -0
|
@@ -10,6 +10,46 @@
|
|
|
10
10
|
"config/scope.json": "b198a86186b4c6d5e1af516bf4e3a6afa8878e622ca1d57a5bf72d294f8c6f25",
|
|
11
11
|
"config/slash-commands.json": "305c1dc5b556e8d64ad9dd585dafac1a9955cf1bd5321429955b19b7a62736b6",
|
|
12
12
|
"config/torusguard.json": "55dbde335997421a01c97709fd1672ad70fa921bfe8346dd57552b799db2419e",
|
|
13
|
+
"core/__init__.py": "2120562452ae03c84468d67246dc93376f7ebcde8e4ca767c6253bc92c35dbbf",
|
|
14
|
+
"core/agent_roles.py": "d7189dbf1d3ae4e330eb316bed5d399a18992295addf466f4c6552bc14ae6a34",
|
|
15
|
+
"core/ast_walker.py": "309564d168e6eb9e3e93aceb29a95a61872b35a4da7235ee49e79e9d3a5e7cc6",
|
|
16
|
+
"core/authorization.py": "2bb7f85b4639959276fc7cfd427df7edb8b1f97f8003707a0032f100953d1b30",
|
|
17
|
+
"core/browser_verifier.py": "e450bdbb8d5c2808a3b3ea7bc33bce2451230cbbb7ed4f17dbc7107ab0f30d56",
|
|
18
|
+
"core/bundle.py": "82505fba44a5ad867a4caef34e1233ebf76d4bc2e15b943e2413822602f1a95f",
|
|
19
|
+
"core/call_graph.py": "7e230f8b5fa7dd8f780eafbe7381f2d9538f01a880c1349c41139cce20f9094f",
|
|
20
|
+
"core/clustering.py": "0ffcad5e8a459084d200248de8799d466c2b53ad627b778314b09f2733df782c",
|
|
21
|
+
"core/confidence.py": "81c6242a1a3eaea873d39e8b212e5781a2df2316614f18a2fe6ef757561f5bb5",
|
|
22
|
+
"core/cross_file_taint.py": "1fa323529e5ca2fcce06167e4a59431f9f8217ad7a5097f8afbc6b9a9dc0913d",
|
|
23
|
+
"core/exploit_checker.py": "74a48e6e1e1b9791107b487ab5434540494946441605cf9115fa90b787bc5c5a",
|
|
24
|
+
"core/formatter.py": "a9d2a20e52caaf8a801f65f325b3f5bc430eb6301506973095961d4615b7e429",
|
|
25
|
+
"core/governance.py": "657edfa332c2f855f917545862c9d38f31468cec464d11dd2c012dcf794fb32c",
|
|
26
|
+
"core/identity.py": "f42d3d81c7ee8ca5d2ef08d48066abdc42d2ccbd5fe0bbd88b35d5c8174b696f",
|
|
27
|
+
"core/import_resolver.py": "4ac89ac405816b7de599fbabfa47556d10c1557d92f3a700bf50b90f52ba6c75",
|
|
28
|
+
"core/incremental.py": "8ff9d41f6667bf567d2e952f31ae330271ba1d6cf5411ab4468c355ca2fa6681",
|
|
29
|
+
"core/lifecycle.py": "f4406acba8464ed9111128ef545f8c576639cadda8b9de7e23ff8a90fad24f9e",
|
|
30
|
+
"core/models.py": "ed23b50aab2eb7ea9bc16dbb20b0bf4f978f3aae7f39f0a713f7efe08ff238b5",
|
|
31
|
+
"core/parallel.py": "27fcfdd3760d481ffdd4e7321a79d17ef4823dd3744687fcc9d00349c0bb1d49",
|
|
32
|
+
"core/parser.py": "2f01e9beb178e86002fd8dd3211cf269ab59f21e5c65aabb5e9d0e110504d1d1",
|
|
33
|
+
"core/rechecker.py": "2a21b788158cac79db9030db79e3a27021e7f66692c37c39e0bd3fadf483388c",
|
|
34
|
+
"core/replay_trace.py": "8132cb43dd4593cc96f09f014c2b3882ef5296ebc5029a921423263b07ca7a1d",
|
|
35
|
+
"core/rules_registry.py": "80c4f5067f151b596388ae9a4546d2f009f10342daa5221412e5c9a222b27a31",
|
|
36
|
+
"core/run_folder.py": "cc8702dfd3a2768e5dca74f7ac85e316f53f1acb059bad87ca3650eeeae2defa",
|
|
37
|
+
"core/run_manager.py": "2470ebc8b54edaab3679d909fde48f02c7530f1e12c917b7b5cd5c004062a8b6",
|
|
38
|
+
"core/runtime_evidence.py": "79c947a3b131c3be2f2938789d12647a0d9010bb4077bf3f33b2c7218ba9028b",
|
|
39
|
+
"core/runtime_validator.py": "39477ef1138e8deaa5c3859d6402e71d2c0eb6e2e39fbd3db04fe3ad8e2c798c",
|
|
40
|
+
"core/safety_gate.py": "349e84187930faf79baa38643712d48636de504e8613667e42ec852999efa9fb",
|
|
41
|
+
"core/sarif.py": "93316e7d5fa0ac3660ce18307a2ef4f9c2b2b24b0a4e40d288f94edd0ef84e6d",
|
|
42
|
+
"core/stack_profiler.py": "8c5166c712d7e9341d6290b2220da05662f1ba251899d6f501a9875625f5539c",
|
|
43
|
+
"core/symbol_table.py": "8e700e01e920e7c8a496a16e400195bb6cedd9e3624997fbb44b29124e256d74",
|
|
44
|
+
"core/taint.py": "f54b3e2d620d480969681847e63149b259876dbac470dc417e90407e1def925b",
|
|
45
|
+
"core/taint_graph.py": "2f697a4d4c44801f346f7bde0794cc70c481b4a5a28fe02add20fa845fd9a5c5",
|
|
46
|
+
"core/taint_rules.py": "d29893e0212a2afb21fede6c20afb6d3fe9ff89511659675f02a034ea1e87d8f",
|
|
47
|
+
"core/v070_reporter.py": "d9e9bebd4e158f4c1b1b50897c04c2c5f9db85919b1700b47331ecf16fe7bd63",
|
|
48
|
+
"core/v070_workflow.py": "57bf1468c78f47b4aa5fb5804eb3c247825daa0933bb5cf0aad4ae2394adcead",
|
|
49
|
+
"core/v6_reporter.py": "95fa2ec5b0e708101b62131152445039192382e409d0f40c35cdcbf96648ca26",
|
|
50
|
+
"core/v6_workflow.py": "3e38afafc3afdbebe8cf76ed24da00435aab27a2ac512a292983f8b1e88ebcb8",
|
|
51
|
+
"core/watcher.py": "b3d4856023ee2f6c65b2938d3c76c246d7c440c58cdc7b642dc27209d68a959a",
|
|
52
|
+
"custom_rules/README.md": "282d35795e77a9def907155b068ba2949fd459f80de1d0d037b21777c5c9a718",
|
|
13
53
|
"references/csharp-security.md": "d6e267855b08ed4fdff26f3b876f089ae1f90a7ec6546cba7e8173380d9daa9d",
|
|
14
54
|
"references/django-security.md": "26ea5535ac435e61489df1e381ac62b19e81702edfe095e78c937be93fa15ea7",
|
|
15
55
|
"references/drf-security.md": "c6796398317b0f264d89fff598404e126d819e69e1ea0a5129924a5eb2a7af9d",
|
|
@@ -43,6 +83,8 @@
|
|
|
43
83
|
"rules/TG-INPUT-004-unrestricted-file-upload.md": "d665fb7ede456c24d12229cec22b30374a4dc036c3fe3a41ece22f97ab78a1f4",
|
|
44
84
|
"rules/TG-INPUT-005-unsafe-template-rendering-and-escaping.md": "b6006e741a303d8ff2cd65ef417e6199e5dcf8fe7d603941244db82f6cbe1753",
|
|
45
85
|
"rules/TG-INPUT-006-unsafe-file-path-traversal.md": "5edb665cd2c41b659849c96d0d4b801a6365e130be12c51733a3d6f17cfd85ed",
|
|
86
|
+
"rules/TG-INPUT-007-unvalidated-redirect.md": "7da41ecbd39a7c90fe90fc683df48f38b0cf5a0d7c2b027f0827830bd8f814f7",
|
|
87
|
+
"rules/TG-INPUT-008-insecure-deserialization.md": "5f5f85a9429d32959f890f668ff1fd75bd7ce976a7b9406c3b7235fc728989ca",
|
|
46
88
|
"rules/TG-PLATFORM-001-wildcard-cors-with-credentials.md": "fb8154f5b8051e94886c956b1e7bdbc5f316739795b8fb9bb493223ca774fe25",
|
|
47
89
|
"rules/TG-PLATFORM-002-missing-security-headers.md": "207f489453d6256b5d794f79be25c66e9f932ae5cb561b3e8b50d26a28f6a07a",
|
|
48
90
|
"rules/TG-PLATFORM-003-production-stack-trace-exposure.md": "298c75b928c160720243e42ce5bf43397e73cf50ed472482d5ef3f7635fcb839",
|
|
@@ -155,14 +197,16 @@
|
|
|
155
197
|
"schemas/retest.schema.json": "97c0407ca4365a524020c430912f686f698cc0de90043194621071e9fc681cc7",
|
|
156
198
|
"schemas/runtime-evidence.schema.json": "929d2b094c1cd1f7f9db07be1eba5994e8002477eab3fd24140e1e973fd18cc1",
|
|
157
199
|
"scripts/apply_runner.py": "b145a68a4bc10fcacb853f972aee81fa3607e32d282b2b850c5a63d8e72da890",
|
|
158
|
-
"scripts/audit_runner.py": "
|
|
200
|
+
"scripts/audit_runner.py": "18ebcd46f8363169db4ff4675a5258e0b93df5b219650de95b9a5e9f51da5ff9",
|
|
201
|
+
"scripts/deliberation_tournament.py": "52b130eb2031dd411a6f52e82e9b83caf800c4ecbdef29d6b0c848f02b528e3d",
|
|
159
202
|
"scripts/diff_guard.py": "0dc178cdde1ac0ae1a1ea4b2eb2ce1756b2126f6156909cf55d85249f115fcbd",
|
|
160
|
-
"scripts/finding_scorer.py": "
|
|
203
|
+
"scripts/finding_scorer.py": "95c7edfe5ee4742be565914f71bb07bd077b2cf4636b769476345389dd85f3cf",
|
|
161
204
|
"scripts/harden_runner.py": "5d5a40029c088ccb66790a9b0128bdefcd35883ef1dac78088ceb9531392a8f1",
|
|
162
205
|
"scripts/html_reporter.py": "655c57be39e13c177db8842ef471664e5853f3e43b9f2a63e590df40ff9c16cb",
|
|
163
206
|
"scripts/manifest_builder.py": "f1f9a0d63c55cf5ff45e9fd39d1b251c2bce05e777f8c1e325741d340f0128db",
|
|
164
207
|
"scripts/memory_engine.py": "b715d0ca030e95eb06ad6eda99027535df8a7e37d64897c023be6a291cf13dc6",
|
|
165
208
|
"scripts/monorepo_detector.py": "5603674136a5294ebfff89efeca0a546dd4a7deb1d184a2592ff21aff2131f73",
|
|
209
|
+
"scripts/reachability_analyzer.py": "2cf509b5b5e7081f1852fe9a72d7d1d61b29ea5bba55b751b64fed439eb2548f",
|
|
166
210
|
"scripts/recheck_runner.py": "89e93fcc6843493d7e5f0bf97065dbdb40106273a00e07f903250665ca25f6fb",
|
|
167
211
|
"scripts/recipes_runner.py": "090c06ef0de3c640a111c5646837233ceeaca494b161bd5edc630cc1371dca0e",
|
|
168
212
|
"scripts/report_sync.py": "5ebef684690200694a53af30db850d9808d03ec710ed21ef75c4de52b5e5217c",
|
|
@@ -170,10 +214,12 @@
|
|
|
170
214
|
"scripts/run_manager.py": "b738ff70879e46547d32fac6befc61de9599f676411384280fb9819ea3ad7035",
|
|
171
215
|
"scripts/safety_gate.py": "3379b7534b2590cf563717a448983ad8ed7e8f174f0ad65683d33e8a10f51558",
|
|
172
216
|
"scripts/sarif_exporter.py": "86700765212adb3ab590ca72614bf3ad4ce7ce60e3193f7f3bd1a04d34d10f6e",
|
|
217
|
+
"scripts/skill_profiler.py": "ada83e022795febb2365a73753656ff881993d77cf73517e818d668e961adb45",
|
|
173
218
|
"scripts/stack_detect.py": "c05a1ade4c8692025476bf7ea080a8f07c92e5d8e9a04f94c1654386352ffbdc",
|
|
174
219
|
"scripts/status_runner.py": "4c358c91950c7874bcc6a5f23f2d3fda62b0752efcf6c6b658adf02ed77c7752",
|
|
220
|
+
"scripts/stride_generator.py": "c7a4ea2a19a7386dfc6c0fb301e933a32de2c8963ffa605e5aaa651cf880507f",
|
|
175
221
|
"scripts/term_ui.py": "ca69398f85c86fe89526d6334b3ee866c890273997351113c3cc1765b7bd20c3",
|
|
176
|
-
"skills/torusguard/SKILL.md": "
|
|
222
|
+
"skills/torusguard/SKILL.md": "15c69cb10eca1a10344b494888dce57e2baf227c3282bd54424a36ce35fb2460",
|
|
177
223
|
"skills/torusguard/bootstrap.py": "f7ce48cc310dcdbf86c028f05a8f5ad22677f4cebb1bec5c90d173a9044342c5",
|
|
178
224
|
"skills/torusguard/references/auth-and-sessions.md": "c3e4b9600cb53fc28c993922dc880accbec5783ac90d5ee98d63b52762d19525",
|
|
179
225
|
"skills/torusguard/references/business-logic-and-abuse.md": "58e87df2864d468af70c1ff39f5d540c687fa846b671457f85046ab2065fe99c",
|
|
@@ -205,7 +251,7 @@
|
|
|
205
251
|
"skills/torusguard/references/websocket-security.md": "b5315e49432184c006664436d689d426b7322fc6fbbba2899a9ea5e5bab74c92",
|
|
206
252
|
"skills/torusguard-ai-guard/SKILL.md": "130a24d82f1b92fcc3ac2f4edc77d4d999ae629971f2131f66d6fac876f5593f",
|
|
207
253
|
"skills/torusguard-apply/SKILL.md": "edb21eabae4f9ad5be5976b20d217941c87b2a15edfc73383d02460ca3253fca",
|
|
208
|
-
"skills/torusguard-audit/SKILL.md": "
|
|
254
|
+
"skills/torusguard-audit/SKILL.md": "b9ffc74381360656cbc78438c003fb1e67c4f0787f87627555863b474d57a8ad",
|
|
209
255
|
"skills/torusguard-authorize/SKILL.md": "56bcebc718bddadfd66010ebe2d23b4acf429e6230de05dd2300dab6bd383cc2",
|
|
210
256
|
"skills/torusguard-container/SKILL.md": "f9a2dea0b6b1e2de8ce4a189bb32b1010f1b4d6ff7a529450857b6dab20546ff",
|
|
211
257
|
"skills/torusguard-exploit-check/SKILL.md": "c127f1766e98e28dc967e452dff5dfec87689a26cf671ab6e62a135cd4d46e4b",
|
|
@@ -217,7 +263,9 @@
|
|
|
217
263
|
"skills/torusguard-recheck/SKILL.md": "a5c4539ec6d091179c8ba53792fba46f26795976f392d2305e357f25a2966c55",
|
|
218
264
|
"skills/torusguard-redos/SKILL.md": "b09b39bd98589613b2107c177e247f6224fb54ab2f028b4339ae01aac9d28c67",
|
|
219
265
|
"skills/torusguard-report/SKILL.md": "509185ea6730601cf9a44e136219cace61cd0523f8e112de03e4ef1c35e60585",
|
|
266
|
+
"skills/torusguard-review/SKILL.md": "6d9ec907821ddf62bbbeaed8751d1532e72ba42702ea3afdaadaf720f66c35e3",
|
|
220
267
|
"skills/torusguard-status/SKILL.md": "e9741a20313a8304bc7565b194949a59ec7cfd4945b197517680164b3197efc0",
|
|
268
|
+
"skills/torusguard-threatmodel/SKILL.md": "549903f39a030a75d88c184b7373d86bca921d8f802732c3674bfe9537b14537",
|
|
221
269
|
"skills/torusguard-verify/SKILL.md": "aeb4d3c7924253607d130e48491d83bf7b7a21707cd1dac2ba97d64f5e259fd6",
|
|
222
270
|
"skills/torusguard-web-validate/SKILL.md": "f1df00e10abd823d9a8c4daa1a3af7f26c5263c6c8e58e05b61b647d01a25489",
|
|
223
271
|
"templates/audit-report.template.md": "71149dd05b01a74287a47781fdc71fd2d1b4b70337da303bf78767d0410a6c90",
|
|
@@ -226,7 +274,7 @@
|
|
|
226
274
|
"templates/remediation-bundle.template.md": "4d85a540e3a2e74f9b21fc8a2a1072e27ca03e97cd67ca482f529cfe722acc4d",
|
|
227
275
|
"workflows/ai-guard.md": "7d762f4e18f64864b50b64148b972085d2766aeaf13833bc1e6aeb8fddb96999",
|
|
228
276
|
"workflows/apply.md": "0cd0fa84627ff73ffef84aa7eed6d096b57826139c079fa63f1bd745e13b138a",
|
|
229
|
-
"workflows/audit.md": "
|
|
277
|
+
"workflows/audit.md": "9f13b0497553965d30a71ff040a0dc556d526c8bbff136952b8210685632b5d7",
|
|
230
278
|
"workflows/authorize.md": "386779f405c4b7de0282938db4095179ed212fd32296dff158acb3258b41aec1",
|
|
231
279
|
"workflows/container.md": "64936b4873e9dfde6deae8a7d10d572a3bfbbfe9ef2340d0df8a3db5e1d02ad7",
|
|
232
280
|
"workflows/exploit-check.md": "4dc4016b7a22f18d5c32dd6fcfa7a859df07d03300973654aea92fe5251c8a85",
|
|
@@ -238,7 +286,9 @@
|
|
|
238
286
|
"workflows/recheck.md": "f57194675ed465ee5fd6e8fc731e7102becd2dd0a8f8848517c0e11d3de849cf",
|
|
239
287
|
"workflows/redos.md": "f55a4f510849a5ea7e2ae4b08ecc70dff03c1bf21c7fdc664a4ff3ad0396f904",
|
|
240
288
|
"workflows/report.md": "7c718dfef6da1b66ba0fed300b7dfc90438fc3866af5a9b2aae4b3c3acd638e2",
|
|
289
|
+
"workflows/review.md": "ac8edc3c1d64571c7d58769e471fb10855969de72d874acb988c9c3c963f9a45",
|
|
241
290
|
"workflows/status.md": "021a962ae4e6fc81383db2ef42d28dcfc1b3e546c9a10a7a15b9910e531cf0c2",
|
|
291
|
+
"workflows/threatmodel.md": "b509c38754bff5284d768d3e64cea21839ee9abcedb1661e597d291145715cf1",
|
|
242
292
|
"workflows/verify.md": "dd2579fe7d6e31ba47a4094edfbf4ab04be0745da7dc79e104b0547395c715d1",
|
|
243
293
|
"workflows/web-validate.md": "08441b01d15fd16f6697a95244632ea1465193631ecfb0746fe0c58895ff1c2b"
|
|
244
294
|
}
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
"""
|
|
2
|
+
TorusGuard Core Architecture & Security Workflow Engine (v0.7.0)
|
|
3
|
+
|
|
4
|
+
Tiered architectural layers:
|
|
5
|
+
- Tier 1: Canonical Data Models, Lifecycle State Machine & Reporting (v0.5 base)
|
|
6
|
+
- Tier 2: Governed Remediation, Clustering, Patch Policy & SARIF Export (v0.6 engine)
|
|
7
|
+
- Tier 3: Authorized Runtime Validation, Exploitability Confirmation & Multi-Agent Roles (v0.7 engine)
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
# ==============================================================================
|
|
11
|
+
# Tier 1: Canonical Data Models, Lifecycle & Provenance (v0.5 base)
|
|
12
|
+
# ==============================================================================
|
|
13
|
+
from .models import (
|
|
14
|
+
Finding,
|
|
15
|
+
Evidence,
|
|
16
|
+
Remediation,
|
|
17
|
+
FrameworkPattern,
|
|
18
|
+
AffectedComponent,
|
|
19
|
+
ReproductionMethod,
|
|
20
|
+
RetestRecord,
|
|
21
|
+
NotesRecord,
|
|
22
|
+
FindingTimestamps,
|
|
23
|
+
ProvenanceChain,
|
|
24
|
+
ConfidenceScore,
|
|
25
|
+
ConfidenceFactors,
|
|
26
|
+
ConfidenceBand,
|
|
27
|
+
SeverityLevel,
|
|
28
|
+
SeverityInfo,
|
|
29
|
+
RemediationPriority,
|
|
30
|
+
FindingStatus,
|
|
31
|
+
LifecycleStage,
|
|
32
|
+
TaxonomyCategory,
|
|
33
|
+
EvidenceType,
|
|
34
|
+
AuditReport,
|
|
35
|
+
mask_sensitive_data,
|
|
36
|
+
)
|
|
37
|
+
from .lifecycle import FindingLifecycleManager, LifecycleTransitionError
|
|
38
|
+
from .formatter import ReportFormatter
|
|
39
|
+
from .run_folder import RunFolder
|
|
40
|
+
|
|
41
|
+
# ==============================================================================
|
|
42
|
+
# Tier 2: Governed Remediation, Clustering, Patch Policy & SARIF (v0.6 engine)
|
|
43
|
+
# ==============================================================================
|
|
44
|
+
from .identity import IdentityEngine, FindingFingerprint
|
|
45
|
+
from .clustering import ClusteringEngine, RootCauseCluster
|
|
46
|
+
from .bundle import BundleManager, RemediationBundle
|
|
47
|
+
from .governance import PatchGovernor, PatchPolicyDecision, HIGH_RISK_KEYWORDS, SENSITIVE_CATEGORIES
|
|
48
|
+
from .rechecker import TargetedRechecker, TargetedRecheckResult, RecheckOutcome
|
|
49
|
+
from .run_manager import RunManager
|
|
50
|
+
from .sarif import SarifExporter
|
|
51
|
+
from .v6_reporter import V6Reporter
|
|
52
|
+
from .v6_workflow import V6Workflow
|
|
53
|
+
from .stack_profiler import StackProfiler, StackProfile
|
|
54
|
+
|
|
55
|
+
# ==============================================================================
|
|
56
|
+
# Tier 3: Authorized Runtime Validation & Exploitability Confirmation (v0.7 engine)
|
|
57
|
+
# ==============================================================================
|
|
58
|
+
from .authorization import AuthorizationManager, AuthorizationRecord, TargetScope, AuthorizationError
|
|
59
|
+
from .safety_gate import SafetyGate, SafetyDecision, SafetyReviewLevel
|
|
60
|
+
from .runtime_evidence import EvidenceCollector, RuntimeEvidenceItem, RedactionEngine
|
|
61
|
+
from .runtime_validator import WebValidator, SessionState
|
|
62
|
+
from .exploit_checker import ExploitChecker, ExploitCheckResult, ExploitabilityStatus
|
|
63
|
+
from .browser_verifier import BrowserVerifier, BrowserAction
|
|
64
|
+
from .agent_roles import RoleOrchestrator, RoleHandoff, AgentRole
|
|
65
|
+
from .replay_trace import ReplayManager, ReplayTrace, ReplayStep
|
|
66
|
+
from .v070_reporter import V070Reporter
|
|
67
|
+
from .v070_workflow import V070Workflow
|
|
68
|
+
|
|
69
|
+
__version__ = "0.7.0"
|
|
70
|
+
|
|
71
|
+
__all__ = [
|
|
72
|
+
# Tier 1: Canonical Models & Lifecycle
|
|
73
|
+
"Finding",
|
|
74
|
+
"Evidence",
|
|
75
|
+
"Remediation",
|
|
76
|
+
"FrameworkPattern",
|
|
77
|
+
"AffectedComponent",
|
|
78
|
+
"ReproductionMethod",
|
|
79
|
+
"RetestRecord",
|
|
80
|
+
"NotesRecord",
|
|
81
|
+
"FindingTimestamps",
|
|
82
|
+
"ProvenanceChain",
|
|
83
|
+
"ConfidenceScore",
|
|
84
|
+
"ConfidenceFactors",
|
|
85
|
+
"ConfidenceBand",
|
|
86
|
+
"SeverityLevel",
|
|
87
|
+
"SeverityInfo",
|
|
88
|
+
"RemediationPriority",
|
|
89
|
+
"FindingStatus",
|
|
90
|
+
"LifecycleStage",
|
|
91
|
+
"TaxonomyCategory",
|
|
92
|
+
"EvidenceType",
|
|
93
|
+
"AuditReport",
|
|
94
|
+
"mask_sensitive_data",
|
|
95
|
+
"FindingLifecycleManager",
|
|
96
|
+
"LifecycleTransitionError",
|
|
97
|
+
"ReportFormatter",
|
|
98
|
+
"RunFolder",
|
|
99
|
+
# Tier 2: Governed Remediation & v0.6 Engine
|
|
100
|
+
"IdentityEngine",
|
|
101
|
+
"FindingFingerprint",
|
|
102
|
+
"ClusteringEngine",
|
|
103
|
+
"RootCauseCluster",
|
|
104
|
+
"BundleManager",
|
|
105
|
+
"RemediationBundle",
|
|
106
|
+
"PatchGovernor",
|
|
107
|
+
"PatchPolicyDecision",
|
|
108
|
+
"HIGH_RISK_KEYWORDS",
|
|
109
|
+
"SENSITIVE_CATEGORIES",
|
|
110
|
+
"TargetedRechecker",
|
|
111
|
+
"TargetedRecheckResult",
|
|
112
|
+
"RecheckOutcome",
|
|
113
|
+
"RunManager",
|
|
114
|
+
"SarifExporter",
|
|
115
|
+
"V6Reporter",
|
|
116
|
+
"V6Workflow",
|
|
117
|
+
"StackProfiler",
|
|
118
|
+
"StackProfile",
|
|
119
|
+
# Tier 3: Authorized Runtime Validation & v0.7 Engine
|
|
120
|
+
"AuthorizationManager",
|
|
121
|
+
"AuthorizationRecord",
|
|
122
|
+
"TargetScope",
|
|
123
|
+
"AuthorizationError",
|
|
124
|
+
"SafetyGate",
|
|
125
|
+
"SafetyDecision",
|
|
126
|
+
"SafetyReviewLevel",
|
|
127
|
+
"EvidenceCollector",
|
|
128
|
+
"RuntimeEvidenceItem",
|
|
129
|
+
"RedactionEngine",
|
|
130
|
+
"WebValidator",
|
|
131
|
+
"SessionState",
|
|
132
|
+
"ExploitChecker",
|
|
133
|
+
"ExploitCheckResult",
|
|
134
|
+
"ExploitabilityStatus",
|
|
135
|
+
"BrowserVerifier",
|
|
136
|
+
"BrowserAction",
|
|
137
|
+
"RoleOrchestrator",
|
|
138
|
+
"RoleHandoff",
|
|
139
|
+
"AgentRole",
|
|
140
|
+
"ReplayManager",
|
|
141
|
+
"ReplayTrace",
|
|
142
|
+
"ReplayStep",
|
|
143
|
+
"V070Reporter",
|
|
144
|
+
"V070Workflow",
|
|
145
|
+
]
|
|
146
|
+
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
"""
|
|
2
|
+
TorusGuard v0.7.0 Role-Based Multi-Agent Workflow Engine
|
|
3
|
+
Coordinates explicit handoff contracts between Profiler, Validator, Remediator,
|
|
4
|
+
and Reviewer agent roles, ensuring strict authority separation and full auditability.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import json
|
|
8
|
+
from enum import Enum
|
|
9
|
+
from datetime import datetime, timezone
|
|
10
|
+
from pathlib import Path
|
|
11
|
+
from typing import Dict, Any, List, Optional, Tuple
|
|
12
|
+
from dataclasses import dataclass, asdict
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class AgentRole(str, Enum):
|
|
16
|
+
PROFILER = "Profiler"
|
|
17
|
+
VALIDATOR = "Validator"
|
|
18
|
+
REMEDIATOR = "Remediator"
|
|
19
|
+
REVIEWER = "Reviewer"
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
@dataclass
|
|
23
|
+
class RoleHandoff:
|
|
24
|
+
handoff_id: str
|
|
25
|
+
from_role: str
|
|
26
|
+
to_role: str
|
|
27
|
+
timestamp: str
|
|
28
|
+
contract_goal: str
|
|
29
|
+
inputs_passed: Dict[str, Any]
|
|
30
|
+
outputs_produced: Dict[str, Any]
|
|
31
|
+
status: str = "Completed"
|
|
32
|
+
|
|
33
|
+
def to_dict(self) -> Dict[str, Any]:
|
|
34
|
+
return asdict(self)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
class RoleOrchestrator:
|
|
38
|
+
"""
|
|
39
|
+
Coordinates the 4-role multi-agent workflow and records audit logs.
|
|
40
|
+
"""
|
|
41
|
+
|
|
42
|
+
def __init__(self, run_id: str):
|
|
43
|
+
self.run_id = run_id
|
|
44
|
+
self.handoffs: List[RoleHandoff] = []
|
|
45
|
+
|
|
46
|
+
def record_handoff(
|
|
47
|
+
self,
|
|
48
|
+
from_role: AgentRole,
|
|
49
|
+
to_role: AgentRole,
|
|
50
|
+
contract_goal: str,
|
|
51
|
+
inputs: Dict[str, Any],
|
|
52
|
+
outputs: Dict[str, Any]
|
|
53
|
+
) -> RoleHandoff:
|
|
54
|
+
now = datetime.now(timezone.utc).isoformat()
|
|
55
|
+
h_id = f"HDF-{len(self.handoffs) + 1:02d}"
|
|
56
|
+
handoff = RoleHandoff(
|
|
57
|
+
handoff_id=h_id,
|
|
58
|
+
from_role=from_role.value,
|
|
59
|
+
to_role=to_role.value,
|
|
60
|
+
timestamp=now,
|
|
61
|
+
contract_goal=contract_goal,
|
|
62
|
+
inputs_passed=inputs,
|
|
63
|
+
outputs_produced=outputs,
|
|
64
|
+
status="Completed"
|
|
65
|
+
)
|
|
66
|
+
self.handoffs.append(handoff)
|
|
67
|
+
return handoff
|
|
68
|
+
|
|
69
|
+
def write_artifacts(self, run_dir: Path) -> Tuple[Path, Path]:
|
|
70
|
+
run_dir.mkdir(parents=True, exist_ok=True)
|
|
71
|
+
audit_file = run_dir / "role-audit.json"
|
|
72
|
+
handoff_file = run_dir / "agent-handoffs.md"
|
|
73
|
+
|
|
74
|
+
# 1. role-audit.json
|
|
75
|
+
with open(audit_file, "w", encoding="utf-8") as f:
|
|
76
|
+
json.dump([h.to_dict() for h in self.handoffs], f, indent=2)
|
|
77
|
+
|
|
78
|
+
# 2. agent-handoffs.md
|
|
79
|
+
lines = [
|
|
80
|
+
"# TorusGuard v0.7.0 Multi-Agent Role Handoff & Governance Trail",
|
|
81
|
+
f"\n**Run Identifier:** `{self.run_id}`",
|
|
82
|
+
f"**Total Role Handoffs:** `{len(self.handoffs)}`",
|
|
83
|
+
"\n---",
|
|
84
|
+
"\n## 👥 Multi-Agent Responsibility Matrix\n",
|
|
85
|
+
"| Agent Role | Explicit Authority & Purpose | Forbidden Actions |",
|
|
86
|
+
"|---|---|---|",
|
|
87
|
+
"| **🔍 Profiler** | Detects tech stack, framework versions, route ASTs, and storage boundaries. | Cannot execute active probes or generate code patches. |",
|
|
88
|
+
"| **⚡ Validator** | Executes authorized, bounded runtime HTTP/browser probes; gathers evidence. | Cannot apply code changes or override reviewer policies. |",
|
|
89
|
+
"| **🛠️ Remediator** | Formulates minimal bounded remediation bundles enriched with runtime context. | Cannot dispatch runtime network probes or declare final sign-off. |",
|
|
90
|
+
"| **🛡️ Reviewer** | Verifies technical evidence, reviews safety decisions, and issues sign-off. | Does not execute probes or author patches. |",
|
|
91
|
+
"\n---",
|
|
92
|
+
"\n## 🔄 Chronological Handoff Log\n",
|
|
93
|
+
"| Handoff ID | From Role | To Role | Contract Goal | Timestamp | Status |",
|
|
94
|
+
"|---|---|---|---|---|:---:|",
|
|
95
|
+
]
|
|
96
|
+
for h in self.handoffs:
|
|
97
|
+
lines.append(
|
|
98
|
+
f"| `{h.handoff_id}` | **{h.from_role}** | **{h.to_role}** | {h.contract_goal} | `{h.timestamp}` | ✅ {h.status} |"
|
|
99
|
+
)
|
|
100
|
+
|
|
101
|
+
with open(handoff_file, "w", encoding="utf-8") as f:
|
|
102
|
+
f.write("\n".join(lines) + "\n")
|
|
103
|
+
|
|
104
|
+
return audit_file, handoff_file
|
|
@@ -0,0 +1,283 @@
|
|
|
1
|
+
"""
|
|
2
|
+
TorusGuard Polyglot AST Walker
|
|
3
|
+
Extracts structured primitives (FunctionCall, Assignment, ImportStatement, StringLiteral)
|
|
4
|
+
from Tree-sitter AST nodes and fallback parsers across polyglot languages.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from dataclasses import dataclass, field, asdict
|
|
8
|
+
from typing import List, Dict, Any, Optional
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@dataclass
|
|
12
|
+
class FunctionCall:
|
|
13
|
+
name: str
|
|
14
|
+
full_call: str
|
|
15
|
+
arguments: List[str]
|
|
16
|
+
line_number: int
|
|
17
|
+
column: int
|
|
18
|
+
receiver: Optional[str] = None
|
|
19
|
+
|
|
20
|
+
def to_dict(self) -> Dict[str, Any]:
|
|
21
|
+
return asdict(self)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
@dataclass
|
|
25
|
+
class Assignment:
|
|
26
|
+
target: str
|
|
27
|
+
value_expression: str
|
|
28
|
+
line_number: int
|
|
29
|
+
column: int
|
|
30
|
+
|
|
31
|
+
def to_dict(self) -> Dict[str, Any]:
|
|
32
|
+
return asdict(self)
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
@dataclass
|
|
36
|
+
class ImportStatement:
|
|
37
|
+
module: str
|
|
38
|
+
imported_names: List[str]
|
|
39
|
+
alias_map: Dict[str, str] = field(default_factory=dict)
|
|
40
|
+
line_number: int = 0
|
|
41
|
+
is_relative: bool = False
|
|
42
|
+
|
|
43
|
+
def to_dict(self) -> Dict[str, Any]:
|
|
44
|
+
return asdict(self)
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
@dataclass
|
|
48
|
+
class StringLiteral:
|
|
49
|
+
value: str
|
|
50
|
+
line_number: int
|
|
51
|
+
column: int
|
|
52
|
+
|
|
53
|
+
def to_dict(self) -> Dict[str, Any]:
|
|
54
|
+
return asdict(self)
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
class TreeSitterWalker:
|
|
58
|
+
"""
|
|
59
|
+
Traverses Tree-sitter parse trees and extracts normalized language constructs.
|
|
60
|
+
"""
|
|
61
|
+
|
|
62
|
+
@staticmethod
|
|
63
|
+
def extract_function_calls(root_node, source_bytes: bytes) -> List[FunctionCall]:
|
|
64
|
+
calls: List[FunctionCall] = []
|
|
65
|
+
|
|
66
|
+
def visit(node):
|
|
67
|
+
# Python: call -> function, arguments
|
|
68
|
+
# JS/TS: call_expression -> function, arguments
|
|
69
|
+
# Go: call_expression -> function, argument_list
|
|
70
|
+
if node.type in ("call", "call_expression"):
|
|
71
|
+
func_child = node.child_by_field_name("function")
|
|
72
|
+
args_child = node.child_by_field_name("arguments") or node.child_by_field_name("argument_list")
|
|
73
|
+
|
|
74
|
+
func_name = ""
|
|
75
|
+
receiver = None
|
|
76
|
+
if func_child:
|
|
77
|
+
func_text = source_bytes[func_child.start_byte:func_child.end_byte].decode("utf-8", errors="replace")
|
|
78
|
+
func_name = func_text
|
|
79
|
+
if "." in func_text:
|
|
80
|
+
parts = func_text.split(".")
|
|
81
|
+
receiver = ".".join(parts[:-1])
|
|
82
|
+
|
|
83
|
+
args_list: List[str] = []
|
|
84
|
+
if args_child:
|
|
85
|
+
for ch in args_child.children:
|
|
86
|
+
if ch.type not in (",", "(", ")"):
|
|
87
|
+
arg_text = source_bytes[ch.start_byte:ch.end_byte].decode("utf-8", errors="replace").strip()
|
|
88
|
+
if arg_text:
|
|
89
|
+
args_list.append(arg_text)
|
|
90
|
+
|
|
91
|
+
line_num = node.start_point[0] + 1
|
|
92
|
+
col = node.start_point[1]
|
|
93
|
+
call_text = source_bytes[node.start_byte:node.end_byte].decode("utf-8", errors="replace")
|
|
94
|
+
|
|
95
|
+
calls.append(FunctionCall(
|
|
96
|
+
name=func_name,
|
|
97
|
+
full_call=call_text,
|
|
98
|
+
arguments=args_list,
|
|
99
|
+
line_number=line_num,
|
|
100
|
+
column=col,
|
|
101
|
+
receiver=receiver
|
|
102
|
+
))
|
|
103
|
+
|
|
104
|
+
for ch in node.children:
|
|
105
|
+
visit(ch)
|
|
106
|
+
|
|
107
|
+
visit(root_node)
|
|
108
|
+
return calls
|
|
109
|
+
|
|
110
|
+
@staticmethod
|
|
111
|
+
def extract_assignments(root_node, source_bytes: bytes) -> List[Assignment]:
|
|
112
|
+
assignments: List[Assignment] = []
|
|
113
|
+
|
|
114
|
+
def visit(node):
|
|
115
|
+
# Python: assignment -> left, right
|
|
116
|
+
# JS/TS: variable_declarator (name, value), assignment_expression (left, right)
|
|
117
|
+
# Go: short_var_declaration (left, right), assignment_statement (left, right)
|
|
118
|
+
target = ""
|
|
119
|
+
val_expr = ""
|
|
120
|
+
line_num = node.start_point[0] + 1
|
|
121
|
+
col = node.start_point[1]
|
|
122
|
+
|
|
123
|
+
if node.type == "assignment": # Python
|
|
124
|
+
left = node.child_by_field_name("left")
|
|
125
|
+
right = node.child_by_field_name("right")
|
|
126
|
+
if left and right:
|
|
127
|
+
target = source_bytes[left.start_byte:left.end_byte].decode("utf-8", errors="replace").strip()
|
|
128
|
+
val_expr = source_bytes[right.start_byte:right.end_byte].decode("utf-8", errors="replace").strip()
|
|
129
|
+
assignments.append(Assignment(target=target, value_expression=val_expr, line_number=line_num, column=col))
|
|
130
|
+
|
|
131
|
+
elif node.type == "variable_declarator": # JS/TS
|
|
132
|
+
name = node.child_by_field_name("name")
|
|
133
|
+
val = node.child_by_field_name("value")
|
|
134
|
+
if name:
|
|
135
|
+
target = source_bytes[name.start_byte:name.end_byte].decode("utf-8", errors="replace").strip()
|
|
136
|
+
if val:
|
|
137
|
+
val_expr = source_bytes[val.start_byte:val.end_byte].decode("utf-8", errors="replace").strip()
|
|
138
|
+
assignments.append(Assignment(target=target, value_expression=val_expr, line_number=line_num, column=col))
|
|
139
|
+
|
|
140
|
+
elif node.type == "assignment_expression": # JS/TS
|
|
141
|
+
left = node.child_by_field_name("left")
|
|
142
|
+
right = node.child_by_field_name("right")
|
|
143
|
+
if left and right:
|
|
144
|
+
target = source_bytes[left.start_byte:left.end_byte].decode("utf-8", errors="replace").strip()
|
|
145
|
+
val_expr = source_bytes[right.start_byte:right.end_byte].decode("utf-8", errors="replace").strip()
|
|
146
|
+
assignments.append(Assignment(target=target, value_expression=val_expr, line_number=line_num, column=col))
|
|
147
|
+
|
|
148
|
+
elif node.type in ("short_var_declaration", "assignment_statement"): # Go
|
|
149
|
+
left = node.child_by_field_name("left")
|
|
150
|
+
right = node.child_by_field_name("right")
|
|
151
|
+
if left and right:
|
|
152
|
+
target = source_bytes[left.start_byte:left.end_byte].decode("utf-8", errors="replace").strip()
|
|
153
|
+
val_expr = source_bytes[right.start_byte:right.end_byte].decode("utf-8", errors="replace").strip()
|
|
154
|
+
assignments.append(Assignment(target=target, value_expression=val_expr, line_number=line_num, column=col))
|
|
155
|
+
|
|
156
|
+
for ch in node.children:
|
|
157
|
+
visit(ch)
|
|
158
|
+
|
|
159
|
+
visit(root_node)
|
|
160
|
+
return assignments
|
|
161
|
+
|
|
162
|
+
@staticmethod
|
|
163
|
+
def extract_imports(root_node, source_bytes: bytes, language: str) -> List[ImportStatement]:
|
|
164
|
+
imports: List[ImportStatement] = []
|
|
165
|
+
|
|
166
|
+
def visit(node):
|
|
167
|
+
line_num = node.start_point[0] + 1
|
|
168
|
+
|
|
169
|
+
# Python imports
|
|
170
|
+
if node.type == "import_statement":
|
|
171
|
+
raw = source_bytes[node.start_byte:node.end_byte].decode("utf-8", errors="replace").strip()
|
|
172
|
+
# e.g. import os, sys as s
|
|
173
|
+
names = []
|
|
174
|
+
alias_map = {}
|
|
175
|
+
for ch in node.children:
|
|
176
|
+
if ch.type == "dotted_name":
|
|
177
|
+
mod = source_bytes[ch.start_byte:ch.end_byte].decode("utf-8", errors="replace").strip()
|
|
178
|
+
names.append(mod)
|
|
179
|
+
elif ch.type == "aliased_import":
|
|
180
|
+
n = ch.child_by_field_name("name")
|
|
181
|
+
a = ch.child_by_field_name("alias")
|
|
182
|
+
if n and a:
|
|
183
|
+
name_str = source_bytes[n.start_byte:n.end_byte].decode("utf-8", errors="replace").strip()
|
|
184
|
+
alias_str = source_bytes[a.start_byte:a.end_byte].decode("utf-8", errors="replace").strip()
|
|
185
|
+
names.append(name_str)
|
|
186
|
+
alias_map[alias_str] = name_str
|
|
187
|
+
for n in names:
|
|
188
|
+
imports.append(ImportStatement(module=n, imported_names=[n], alias_map=alias_map, line_number=line_num))
|
|
189
|
+
|
|
190
|
+
elif node.type == "import_from_statement":
|
|
191
|
+
# from module import a, b as c
|
|
192
|
+
module_name = ""
|
|
193
|
+
mod_child = node.child_by_field_name("module_name")
|
|
194
|
+
if mod_child:
|
|
195
|
+
module_name = source_bytes[mod_child.start_byte:mod_child.end_byte].decode("utf-8", errors="replace").strip()
|
|
196
|
+
names = []
|
|
197
|
+
alias_map = {}
|
|
198
|
+
for ch in node.children:
|
|
199
|
+
if ch.type == "dotted_name" and ch != mod_child:
|
|
200
|
+
names.append(source_bytes[ch.start_byte:ch.end_byte].decode("utf-8", errors="replace").strip())
|
|
201
|
+
elif ch.type == "aliased_import":
|
|
202
|
+
n = ch.child_by_field_name("name")
|
|
203
|
+
a = ch.child_by_field_name("alias")
|
|
204
|
+
if n and a:
|
|
205
|
+
n_str = source_bytes[n.start_byte:n.end_byte].decode("utf-8", errors="replace").strip()
|
|
206
|
+
a_str = source_bytes[a.start_byte:a.end_byte].decode("utf-8", errors="replace").strip()
|
|
207
|
+
names.append(n_str)
|
|
208
|
+
alias_map[a_str] = n_str
|
|
209
|
+
is_rel = module_name.startswith(".")
|
|
210
|
+
imports.append(ImportStatement(
|
|
211
|
+
module=module_name,
|
|
212
|
+
imported_names=names,
|
|
213
|
+
alias_map=alias_map,
|
|
214
|
+
line_number=line_num,
|
|
215
|
+
is_relative=is_rel
|
|
216
|
+
))
|
|
217
|
+
|
|
218
|
+
# JS/TS imports: import_statement
|
|
219
|
+
elif node.type == "import_statement":
|
|
220
|
+
raw = source_bytes[node.start_byte:node.end_byte].decode("utf-8", errors="replace").strip()
|
|
221
|
+
source_child = node.child_by_field_name("source")
|
|
222
|
+
source_mod = ""
|
|
223
|
+
if source_child:
|
|
224
|
+
source_mod = source_bytes[source_child.start_byte:source_child.end_byte].decode("utf-8", errors="replace").strip().strip("'\"")
|
|
225
|
+
names = []
|
|
226
|
+
alias_map = {}
|
|
227
|
+
for ch in node.children:
|
|
228
|
+
if ch.type == "import_clause":
|
|
229
|
+
clause_str = source_bytes[ch.start_byte:ch.end_byte].decode("utf-8", errors="replace").strip()
|
|
230
|
+
names.append(clause_str)
|
|
231
|
+
is_rel = source_mod.startswith(".")
|
|
232
|
+
imports.append(ImportStatement(
|
|
233
|
+
module=source_mod,
|
|
234
|
+
imported_names=names,
|
|
235
|
+
alias_map=alias_map,
|
|
236
|
+
line_number=line_num,
|
|
237
|
+
is_relative=is_rel
|
|
238
|
+
))
|
|
239
|
+
|
|
240
|
+
# Go imports: import_declaration
|
|
241
|
+
elif node.type == "import_declaration":
|
|
242
|
+
for ch in node.children:
|
|
243
|
+
if ch.type in ("import_spec", "import_spec_list"):
|
|
244
|
+
for spec in (ch.children if ch.type == "import_spec_list" else [ch]):
|
|
245
|
+
if spec.type == "import_spec":
|
|
246
|
+
path_child = spec.child_by_field_name("path")
|
|
247
|
+
if path_child:
|
|
248
|
+
path_str = source_bytes[path_child.start_byte:path_child.end_byte].decode("utf-8", errors="replace").strip().strip('"')
|
|
249
|
+
name_child = spec.child_by_field_name("name")
|
|
250
|
+
alias = ""
|
|
251
|
+
if name_child:
|
|
252
|
+
alias = source_bytes[name_child.start_byte:name_child.end_byte].decode("utf-8", errors="replace").strip()
|
|
253
|
+
alias_map = {alias: path_str} if alias else {}
|
|
254
|
+
imports.append(ImportStatement(
|
|
255
|
+
module=path_str,
|
|
256
|
+
imported_names=[path_str],
|
|
257
|
+
alias_map=alias_map,
|
|
258
|
+
line_number=spec.start_point[0] + 1
|
|
259
|
+
))
|
|
260
|
+
|
|
261
|
+
for ch in node.children:
|
|
262
|
+
visit(ch)
|
|
263
|
+
|
|
264
|
+
visit(root_node)
|
|
265
|
+
return imports
|
|
266
|
+
|
|
267
|
+
@staticmethod
|
|
268
|
+
def extract_string_literals(root_node, source_bytes: bytes) -> List[StringLiteral]:
|
|
269
|
+
literals: List[StringLiteral] = []
|
|
270
|
+
|
|
271
|
+
def visit(node):
|
|
272
|
+
if node.type in ("string", "string_literal", "raw_string_literal", "template_string"):
|
|
273
|
+
text = source_bytes[node.start_byte:node.end_byte].decode("utf-8", errors="replace")
|
|
274
|
+
literals.append(StringLiteral(
|
|
275
|
+
value=text.strip("\"'`"),
|
|
276
|
+
line_number=node.start_point[0] + 1,
|
|
277
|
+
column=node.start_point[1]
|
|
278
|
+
))
|
|
279
|
+
for ch in node.children:
|
|
280
|
+
visit(ch)
|
|
281
|
+
|
|
282
|
+
visit(root_node)
|
|
283
|
+
return literals
|