torusguard 2.1.0 → 2.1.1
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 +47 -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/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__/rules_sync.cpython-314.pyc +0 -0
- package/.torusguard/scripts/audit_runner.py +108 -10
- package/.torusguard/scripts/finding_scorer.py +43 -13
- package/.torusguard/scripts/skill_profiler.py +26 -0
- package/.torusguard/skills/torusguard/SKILL.md +6 -2
- package/.torusguard/skills/torusguard-audit/SKILL.md +109 -84
- package/.torusguard/workflows/audit.md +21 -17
- package/README.md +19 -11
- package/package.json +7 -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 +48 -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/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/finding_scorer.py +43 -13
- 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/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/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
|
@@ -10,6 +10,45 @@
|
|
|
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",
|
|
13
52
|
"references/csharp-security.md": "d6e267855b08ed4fdff26f3b876f089ae1f90a7ec6546cba7e8173380d9daa9d",
|
|
14
53
|
"references/django-security.md": "26ea5535ac435e61489df1e381ac62b19e81702edfe095e78c937be93fa15ea7",
|
|
15
54
|
"references/drf-security.md": "c6796398317b0f264d89fff598404e126d819e69e1ea0a5129924a5eb2a7af9d",
|
|
@@ -43,6 +82,8 @@
|
|
|
43
82
|
"rules/TG-INPUT-004-unrestricted-file-upload.md": "d665fb7ede456c24d12229cec22b30374a4dc036c3fe3a41ece22f97ab78a1f4",
|
|
44
83
|
"rules/TG-INPUT-005-unsafe-template-rendering-and-escaping.md": "b6006e741a303d8ff2cd65ef417e6199e5dcf8fe7d603941244db82f6cbe1753",
|
|
45
84
|
"rules/TG-INPUT-006-unsafe-file-path-traversal.md": "5edb665cd2c41b659849c96d0d4b801a6365e130be12c51733a3d6f17cfd85ed",
|
|
85
|
+
"rules/TG-INPUT-007-unvalidated-redirect.md": "7da41ecbd39a7c90fe90fc683df48f38b0cf5a0d7c2b027f0827830bd8f814f7",
|
|
86
|
+
"rules/TG-INPUT-008-insecure-deserialization.md": "5f5f85a9429d32959f890f668ff1fd75bd7ce976a7b9406c3b7235fc728989ca",
|
|
46
87
|
"rules/TG-PLATFORM-001-wildcard-cors-with-credentials.md": "fb8154f5b8051e94886c956b1e7bdbc5f316739795b8fb9bb493223ca774fe25",
|
|
47
88
|
"rules/TG-PLATFORM-002-missing-security-headers.md": "207f489453d6256b5d794f79be25c66e9f932ae5cb561b3e8b50d26a28f6a07a",
|
|
48
89
|
"rules/TG-PLATFORM-003-production-stack-trace-exposure.md": "298c75b928c160720243e42ce5bf43397e73cf50ed472482d5ef3f7635fcb839",
|
|
@@ -155,9 +196,9 @@
|
|
|
155
196
|
"schemas/retest.schema.json": "97c0407ca4365a524020c430912f686f698cc0de90043194621071e9fc681cc7",
|
|
156
197
|
"schemas/runtime-evidence.schema.json": "929d2b094c1cd1f7f9db07be1eba5994e8002477eab3fd24140e1e973fd18cc1",
|
|
157
198
|
"scripts/apply_runner.py": "b145a68a4bc10fcacb853f972aee81fa3607e32d282b2b850c5a63d8e72da890",
|
|
158
|
-
"scripts/audit_runner.py": "
|
|
199
|
+
"scripts/audit_runner.py": "18ebcd46f8363169db4ff4675a5258e0b93df5b219650de95b9a5e9f51da5ff9",
|
|
159
200
|
"scripts/diff_guard.py": "0dc178cdde1ac0ae1a1ea4b2eb2ce1756b2126f6156909cf55d85249f115fcbd",
|
|
160
|
-
"scripts/finding_scorer.py": "
|
|
201
|
+
"scripts/finding_scorer.py": "95c7edfe5ee4742be565914f71bb07bd077b2cf4636b769476345389dd85f3cf",
|
|
161
202
|
"scripts/harden_runner.py": "5d5a40029c088ccb66790a9b0128bdefcd35883ef1dac78088ceb9531392a8f1",
|
|
162
203
|
"scripts/html_reporter.py": "655c57be39e13c177db8842ef471664e5853f3e43b9f2a63e590df40ff9c16cb",
|
|
163
204
|
"scripts/manifest_builder.py": "f1f9a0d63c55cf5ff45e9fd39d1b251c2bce05e777f8c1e325741d340f0128db",
|
|
@@ -170,10 +211,11 @@
|
|
|
170
211
|
"scripts/run_manager.py": "b738ff70879e46547d32fac6befc61de9599f676411384280fb9819ea3ad7035",
|
|
171
212
|
"scripts/safety_gate.py": "3379b7534b2590cf563717a448983ad8ed7e8f174f0ad65683d33e8a10f51558",
|
|
172
213
|
"scripts/sarif_exporter.py": "86700765212adb3ab590ca72614bf3ad4ce7ce60e3193f7f3bd1a04d34d10f6e",
|
|
214
|
+
"scripts/skill_profiler.py": "ada83e022795febb2365a73753656ff881993d77cf73517e818d668e961adb45",
|
|
173
215
|
"scripts/stack_detect.py": "c05a1ade4c8692025476bf7ea080a8f07c92e5d8e9a04f94c1654386352ffbdc",
|
|
174
216
|
"scripts/status_runner.py": "4c358c91950c7874bcc6a5f23f2d3fda62b0752efcf6c6b658adf02ed77c7752",
|
|
175
217
|
"scripts/term_ui.py": "ca69398f85c86fe89526d6334b3ee866c890273997351113c3cc1765b7bd20c3",
|
|
176
|
-
"skills/torusguard/SKILL.md": "
|
|
218
|
+
"skills/torusguard/SKILL.md": "15c69cb10eca1a10344b494888dce57e2baf227c3282bd54424a36ce35fb2460",
|
|
177
219
|
"skills/torusguard/bootstrap.py": "f7ce48cc310dcdbf86c028f05a8f5ad22677f4cebb1bec5c90d173a9044342c5",
|
|
178
220
|
"skills/torusguard/references/auth-and-sessions.md": "c3e4b9600cb53fc28c993922dc880accbec5783ac90d5ee98d63b52762d19525",
|
|
179
221
|
"skills/torusguard/references/business-logic-and-abuse.md": "58e87df2864d468af70c1ff39f5d540c687fa846b671457f85046ab2065fe99c",
|
|
@@ -205,7 +247,7 @@
|
|
|
205
247
|
"skills/torusguard/references/websocket-security.md": "b5315e49432184c006664436d689d426b7322fc6fbbba2899a9ea5e5bab74c92",
|
|
206
248
|
"skills/torusguard-ai-guard/SKILL.md": "130a24d82f1b92fcc3ac2f4edc77d4d999ae629971f2131f66d6fac876f5593f",
|
|
207
249
|
"skills/torusguard-apply/SKILL.md": "edb21eabae4f9ad5be5976b20d217941c87b2a15edfc73383d02460ca3253fca",
|
|
208
|
-
"skills/torusguard-audit/SKILL.md": "
|
|
250
|
+
"skills/torusguard-audit/SKILL.md": "b9ffc74381360656cbc78438c003fb1e67c4f0787f87627555863b474d57a8ad",
|
|
209
251
|
"skills/torusguard-authorize/SKILL.md": "56bcebc718bddadfd66010ebe2d23b4acf429e6230de05dd2300dab6bd383cc2",
|
|
210
252
|
"skills/torusguard-container/SKILL.md": "f9a2dea0b6b1e2de8ce4a189bb32b1010f1b4d6ff7a529450857b6dab20546ff",
|
|
211
253
|
"skills/torusguard-exploit-check/SKILL.md": "c127f1766e98e28dc967e452dff5dfec87689a26cf671ab6e62a135cd4d46e4b",
|
|
@@ -226,7 +268,7 @@
|
|
|
226
268
|
"templates/remediation-bundle.template.md": "4d85a540e3a2e74f9b21fc8a2a1072e27ca03e97cd67ca482f529cfe722acc4d",
|
|
227
269
|
"workflows/ai-guard.md": "7d762f4e18f64864b50b64148b972085d2766aeaf13833bc1e6aeb8fddb96999",
|
|
228
270
|
"workflows/apply.md": "0cd0fa84627ff73ffef84aa7eed6d096b57826139c079fa63f1bd745e13b138a",
|
|
229
|
-
"workflows/audit.md": "
|
|
271
|
+
"workflows/audit.md": "9f13b0497553965d30a71ff040a0dc556d526c8bbff136952b8210685632b5d7",
|
|
230
272
|
"workflows/authorize.md": "386779f405c4b7de0282938db4095179ed212fd32296dff158acb3258b41aec1",
|
|
231
273
|
"workflows/container.md": "64936b4873e9dfde6deae8a7d10d572a3bfbbfe9ef2340d0df8a3db5e1d02ad7",
|
|
232
274
|
"workflows/exploit-check.md": "4dc4016b7a22f18d5c32dd6fcfa7a859df07d03300973654aea92fe5251c8a85",
|
|
@@ -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
|