torusguard 1.3.5 → 1.4.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 +37 -36
- package/.torusguard/runs/report-latest.html +5862 -315
- package/.torusguard/runs/results-latest.sarif +20 -0
- package/.torusguard/runs/run-20260918-104221-audit/findings.json +1 -0
- package/.torusguard/runs/run-20260918-104221-audit/findings.md +8 -0
- package/.torusguard/runs/run-20260918-104221-audit/manifest.json +12 -0
- package/.torusguard/runs/run-20260918-104221-audit/summary.md +5 -0
- package/.torusguard/runs/run-20260918-104236-audit/findings.json +2314 -0
- package/.torusguard/runs/run-20260918-104236-audit/findings.md +960 -0
- package/.torusguard/runs/run-20260918-104236-audit/manifest.json +12 -0
- package/.torusguard/runs/run-20260918-104236-audit/summary.md +5 -0
- package/.torusguard/runs/run-20260918-105723-audit/findings.json +2382 -0
- package/.torusguard/runs/run-20260918-105723-audit/findings.md +960 -0
- package/.torusguard/runs/run-20260918-105723-audit/manifest.json +12 -0
- package/.torusguard/runs/run-20260918-105723-audit/summary.md +5 -0
- package/.torusguard/runs/run-20260918-105731-audit/findings.json +1 -0
- package/.torusguard/runs/run-20260918-105731-audit/findings.md +8 -0
- package/.torusguard/runs/run-20260918-105731-audit/manifest.json +12 -0
- package/.torusguard/runs/run-20260918-105731-audit/summary.md +5 -0
- package/.torusguard/runs/run-20260918-105940-audit/findings.json +1 -0
- package/.torusguard/runs/run-20260918-105940-audit/findings.md +8 -0
- package/.torusguard/runs/run-20260918-105940-audit/manifest.json +13 -0
- package/.torusguard/runs/run-20260918-105940-audit/remediation.md +7 -0
- package/.torusguard/runs/run-20260918-105940-audit/summary.md +5 -0
- package/.torusguard/runs/run-20260919-145701-audit/findings.json +1 -0
- package/.torusguard/runs/run-20260919-145701-audit/findings.md +8 -0
- package/.torusguard/runs/run-20260919-145701-audit/manifest.json +12 -0
- package/.torusguard/runs/run-20260919-145701-audit/summary.md +5 -0
- package/.torusguard/runs/run-20260919-151729-audit/findings.json +1 -0
- package/.torusguard/runs/run-20260919-151729-audit/findings.md +8 -0
- package/.torusguard/runs/run-20260919-151729-audit/manifest.json +13 -0
- package/.torusguard/runs/run-20260919-151729-audit/remediation.md +7 -0
- package/.torusguard/runs/run-20260919-151729-audit/summary.md +5 -0
- package/.torusguard/runs/run-20260919-152340-audit/findings.json +1 -0
- package/.torusguard/runs/run-20260919-152340-audit/findings.md +8 -0
- package/.torusguard/runs/run-20260919-152340-audit/manifest.json +12 -0
- package/.torusguard/runs/run-20260919-152340-audit/summary.md +5 -0
- package/.torusguard/runs/run-20260919-152345-audit/findings.json +1 -0
- package/.torusguard/runs/run-20260919-152345-audit/findings.md +8 -0
- package/.torusguard/runs/run-20260919-152345-audit/manifest.json +12 -0
- package/.torusguard/runs/run-20260919-152345-audit/summary.md +5 -0
- package/.torusguard/runs/run-20260919-153500-audit/findings.json +1 -0
- package/.torusguard/runs/run-20260919-153500-audit/findings.md +8 -0
- package/.torusguard/runs/run-20260919-153500-audit/manifest.json +12 -0
- package/.torusguard/runs/run-20260919-153500-audit/summary.md +5 -0
- package/.torusguard/scripts/__pycache__/apply_runner.cpython-314.pyc +0 -0
- package/.torusguard/scripts/__pycache__/audit_runner.cpython-314.pyc +0 -0
- package/.torusguard/scripts/__pycache__/diff_guard.cpython-314.pyc +0 -0
- package/.torusguard/scripts/__pycache__/finding_scorer.cpython-314.pyc +0 -0
- package/.torusguard/scripts/__pycache__/harden_runner.cpython-314.pyc +0 -0
- package/.torusguard/scripts/__pycache__/html_reporter.cpython-314.pyc +0 -0
- package/.torusguard/scripts/__pycache__/manifest_builder.cpython-314.pyc +0 -0
- package/.torusguard/scripts/__pycache__/memory_engine.cpython-314.pyc +0 -0
- package/.torusguard/scripts/__pycache__/monorepo_detector.cpython-314.pyc +0 -0
- package/.torusguard/scripts/__pycache__/recheck_runner.cpython-314.pyc +0 -0
- package/.torusguard/scripts/__pycache__/recipes_runner.cpython-314.pyc +0 -0
- package/.torusguard/scripts/__pycache__/report_sync.cpython-314.pyc +0 -0
- package/.torusguard/scripts/__pycache__/run_manager.cpython-314.pyc +0 -0
- package/.torusguard/scripts/__pycache__/sarif_exporter.cpython-314.pyc +0 -0
- package/.torusguard/scripts/__pycache__/stack_detect.cpython-314.pyc +0 -0
- package/.torusguard/scripts/__pycache__/term_ui.cpython-314.pyc +0 -0
- package/.torusguard/scripts/apply_runner.py +108 -9
- package/.torusguard/scripts/audit_runner.py +336 -24
- package/.torusguard/scripts/harden_runner.py +124 -70
- package/.torusguard/scripts/html_reporter.py +3585 -648
- package/.torusguard/scripts/manifest_builder.py +2 -0
- package/.torusguard/scripts/recheck_runner.py +5 -4
- package/.torusguard/scripts/recipes_runner.py +91 -8
- package/.torusguard/scripts/report_sync.py +496 -73
- package/.torusguard/scripts/sarif_exporter.py +48 -8
- package/.torusguard/scripts/stack_detect.py +44 -2
- package/.torusguard/scripts/status_runner.py +267 -0
- package/.torusguard/scripts/term_ui.py +1 -1
- package/.torusguard/skills/torusguard/SKILL.md +75 -72
- package/.torusguard/skills/torusguard-apply/SKILL.md +84 -80
- package/.torusguard/skills/torusguard-audit/SKILL.md +87 -83
- package/.torusguard/skills/torusguard-authorize/SKILL.md +7 -2
- package/.torusguard/skills/torusguard-exploit-check/SKILL.md +7 -2
- package/.torusguard/skills/torusguard-full/SKILL.md +7 -2
- package/.torusguard/skills/torusguard-harden/SKILL.md +98 -94
- package/.torusguard/skills/torusguard-init/SKILL.md +68 -64
- package/.torusguard/skills/torusguard-recheck/SKILL.md +81 -77
- package/.torusguard/skills/torusguard-report/SKILL.md +93 -72
- package/.torusguard/skills/torusguard-status/SKILL.md +62 -58
- package/.torusguard/skills/torusguard-verify/SKILL.md +7 -2
- package/.torusguard/skills/torusguard-web-validate/SKILL.md +7 -2
- package/.torusguard/workflows/apply.md +1 -1
- package/.torusguard/workflows/audit.md +1 -1
- package/.torusguard/workflows/authorize.md +1 -1
- package/.torusguard/workflows/exploit-check.md +1 -1
- package/.torusguard/workflows/harden.md +1 -1
- package/.torusguard/workflows/init.md +1 -1
- package/.torusguard/workflows/memory.md +1 -1
- package/.torusguard/workflows/recheck.md +1 -1
- package/.torusguard/workflows/report.md +1 -1
- package/.torusguard/workflows/status.md +1 -1
- package/.torusguard/workflows/verify.md +1 -1
- package/.torusguard/workflows/web-validate.md +1 -1
- package/README.md +115 -81
- package/bin/torusguard.js +244 -38
- package/package.json +6 -2
- package/skills/torusguard/SKILL.md +1 -1
- package/skills/torusguard/__pycache__/bootstrap.cpython-314.pyc +0 -0
- package/skills/torusguard/bootstrap.py +52 -8
- package/skills/torusguard/payload/.manifest.json +51 -36
- package/skills/torusguard/payload/scripts/__pycache__/apply_runner.cpython-314.pyc +0 -0
- package/skills/torusguard/payload/scripts/__pycache__/audit_runner.cpython-311.pyc +0 -0
- package/skills/torusguard/payload/scripts/__pycache__/audit_runner.cpython-314.pyc +0 -0
- package/skills/torusguard/payload/scripts/__pycache__/diff_guard.cpython-311.pyc +0 -0
- package/skills/torusguard/payload/scripts/__pycache__/diff_guard.cpython-314.pyc +0 -0
- package/skills/torusguard/payload/scripts/__pycache__/finding_scorer.cpython-311.pyc +0 -0
- package/skills/torusguard/payload/scripts/__pycache__/finding_scorer.cpython-314.pyc +0 -0
- package/skills/torusguard/payload/scripts/__pycache__/harden_runner.cpython-314.pyc +0 -0
- package/skills/torusguard/payload/scripts/__pycache__/html_reporter.cpython-311.pyc +0 -0
- package/skills/torusguard/payload/scripts/__pycache__/html_reporter.cpython-314.pyc +0 -0
- package/skills/torusguard/payload/scripts/__pycache__/manifest_builder.cpython-314.pyc +0 -0
- package/skills/torusguard/payload/scripts/__pycache__/memory_engine.cpython-311.pyc +0 -0
- package/skills/torusguard/payload/scripts/__pycache__/memory_engine.cpython-314.pyc +0 -0
- package/skills/torusguard/payload/scripts/__pycache__/monorepo_detector.cpython-311.pyc +0 -0
- package/skills/torusguard/payload/scripts/__pycache__/monorepo_detector.cpython-314.pyc +0 -0
- package/skills/torusguard/payload/scripts/__pycache__/recheck_runner.cpython-314.pyc +0 -0
- package/skills/torusguard/payload/scripts/__pycache__/report_sync.cpython-311.pyc +0 -0
- package/skills/torusguard/payload/scripts/__pycache__/report_sync.cpython-314.pyc +0 -0
- package/skills/torusguard/payload/scripts/__pycache__/rules_sync.cpython-311.pyc +0 -0
- package/skills/torusguard/payload/scripts/__pycache__/run_manager.cpython-311.pyc +0 -0
- package/skills/torusguard/payload/scripts/__pycache__/run_manager.cpython-314.pyc +0 -0
- package/skills/torusguard/payload/scripts/__pycache__/sarif_exporter.cpython-314.pyc +0 -0
- package/skills/torusguard/payload/scripts/__pycache__/stack_detect.cpython-311.pyc +0 -0
- package/skills/torusguard/payload/scripts/__pycache__/stack_detect.cpython-314.pyc +0 -0
- package/skills/torusguard/payload/scripts/__pycache__/term_ui.cpython-311.pyc +0 -0
- package/skills/torusguard/payload/scripts/__pycache__/term_ui.cpython-314.pyc +0 -0
- package/skills/torusguard/payload/scripts/apply_runner.py +108 -9
- package/skills/torusguard/payload/scripts/audit_runner.py +336 -24
- package/skills/torusguard/payload/scripts/harden_runner.py +124 -70
- package/skills/torusguard/payload/scripts/html_reporter.py +3585 -648
- package/skills/torusguard/payload/scripts/manifest_builder.py +2 -0
- package/skills/torusguard/payload/scripts/recheck_runner.py +5 -4
- package/skills/torusguard/payload/scripts/recipes_runner.py +91 -8
- package/skills/torusguard/payload/scripts/report_sync.py +496 -73
- package/skills/torusguard/payload/scripts/sarif_exporter.py +48 -8
- package/skills/torusguard/payload/scripts/stack_detect.py +44 -2
- package/skills/torusguard/payload/scripts/status_runner.py +267 -0
- package/skills/torusguard/payload/scripts/term_ui.py +1 -1
- package/skills/torusguard/payload/skills/torusguard/SKILL.md +1 -1
- package/skills/torusguard/payload/skills/torusguard-apply/SKILL.md +1 -1
- package/skills/torusguard/payload/skills/torusguard-audit/SKILL.md +1 -1
- package/skills/torusguard/payload/skills/torusguard-authorize/SKILL.md +1 -1
- package/skills/torusguard/payload/skills/torusguard-exploit-check/SKILL.md +1 -1
- package/skills/torusguard/payload/skills/torusguard-full/SKILL.md +1 -1
- package/skills/torusguard/payload/skills/torusguard-harden/SKILL.md +1 -1
- package/skills/torusguard/payload/skills/torusguard-init/SKILL.md +1 -1
- package/skills/torusguard/payload/skills/torusguard-recheck/SKILL.md +1 -1
- package/skills/torusguard/payload/skills/torusguard-report/SKILL.md +40 -23
- package/skills/torusguard/payload/skills/torusguard-status/SKILL.md +1 -1
- package/skills/torusguard/payload/skills/torusguard-verify/SKILL.md +1 -1
- package/skills/torusguard/payload/skills/torusguard-web-validate/SKILL.md +1 -1
- package/skills/torusguard/payload/workflows/apply.md +9 -1
- package/skills/torusguard/payload/workflows/audit.md +8 -2
- package/skills/torusguard/payload/workflows/authorize.md +1 -1
- package/skills/torusguard/payload/workflows/exploit-check.md +1 -1
- package/skills/torusguard/payload/workflows/harden.md +6 -1
- package/skills/torusguard/payload/workflows/init.md +7 -1
- package/skills/torusguard/payload/workflows/memory.md +1 -1
- package/skills/torusguard/payload/workflows/recheck.md +1 -1
- package/skills/torusguard/payload/workflows/recipes.md +55 -0
- package/skills/torusguard/payload/workflows/report.md +59 -55
- package/skills/torusguard/payload/workflows/status.md +4 -1
- package/skills/torusguard/payload/workflows/torusguard-apply.md +110 -0
- package/skills/torusguard/payload/workflows/torusguard-audit.md +105 -0
- package/skills/torusguard/payload/workflows/torusguard-authorize.md +96 -0
- package/skills/torusguard/payload/workflows/torusguard-exploit-check.md +98 -0
- package/skills/torusguard/payload/workflows/torusguard-harden.md +104 -0
- package/skills/torusguard/payload/workflows/torusguard-init.md +106 -0
- package/skills/torusguard/payload/workflows/torusguard-recheck.md +101 -0
- package/skills/torusguard/payload/workflows/torusguard-recipes.md +55 -0
- package/skills/torusguard/payload/workflows/torusguard-report.md +105 -0
- package/skills/torusguard/payload/workflows/torusguard-status.md +103 -0
- package/skills/torusguard/payload/workflows/torusguard-verify.md +100 -0
- package/skills/torusguard/payload/workflows/torusguard-web-validate.md +96 -0
- package/skills/torusguard/payload/workflows/torusguard.md +19 -0
- package/skills/torusguard/payload/workflows/verify.md +1 -1
- package/skills/torusguard/payload/workflows/web-validate.md +1 -1
- package/skills/torusguard-apply/SKILL.md +1 -1
- package/skills/torusguard-audit/SKILL.md +1 -1
- package/skills/torusguard-authorize/SKILL.md +1 -1
- package/skills/torusguard-exploit-check/SKILL.md +1 -1
- package/skills/torusguard-full/SKILL.md +1 -1
- package/skills/torusguard-harden/SKILL.md +1 -1
- package/skills/torusguard-init/SKILL.md +1 -1
- package/skills/torusguard-recheck/SKILL.md +1 -1
- package/skills/torusguard-report/SKILL.md +40 -23
- package/skills/torusguard-status/SKILL.md +1 -1
- package/skills/torusguard-verify/SKILL.md +1 -1
- package/skills/torusguard-web-validate/SKILL.md +1 -1
|
@@ -0,0 +1,960 @@
|
|
|
1
|
+
# TorusGuard Security Audit Findings: run-20260918-105723-audit
|
|
2
|
+
- Target Root: `C:\Users\Admin\Desktop\TorusGuard`
|
|
3
|
+
- Total Scored Findings: `68`
|
|
4
|
+
- Identified Clusters: `9`
|
|
5
|
+
- Generated At: `2026-09-18 10:57:23 IST`
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
## Summary of Findings
|
|
9
|
+
|
|
10
|
+
### [Low] TG-INPUT-002 - Raw SQL Concatenation
|
|
11
|
+
- **Finding ID:** `TG-INPUT-002-f8cd11b9`
|
|
12
|
+
- **Location:** `harness/runner.py:258`
|
|
13
|
+
- **Confidence Score:** `74/100` (High Confidence)
|
|
14
|
+
- **Cluster:** `cluster-injection`
|
|
15
|
+
- **Description:** Python f-string interpolation in raw SQL query
|
|
16
|
+
```
|
|
17
|
+
framework_pattern=FrameworkPattern(
|
|
18
|
+
framework="Django",
|
|
19
|
+
unsafe_snippet="User.objects.raw(f'SELECT * FROM users WHERE name = {name}')",
|
|
20
|
+
safe_snippet="User.objects.raw('SELECT * FROM users WHERE name = %s', [name])",
|
|
21
|
+
),
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
### [Low] TG-SEC-001 - Hardcoded Secret or API Key in Tracked Source
|
|
25
|
+
- **Finding ID:** `TG-SEC-001-593d6437`
|
|
26
|
+
- **Location:** `harness/runner.py:211`
|
|
27
|
+
- **Confidence Score:** `71/100` (High Confidence)
|
|
28
|
+
- **Cluster:** `cluster-credentials-exposure`
|
|
29
|
+
- **Description:** Hardcoded credential or API secret string
|
|
30
|
+
```
|
|
31
|
+
type=EvidenceType.SOURCE,
|
|
32
|
+
location="server/auth.py:42",
|
|
33
|
+
raw_snippet="SECRET_KEY = 'super_secret_jwt_key'",
|
|
34
|
+
rationale="Hardcoded secret credential.",
|
|
35
|
+
confidence_level=ConfidenceBand.CONFIRMED,
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
### [Low] TG-SEC-001 - Hardcoded Secret or API Key in Tracked Source
|
|
39
|
+
- **Finding ID:** `TG-SEC-001-e0a84cf3`
|
|
40
|
+
- **Location:** `harness/runner.py:221`
|
|
41
|
+
- **Confidence Score:** `71/100` (High Confidence)
|
|
42
|
+
- **Cluster:** `cluster-credentials-exposure`
|
|
43
|
+
- **Description:** Hardcoded credential or API secret string
|
|
44
|
+
```
|
|
45
|
+
def test_sensitive_data_masking(self):
|
|
46
|
+
print("\n6. Testing Sensitive Secret & Token Masking...")
|
|
47
|
+
sample_secret = "API_KEY = 'sk_live_998877665544332211'"
|
|
48
|
+
masked = mask_sensitive_data(sample_secret)
|
|
49
|
+
self.log_test("Stripe Secret Key Redaction", "sk_live_***REDACTED***" in masked and "998877665544332211" not in masked)
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### [Low] TG-SEC-001 - Hardcoded Secret or API Key in Tracked Source
|
|
53
|
+
- **Finding ID:** `TG-SEC-001-88c9bb29`
|
|
54
|
+
- **Location:** `harness/runner.py:392`
|
|
55
|
+
- **Confidence Score:** `71/100` (High Confidence)
|
|
56
|
+
- **Cluster:** `cluster-credentials-exposure`
|
|
57
|
+
- **Description:** Hardcoded credential or API secret string
|
|
58
|
+
```
|
|
59
|
+
type=EvidenceType.SOURCE,
|
|
60
|
+
location="settings.py:10",
|
|
61
|
+
raw_snippet="DEBUG = True\nSECRET_KEY = 'sk_live_secret_key_12345'",
|
|
62
|
+
rationale="Production debug mode exposure and hardcoded secret.",
|
|
63
|
+
confidence_level=ConfidenceBand.CONFIRMED,
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### [Low] TG-DB-002 - Privileged Database Credential in Browser Context
|
|
67
|
+
- **Finding ID:** `TG-DB-002-08d11e50`
|
|
68
|
+
- **Location:** `harness/validate_v0_9_2_diff_and_monorepo.py:134`
|
|
69
|
+
- **Confidence Score:** `69/100` (Medium Confidence)
|
|
70
|
+
- **Cluster:** `cluster-client-leak`
|
|
71
|
+
- **Description:** Service role key or raw database connection string reference in frontend code
|
|
72
|
+
```
|
|
73
|
+
assert nextjs_file.is_file(), "Missing actions.ts in vulnerable_nextjs"
|
|
74
|
+
nx_code = nextjs_file.read_text(encoding="utf-8")
|
|
75
|
+
assert "TG-CLIENT-001" in nx_code and "SUPABASE_SERVICE_ROLE_KEY" in nx_code
|
|
76
|
+
assert "TG-AUTH-003" in nx_code and "use server" in nx_code
|
|
77
|
+
print(" [PASS] vulnerable_nextjs fixture contains TG-CLIENT-001 and TG-AUTH-003 sinks")
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### [Low] TG-SEC-001 - Hardcoded Secret or API Key in Tracked Source
|
|
81
|
+
- **Finding ID:** `TG-SEC-001-c616aefd`
|
|
82
|
+
- **Location:** `harness/validate_qa_v0_6_0.py:64`
|
|
83
|
+
- **Confidence Score:** `67/100` (Medium Confidence)
|
|
84
|
+
- **Cluster:** `cluster-credentials-exposure`
|
|
85
|
+
- **Description:** Hardcoded credential or API secret string
|
|
86
|
+
```
|
|
87
|
+
"tiny-repo": {
|
|
88
|
+
"vulnerable": {
|
|
89
|
+
"app.py": 'DEBUG = True\nSECRET_KEY = "sk_live_1234567890"\n\ndef index():\n return "Welcome"\n'
|
|
90
|
+
},
|
|
91
|
+
"hardened": {
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### [Low] TG-SEC-001 - Hardcoded Secret or API Key in Tracked Source
|
|
95
|
+
- **Finding ID:** `TG-SEC-001-d5b3684f`
|
|
96
|
+
- **Location:** `harness/validate_qa_v0_6_0.py:90`
|
|
97
|
+
- **Confidence Score:** `67/100` (Medium Confidence)
|
|
98
|
+
- **Cluster:** `cluster-credentials-exposure`
|
|
99
|
+
- **Description:** Hardcoded credential or API secret string
|
|
100
|
+
```
|
|
101
|
+
"confidence_band": "Confirmed",
|
|
102
|
+
"target": {"file_path": "app.py", "line_start": 2, "line_end": 2},
|
|
103
|
+
"evidence": {"code_snippet": 'SECRET_KEY = "sk_live_1234567890"'},
|
|
104
|
+
"what_is_wrong": "Hardcoded secret exposed in source code.",
|
|
105
|
+
"what_should_change": "Load SECRET_KEY from environment variables.",
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
### [Low] TG-SEC-001 - Hardcoded Secret or API Key in Tracked Source
|
|
109
|
+
- **Finding ID:** `TG-SEC-001-54f1a02a`
|
|
110
|
+
- **Location:** `harness/validate_v0_6_2_modern_stacks.py:341`
|
|
111
|
+
- **Confidence Score:** `67/100` (Medium Confidence)
|
|
112
|
+
- **Cluster:** `cluster-credentials-exposure`
|
|
113
|
+
- **Description:** Hardcoded credential or API secret string
|
|
114
|
+
```
|
|
115
|
+
COPY . .
|
|
116
|
+
# Running as root user & hardcoding secrets
|
|
117
|
+
ENV DATABASE_PASSWORD="secret_in_docker"
|
|
118
|
+
CMD ["python", "main.py"]
|
|
119
|
+
""", encoding="utf-8")
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
### [Low] TG-SEC-001 - Hardcoded Secret or API Key in Tracked Source
|
|
123
|
+
- **Finding ID:** `TG-SEC-001-676f776e`
|
|
124
|
+
- **Location:** `harness/validate_v0_6_2_modern_stacks.py:356`
|
|
125
|
+
- **Confidence Score:** `67/100` (Medium Confidence)
|
|
126
|
+
- **Cluster:** `cluster-credentials-exposure`
|
|
127
|
+
- **Description:** Hardcoded credential or API secret string
|
|
128
|
+
```
|
|
129
|
+
"confidence_band": "Confirmed",
|
|
130
|
+
"target": {"file_path": "Dockerfile", "line_start": 5, "line_end": 5},
|
|
131
|
+
"evidence": {"code_snippet": 'ENV DATABASE_PASSWORD="secret_in_docker"'},
|
|
132
|
+
"what_is_wrong": "Secret baked into immutable container image layer.",
|
|
133
|
+
"what_should_change": "Inject secrets at runtime or use BuildKit --mount=type=secret.",
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
### [Low] TG-SEC-001 - Hardcoded Secret or API Key in Tracked Source
|
|
137
|
+
- **Finding ID:** `TG-SEC-001-58f70e46`
|
|
138
|
+
- **Location:** `harness/validate_v0_6_2_modern_stacks.py:362`
|
|
139
|
+
- **Confidence Score:** `67/100` (Medium Confidence)
|
|
140
|
+
- **Cluster:** `cluster-credentials-exposure`
|
|
141
|
+
- **Description:** Hardcoded credential or API secret string
|
|
142
|
+
```
|
|
143
|
+
+++ b/Dockerfile
|
|
144
|
+
@@ -5,1 +5,2 @@
|
|
145
|
+
-ENV DATABASE_PASSWORD="secret_in_docker"
|
|
146
|
+
+USER appuser
|
|
147
|
+
""",
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
### [Low] TG-DB-002 - Privileged Database Credential in Browser Context
|
|
151
|
+
- **Finding ID:** `TG-DB-002-14cf4139`
|
|
152
|
+
- **Location:** `harness/validate_v0_7_0_runtime.py:129`
|
|
153
|
+
- **Confidence Score:** `66/100` (Medium Confidence)
|
|
154
|
+
- **Cluster:** `cluster-client-leak`
|
|
155
|
+
- **Description:** Service role key or raw database connection string reference in frontend code
|
|
156
|
+
```
|
|
157
|
+
self.send_header("Content-Type", "application/json")
|
|
158
|
+
self.end_headers()
|
|
159
|
+
self.wfile.write(b'{"DEBUG": true, "DATABASE_URL": "sqlite:////app/db.sqlite3"}')
|
|
160
|
+
|
|
161
|
+
elif url_path == "/api/files/download":
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
### [Low] TG-DB-002 - Privileged Database Credential in Browser Context
|
|
165
|
+
- **Finding ID:** `TG-DB-002-b53ad22c`
|
|
166
|
+
- **Location:** `harness/validate_v0_7_0_runtime.py:423`
|
|
167
|
+
- **Confidence Score:** `66/100` (Medium Confidence)
|
|
168
|
+
- **Cluster:** `cluster-client-leak`
|
|
169
|
+
- **Description:** Service role key or raw database connection string reference in frontend code
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
# 6. Exposed debug config -> Runtime Confirmed
|
|
173
|
+
r6 = ExploitChecker.check_debug_exposure(val, "fnd-6", "c-4", f"{self.base_url}/debug/env", "DATABASE_URL")
|
|
174
|
+
self.log_test("Phase 3", "Exposed Debug Configuration Confirmed", r6.status == ExploitabilityStatus.RUNTIME_CONFIRMED.value)
|
|
175
|
+
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
### [Low] TG-INPUT-002 - Raw SQL Concatenation
|
|
179
|
+
- **Finding ID:** `TG-INPUT-002-02f8e274`
|
|
180
|
+
- **Location:** `harness/engine/fixture_manager.py:128`
|
|
181
|
+
- **Confidence Score:** `64/100` (Medium Confidence)
|
|
182
|
+
- **Cluster:** `cluster-injection`
|
|
183
|
+
- **Description:** Python f-string interpolation in raw SQL query
|
|
184
|
+
```
|
|
185
|
+
vulnerable_variant=FixtureVariant(
|
|
186
|
+
relative_path="examples/python/sqlalchemy-vuln",
|
|
187
|
+
code_pattern="session.execute(f'SELECT * FROM items WHERE name LIKE {q}')",
|
|
188
|
+
expected_findings_count=4,
|
|
189
|
+
),
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
### [Low] TG-SEC-001 - Hardcoded Secret or API Key in Tracked Source
|
|
193
|
+
- **Finding ID:** `TG-SEC-001-7c852ff3`
|
|
194
|
+
- **Location:** `harness/master_validation.py:257`
|
|
195
|
+
- **Confidence Score:** `64/100` (Medium Confidence)
|
|
196
|
+
- **Cluster:** `cluster-credentials-exposure`
|
|
197
|
+
- **Description:** Hardcoded credential or API secret string
|
|
198
|
+
```
|
|
199
|
+
self.log("Redaction", "JWT Token Redaction", "Bearer ***REDACTED_JWT***" in masked_jwt and "doNotLeakSignature" not in masked_jwt)
|
|
200
|
+
|
|
201
|
+
masked_pwd = mask_sensitive_data("DB_PASSWORD = 'super_secret_database_password_123'")
|
|
202
|
+
self.log("Redaction", "Password Variable Redaction", "***REDACTED***" in masked_pwd and "super_secret_database_password_123" not in masked_pwd)
|
|
203
|
+
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
### [Low] TG-SEC-001 - Hardcoded Secret or API Key in Tracked Source
|
|
207
|
+
- **Finding ID:** `TG-SEC-001-02761dbb`
|
|
208
|
+
- **Location:** `harness/master_validation.py:460`
|
|
209
|
+
- **Confidence Score:** `64/100` (Medium Confidence)
|
|
210
|
+
- **Cluster:** `cluster-credentials-exposure`
|
|
211
|
+
- **Description:** Hardcoded credential or API secret string
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
def _create_sample_finding(self, rule_id: str, target_path: str, secret_test: bool = False) -> Finding:
|
|
215
|
+
raw_code = "STRIPE_API_KEY = 'sk_live_998877665544332211'\nAuthorization = 'Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIn0.doNotLeakSignature'" if secret_test else f"# Logic for {rule_id}\nrole = request.headers.get('X-User-Role')"
|
|
216
|
+
|
|
217
|
+
ev = Evidence(
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
### [Low] TG-DB-004 - Missing Tenant Query Isolation in Multi-Tenant Models
|
|
221
|
+
- **Finding ID:** `TG-DB-004-e8cc000a`
|
|
222
|
+
- **Location:** `harness/runner.py:505`
|
|
223
|
+
- **Confidence Score:** `64/100` (Medium Confidence)
|
|
224
|
+
- **Cluster:** `cluster-tenant-isolation`
|
|
225
|
+
- **Description:** Django ORM .get(id=...) query lacking explicit tenant scope filter
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
# 2. Stable Finding Identity
|
|
229
|
+
code_a = "def view():\n return Item.objects.get(id=id)"
|
|
230
|
+
code_b = "# Shifted comment\ndef view():\n return Item.objects.get(id=id)"
|
|
231
|
+
fp1 = IdentityEngine.generate_identity("TG-DB-004", "views.py", code_a, sink_signature="Item.objects.get")
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
### [Low] TG-DB-004 - Missing Tenant Query Isolation in Multi-Tenant Models
|
|
235
|
+
- **Finding ID:** `TG-DB-004-89b581f9`
|
|
236
|
+
- **Location:** `harness/runner.py:506`
|
|
237
|
+
- **Confidence Score:** `64/100` (Medium Confidence)
|
|
238
|
+
- **Cluster:** `cluster-tenant-isolation`
|
|
239
|
+
- **Description:** Django ORM .get(id=...) query lacking explicit tenant scope filter
|
|
240
|
+
```
|
|
241
|
+
# 2. Stable Finding Identity
|
|
242
|
+
code_a = "def view():\n return Item.objects.get(id=id)"
|
|
243
|
+
code_b = "# Shifted comment\ndef view():\n return Item.objects.get(id=id)"
|
|
244
|
+
fp1 = IdentityEngine.generate_identity("TG-DB-004", "views.py", code_a, sink_signature="Item.objects.get")
|
|
245
|
+
fp2 = IdentityEngine.generate_identity("TG-DB-004", "views.py", code_b, sink_signature="Item.objects.get")
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
### [Low] TG-SEC-001 - Hardcoded Secret or API Key in Tracked Source
|
|
249
|
+
- **Finding ID:** `TG-SEC-001-3a2b5eca`
|
|
250
|
+
- **Location:** `harness/validate_e2e.py:355`
|
|
251
|
+
- **Confidence Score:** `64/100` (Medium Confidence)
|
|
252
|
+
- **Cluster:** `cluster-credentials-exposure`
|
|
253
|
+
- **Description:** Hardcoded credential or API secret string
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
def _create_sample_finding(self, rule_id: str, target_path: str, secret_test: bool = False) -> Finding:
|
|
257
|
+
raw_code = "API_KEY = 'sk_live_998877665544332211'\nAuthorization = 'Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIn0.doNotLeakSignature'" if secret_test else f"# Unsafe logic for {rule_id}\nrole = request.headers.get('X-User-Role')"
|
|
258
|
+
|
|
259
|
+
ev = Evidence(
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
### [Low] TG-INPUT-002 - Raw SQL Concatenation
|
|
263
|
+
- **Finding ID:** `TG-INPUT-002-8f877a5f`
|
|
264
|
+
- **Location:** `harness/validate_v1_1_0_advanced_memory.py:107`
|
|
265
|
+
- **Confidence Score:** `64/100` (Medium Confidence)
|
|
266
|
+
- **Cluster:** `cluster-injection`
|
|
267
|
+
- **Description:** Python f-string interpolation in raw SQL query
|
|
268
|
+
```
|
|
269
|
+
memory_engine.ensure_memory_structure(root_dir=test_root)
|
|
270
|
+
|
|
271
|
+
valid_before = "cursor.execute(f'SELECT * FROM users WHERE id = {uid}')"
|
|
272
|
+
valid_after = "cursor.execute('SELECT * FROM users WHERE id = %s', (uid,))"
|
|
273
|
+
valid_diff = "- cursor.execute(f'SELECT * FROM users WHERE id = {uid}')\n+ cursor.execute('SELECT * FROM users WHERE id = %s', (uid,))"
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
### [Low] TG-INPUT-002 - Raw SQL Concatenation
|
|
277
|
+
- **Finding ID:** `TG-INPUT-002-266bcaa1`
|
|
278
|
+
- **Location:** `harness/validate_v1_1_0_advanced_memory.py:109`
|
|
279
|
+
- **Confidence Score:** `64/100` (Medium Confidence)
|
|
280
|
+
- **Cluster:** `cluster-injection`
|
|
281
|
+
- **Description:** Python f-string interpolation in raw SQL query
|
|
282
|
+
```
|
|
283
|
+
valid_before = "cursor.execute(f'SELECT * FROM users WHERE id = {uid}')"
|
|
284
|
+
valid_after = "cursor.execute('SELECT * FROM users WHERE id = %s', (uid,))"
|
|
285
|
+
valid_diff = "- cursor.execute(f'SELECT * FROM users WHERE id = {uid}')\n+ cursor.execute('SELECT * FROM users WHERE id = %s', (uid,))"
|
|
286
|
+
|
|
287
|
+
recipe = memory_engine.record_golden_recipe(
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
### [Low] TG-PLATFORM-003 - Production Stack Trace Exposure
|
|
291
|
+
- **Finding ID:** `TG-PLATFORM-003-69f083d6`
|
|
292
|
+
- **Location:** `harness/runner.py:392`
|
|
293
|
+
- **Confidence Score:** `61/100` (Medium Confidence)
|
|
294
|
+
- **Cluster:** `cluster-platform`
|
|
295
|
+
- **Description:** Django DEBUG mode enabled in configuration
|
|
296
|
+
```
|
|
297
|
+
type=EvidenceType.SOURCE,
|
|
298
|
+
location="settings.py:10",
|
|
299
|
+
raw_snippet="DEBUG = True\nSECRET_KEY = 'sk_live_secret_key_12345'",
|
|
300
|
+
rationale="Production debug mode exposure and hardcoded secret.",
|
|
301
|
+
confidence_level=ConfidenceBand.CONFIRMED,
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
### [Low] TG-PLATFORM-003 - Production Stack Trace Exposure
|
|
305
|
+
- **Finding ID:** `TG-PLATFORM-003-6f253f06`
|
|
306
|
+
- **Location:** `harness/runner.py:405`
|
|
307
|
+
- **Confidence Score:** `61/100` (Medium Confidence)
|
|
308
|
+
- **Cluster:** `cluster-platform`
|
|
309
|
+
- **Description:** Django DEBUG mode enabled in configuration
|
|
310
|
+
```
|
|
311
|
+
prov = ProvenanceChain(
|
|
312
|
+
discovery_module="rules/TG-PLATFORM-003-production-stack-trace-exposure.md",
|
|
313
|
+
triggering_input="DEBUG = True assignment in settings.py",
|
|
314
|
+
evidence_collected=["settings.py:10"],
|
|
315
|
+
decision_path=["Loaded Django settings", "Found DEBUG enabled"],
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
### [Low] TG-PLATFORM-003 - Production Stack Trace Exposure
|
|
319
|
+
- **Finding ID:** `TG-PLATFORM-003-fbe8ec66`
|
|
320
|
+
- **Location:** `harness/runner.py:416`
|
|
321
|
+
- **Confidence Score:** `61/100` (Medium Confidence)
|
|
322
|
+
- **Cluster:** `cluster-platform`
|
|
323
|
+
- **Description:** Django DEBUG mode enabled in configuration
|
|
324
|
+
```
|
|
325
|
+
framework_pattern=FrameworkPattern(
|
|
326
|
+
framework="Django",
|
|
327
|
+
unsafe_snippet="DEBUG = True",
|
|
328
|
+
safe_snippet="DEBUG = False",
|
|
329
|
+
),
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
### [Low] TG-RATE-001 - Unlimited Authentication Endpoint
|
|
333
|
+
- **Finding ID:** `TG-RATE-001-758a7750`
|
|
334
|
+
- **Location:** `harness/runner.py:575`
|
|
335
|
+
- **Confidence Score:** `60/100` (Medium Confidence)
|
|
336
|
+
- **Cluster:** `cluster-rate-limiting`
|
|
337
|
+
- **Description:** Authentication POST endpoint defined without rate-limiting middleware
|
|
338
|
+
```
|
|
339
|
+
"line_number": 25,
|
|
340
|
+
"description": "Unprotected auth route lacking rate limiting.",
|
|
341
|
+
"snippet": "app.post('/login', async (req, res) => {})",
|
|
342
|
+
"confidence_score": 85,
|
|
343
|
+
"confidence_band": "High Confidence"
|
|
344
|
+
```
|
|
345
|
+
|
|
346
|
+
### [Low] TG-DIFF-001 - Accidental Security Check Bypass in Patch Additions
|
|
347
|
+
- **Finding ID:** `TG-DIFF-001-04571685`
|
|
348
|
+
- **Location:** `harness/evaluate_portfolio_polyglot.py:74`
|
|
349
|
+
- **Confidence Score:** `59/100` (Medium Confidence)
|
|
350
|
+
- **Cluster:** `cluster-transport-security`
|
|
351
|
+
- **Description:** Disabled TLS certificate verification (verify=False)
|
|
352
|
+
```
|
|
353
|
+
"expected_orm": "SQLAlchemy",
|
|
354
|
+
"ecosystem": "Python",
|
|
355
|
+
"test_bypass": ("python", "verify=False", "auth_bypass"),
|
|
356
|
+
"test_tenant": ("python", "tenant_id"),
|
|
357
|
+
},
|
|
358
|
+
```
|
|
359
|
+
|
|
360
|
+
### [Low] TG-DIFF-001 - Accidental Security Check Bypass in Patch Additions
|
|
361
|
+
- **Finding ID:** `TG-DIFF-001-8b55ac4b`
|
|
362
|
+
- **Location:** `harness/evaluate_portfolio_polyglot.py:151`
|
|
363
|
+
- **Confidence Score:** `59/100` (Medium Confidence)
|
|
364
|
+
- **Cluster:** `cluster-transport-security`
|
|
365
|
+
- **Description:** Disabled Go TLS certificate verification (InsecureSkipVerify: true)
|
|
366
|
+
```
|
|
367
|
+
"expected_orm": "GORM",
|
|
368
|
+
"ecosystem": "Go",
|
|
369
|
+
"test_bypass": ("go", "InsecureSkipVerify: true", "tls_bypass"),
|
|
370
|
+
"test_tenant": ("go", '.Where("tenant_id = ?", tenantID)'),
|
|
371
|
+
},
|
|
372
|
+
```
|
|
373
|
+
|
|
374
|
+
### [Low] TG-DIFF-001 - Accidental Security Check Bypass in Patch Additions
|
|
375
|
+
- **Finding ID:** `TG-DIFF-001-cf8d252d`
|
|
376
|
+
- **Location:** `harness/evaluate_portfolio_polyglot.py:162`
|
|
377
|
+
- **Confidence Score:** `59/100` (Medium Confidence)
|
|
378
|
+
- **Cluster:** `cluster-transport-security`
|
|
379
|
+
- **Description:** Disabled Go TLS certificate verification (InsecureSkipVerify: true)
|
|
380
|
+
```
|
|
381
|
+
"expected_orm": "SQLx",
|
|
382
|
+
"ecosystem": "Go",
|
|
383
|
+
"test_bypass": ("go", "tls.Config{InsecureSkipVerify: true}", "tls_bypass"),
|
|
384
|
+
"test_tenant": ("go", '.Where("org_id = ?", orgID)'),
|
|
385
|
+
},
|
|
386
|
+
```
|
|
387
|
+
|
|
388
|
+
### [Low] TG-DIFF-001 - Accidental Security Check Bypass in Patch Additions
|
|
389
|
+
- **Finding ID:** `TG-DIFF-001-3543946e`
|
|
390
|
+
- **Location:** `harness/evaluate_portfolio_polyglot.py:173`
|
|
391
|
+
- **Confidence Score:** `59/100` (Medium Confidence)
|
|
392
|
+
- **Cluster:** `cluster-transport-security`
|
|
393
|
+
- **Description:** Disabled Go TLS certificate verification (InsecureSkipVerify: true)
|
|
394
|
+
```
|
|
395
|
+
"expected_orm": None,
|
|
396
|
+
"ecosystem": "Go",
|
|
397
|
+
"test_bypass": ("go", "InsecureSkipVerify: true", "tls_bypass"),
|
|
398
|
+
"test_tenant": ("go", '.Where("tenant_id = ?", tid)'),
|
|
399
|
+
},
|
|
400
|
+
```
|
|
401
|
+
|
|
402
|
+
### [Low] TG-DIFF-001 - Accidental Security Check Bypass in Patch Additions
|
|
403
|
+
- **Finding ID:** `TG-DIFF-001-efffaad0`
|
|
404
|
+
- **Location:** `harness/evaluate_portfolio_polyglot.py:349`
|
|
405
|
+
- **Confidence Score:** `59/100` (Medium Confidence)
|
|
406
|
+
- **Cluster:** `cluster-transport-security`
|
|
407
|
+
- **Description:** Disabled Go TLS certificate verification (InsecureSkipVerify: true)
|
|
408
|
+
```
|
|
409
|
+
"expected_orm": None,
|
|
410
|
+
"ecosystem": "Polyglot Fleet",
|
|
411
|
+
"test_bypass": ("go", "InsecureSkipVerify: true", "tls_bypass"),
|
|
412
|
+
"test_tenant": ("go", '.Where("tenant_id = ?", tid)'),
|
|
413
|
+
},
|
|
414
|
+
```
|
|
415
|
+
|
|
416
|
+
### [Low] TG-DIFF-001 - Accidental Security Check Bypass in Patch Additions
|
|
417
|
+
- **Finding ID:** `TG-DIFF-001-91bd06b8`
|
|
418
|
+
- **Location:** `harness/evaluate_portfolio_polyglot.py:129`
|
|
419
|
+
- **Confidence Score:** `59/100` (Medium Confidence)
|
|
420
|
+
- **Cluster:** `cluster-transport-security`
|
|
421
|
+
- **Description:** Disabled Node.js TLS rejectUnauthorized
|
|
422
|
+
```
|
|
423
|
+
"expected_orm": "Mongoose",
|
|
424
|
+
"ecosystem": "JavaScript",
|
|
425
|
+
"test_bypass": ("javascript", "rejectUnauthorized: false", "tls_bypass"),
|
|
426
|
+
"test_tenant": ("javascript", "author: req.user.id"),
|
|
427
|
+
},
|
|
428
|
+
```
|
|
429
|
+
|
|
430
|
+
### [Low] TG-DIFF-001 - Accidental Security Check Bypass in Patch Additions
|
|
431
|
+
- **Finding ID:** `TG-DIFF-001-cb245735`
|
|
432
|
+
- **Location:** `harness/evaluate_portfolio_polyglot.py:261`
|
|
433
|
+
- **Confidence Score:** `59/100` (Medium Confidence)
|
|
434
|
+
- **Cluster:** `cluster-transport-security`
|
|
435
|
+
- **Description:** Disabled PHP curl SSL verification
|
|
436
|
+
```
|
|
437
|
+
"expected_orm": "Eloquent",
|
|
438
|
+
"ecosystem": "PHP",
|
|
439
|
+
"test_bypass": ("php", "CURLOPT_SSL_VERIFYPEER => false", "tls_bypass"),
|
|
440
|
+
"test_tenant": ("php", 'where("tenant_id", $tenantId)'),
|
|
441
|
+
},
|
|
442
|
+
```
|
|
443
|
+
|
|
444
|
+
### [Low] TG-DIFF-001 - Accidental Security Check Bypass in Patch Additions
|
|
445
|
+
- **Finding ID:** `TG-DIFF-001-6667680a`
|
|
446
|
+
- **Location:** `harness/validate_v0_9_2_diff_and_monorepo.py:60`
|
|
447
|
+
- **Confidence Score:** `59/100` (Medium Confidence)
|
|
448
|
+
- **Cluster:** `cluster-transport-security`
|
|
449
|
+
- **Description:** Disabled TLS certificate verification (verify=False)
|
|
450
|
+
```
|
|
451
|
+
def authenticate_user(token):
|
|
452
|
+
+ # TODO: bypass auth check for debugging
|
|
453
|
+
+ verify = False
|
|
454
|
+
return True
|
|
455
|
+
"""
|
|
456
|
+
```
|
|
457
|
+
|
|
458
|
+
### [Low] TG-DIFF-001 - Accidental Security Check Bypass in Patch Additions
|
|
459
|
+
- **Finding ID:** `TG-DIFF-001-00b3b8ca`
|
|
460
|
+
- **Location:** `harness/validate_v0_9_2_diff_and_monorepo.py:67`
|
|
461
|
+
- **Confidence Score:** `59/100` (Medium Confidence)
|
|
462
|
+
- **Cluster:** `cluster-transport-security`
|
|
463
|
+
- **Description:** Disabled TLS certificate verification (verify=False)
|
|
464
|
+
```
|
|
465
|
+
rule_ids = [v["rule_id"] for v in res_bypass["violations"]]
|
|
466
|
+
assert "TG-DIFF-001" in rule_ids, "TG-DIFF-001 bypass not caught"
|
|
467
|
+
print(f" [PASS] TG-DIFF-001: Caught bypass comments and verify=False ({res_bypass['total_violations']} violations)")
|
|
468
|
+
|
|
469
|
+
mock_key = "sk" + "_live_" + "99887766554433221100aabbccdd"
|
|
470
|
+
```
|
|
471
|
+
|
|
472
|
+
### [Low] TG-DIFF-001 - Accidental Security Check Bypass in Patch Additions
|
|
473
|
+
- **Finding ID:** `TG-DIFF-001-f209dec6`
|
|
474
|
+
- **Location:** `harness/validate_v1_3_0_polyglot.py:16`
|
|
475
|
+
- **Confidence Score:** `59/100` (Medium Confidence)
|
|
476
|
+
- **Cluster:** `cluster-transport-security`
|
|
477
|
+
- **Description:** Disabled Go TLS certificate verification (InsecureSkipVerify: true)
|
|
478
|
+
```
|
|
479
|
+
- File extension census fallback (no manifest)
|
|
480
|
+
2. Polyglot Diff Guard bypass detection across:
|
|
481
|
+
- Go (InsecureSkipVerify: true)
|
|
482
|
+
- Java (csrf().disable())
|
|
483
|
+
- C# ([AllowAnonymous])
|
|
484
|
+
```
|
|
485
|
+
|
|
486
|
+
### [Low] TG-DIFF-001 - Accidental Security Check Bypass in Patch Additions
|
|
487
|
+
- **Finding ID:** `TG-DIFF-001-d9adecdb`
|
|
488
|
+
- **Location:** `harness/validate_v1_3_0_polyglot.py:182`
|
|
489
|
+
- **Confidence Score:** `59/100` (Medium Confidence)
|
|
490
|
+
- **Cluster:** `cluster-transport-security`
|
|
491
|
+
- **Description:** Disabled Go TLS certificate verification (InsecureSkipVerify: true)
|
|
492
|
+
```
|
|
493
|
+
+++ b/client.go
|
|
494
|
+
@@ -10,3 +10,4 @@
|
|
495
|
+
+ tr := &http.Transport{TLSClientConfig: &tls.Config{InsecureSkipVerify: true}}
|
|
496
|
+
"""
|
|
497
|
+
viol_go = diff_guard.check_diff_content(diff_go, "client.go")
|
|
498
|
+
```
|
|
499
|
+
|
|
500
|
+
### [Low] TG-DIFF-001 - Accidental Security Check Bypass in Patch Additions
|
|
501
|
+
- **Finding ID:** `TG-DIFF-001-ddbf5cf0`
|
|
502
|
+
- **Location:** `harness/validate_v1_3_0_polyglot.py:19`
|
|
503
|
+
- **Confidence Score:** `59/100` (Medium Confidence)
|
|
504
|
+
- **Cluster:** `cluster-transport-security`
|
|
505
|
+
- **Description:** Disabled PHP curl SSL verification
|
|
506
|
+
```
|
|
507
|
+
- Java (csrf().disable())
|
|
508
|
+
- C# ([AllowAnonymous])
|
|
509
|
+
- PHP (CURLOPT_SSL_VERIFYPEER => false)
|
|
510
|
+
- Rust (unsafe { ... })
|
|
511
|
+
3. Polyglot Tenant Scoping Patterns across GORM, LINQ, and Prisma
|
|
512
|
+
```
|
|
513
|
+
|
|
514
|
+
### [Low] TG-DIFF-001 - Accidental Security Check Bypass in Patch Additions
|
|
515
|
+
- **Finding ID:** `TG-DIFF-001-2b3eb6b7`
|
|
516
|
+
- **Location:** `harness/validate_v1_3_0_polyglot.py:215`
|
|
517
|
+
- **Confidence Score:** `59/100` (Medium Confidence)
|
|
518
|
+
- **Cluster:** `cluster-transport-security`
|
|
519
|
+
- **Description:** Disabled PHP curl SSL verification
|
|
520
|
+
```
|
|
521
|
+
+++ b/api.php
|
|
522
|
+
@@ -5,3 +5,4 @@
|
|
523
|
+
+ curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
|
|
524
|
+
"""
|
|
525
|
+
viol_php = diff_guard.check_diff_content(diff_php, "api.php")
|
|
526
|
+
```
|
|
527
|
+
|
|
528
|
+
### [Low] TG-INPUT-005 - Unsafe Template Rendering & Disabled Autoescaping
|
|
529
|
+
- **Finding ID:** `TG-INPUT-005-7f81ea7f`
|
|
530
|
+
- **Location:** `harness/validate_qa_v0_6_0.py:177`
|
|
531
|
+
- **Confidence Score:** `57/100` (Medium Confidence)
|
|
532
|
+
- **Cluster:** `cluster-injection`
|
|
533
|
+
- **Description:** Flask render_template_string rendering untrusted input
|
|
534
|
+
```
|
|
535
|
+
"flask-app": {
|
|
536
|
+
"vulnerable": {
|
|
537
|
+
"app.py": 'from flask import Flask, request, render_template_string\nimport os\n\napp = Flask(__name__)\n\n@app.route("/greet")\ndef greet():\n name = request.args.get("name", "Guest")\n # SSTI: Unescaped string formatting in template\n return render_template_string(f"Hello {name}")\n\n@app.route("/upload", methods=["POST"])\ndef upload():\n f = request.files["file"]\n # Path Traversal in filename\n f.save(os.path.join("/var/uploads", f.filename))\n return "Saved"\n'
|
|
538
|
+
},
|
|
539
|
+
"hardened": {
|
|
540
|
+
```
|
|
541
|
+
|
|
542
|
+
### [Low] TG-INPUT-005 - Unsafe Template Rendering & Disabled Autoescaping
|
|
543
|
+
- **Finding ID:** `TG-INPUT-005-d5aaebe0`
|
|
544
|
+
- **Location:** `harness/validate_qa_v0_6_0.py:190`
|
|
545
|
+
- **Confidence Score:** `57/100` (Medium Confidence)
|
|
546
|
+
- **Cluster:** `cluster-injection`
|
|
547
|
+
- **Description:** Flask render_template_string rendering untrusted input
|
|
548
|
+
```
|
|
549
|
+
"confidence_band": "Confirmed",
|
|
550
|
+
"target": {"file_path": "app.py", "line_start": 10, "line_end": 10},
|
|
551
|
+
"evidence": {"code_snippet": 'return render_template_string(f"Hello {name}")'},
|
|
552
|
+
"what_is_wrong": "User input formatted directly into template string.",
|
|
553
|
+
"what_should_change": "Render static template file with contextual autoescaping.",
|
|
554
|
+
```
|
|
555
|
+
|
|
556
|
+
### [Low] TG-INPUT-005 - Unsafe Template Rendering & Disabled Autoescaping
|
|
557
|
+
- **Finding ID:** `TG-INPUT-005-e0ffb03b`
|
|
558
|
+
- **Location:** `harness/validate_qa_v0_6_0.py:193`
|
|
559
|
+
- **Confidence Score:** `57/100` (Medium Confidence)
|
|
560
|
+
- **Cluster:** `cluster-injection`
|
|
561
|
+
- **Description:** Flask render_template_string rendering untrusted input
|
|
562
|
+
```
|
|
563
|
+
"what_is_wrong": "User input formatted directly into template string.",
|
|
564
|
+
"what_should_change": "Render static template file with contextual autoescaping.",
|
|
565
|
+
"proposed_diff": "--- a/app.py\n+++ b/app.py\n@@ -10,1 +10,1 @@\n-return render_template_string(f\"Hello {name}\")\n+return render_template(\"greet.html\", name=name)\n",
|
|
566
|
+
"verification_steps": "Send name={{7*7}} and verify output contains literal {{7*7}} instead of 49.",
|
|
567
|
+
},
|
|
568
|
+
```
|
|
569
|
+
|
|
570
|
+
### [Low] TG-PLATFORM-003 - Production Stack Trace Exposure
|
|
571
|
+
- **Finding ID:** `TG-PLATFORM-003-153d982f`
|
|
572
|
+
- **Location:** `harness/validate_qa_v0_6_0.py:64`
|
|
573
|
+
- **Confidence Score:** `57/100` (Medium Confidence)
|
|
574
|
+
- **Cluster:** `cluster-platform`
|
|
575
|
+
- **Description:** Django DEBUG mode enabled in configuration
|
|
576
|
+
```
|
|
577
|
+
"tiny-repo": {
|
|
578
|
+
"vulnerable": {
|
|
579
|
+
"app.py": 'DEBUG = True\nSECRET_KEY = "sk_live_1234567890"\n\ndef index():\n return "Welcome"\n'
|
|
580
|
+
},
|
|
581
|
+
"hardened": {
|
|
582
|
+
```
|
|
583
|
+
|
|
584
|
+
### [Low] TG-PLATFORM-003 - Production Stack Trace Exposure
|
|
585
|
+
- **Finding ID:** `TG-PLATFORM-003-21644311`
|
|
586
|
+
- **Location:** `harness/validate_qa_v0_6_0.py:77`
|
|
587
|
+
- **Confidence Score:** `57/100` (Medium Confidence)
|
|
588
|
+
- **Cluster:** `cluster-platform`
|
|
589
|
+
- **Description:** Django DEBUG mode enabled in configuration
|
|
590
|
+
```
|
|
591
|
+
"confidence_band": "Confirmed",
|
|
592
|
+
"target": {"file_path": "app.py", "line_start": 1, "line_end": 1},
|
|
593
|
+
"evidence": {"code_snippet": "DEBUG = True"},
|
|
594
|
+
"what_is_wrong": "DEBUG is statically enabled.",
|
|
595
|
+
"what_should_change": "Load DEBUG from environment variables.",
|
|
596
|
+
```
|
|
597
|
+
|
|
598
|
+
### [Low] TG-PLATFORM-003 - Production Stack Trace Exposure
|
|
599
|
+
- **Finding ID:** `TG-PLATFORM-003-21b8a588`
|
|
600
|
+
- **Location:** `harness/validate_qa_v0_6_0.py:80`
|
|
601
|
+
- **Confidence Score:** `57/100` (Medium Confidence)
|
|
602
|
+
- **Cluster:** `cluster-platform`
|
|
603
|
+
- **Description:** Django DEBUG mode enabled in configuration
|
|
604
|
+
```
|
|
605
|
+
"what_is_wrong": "DEBUG is statically enabled.",
|
|
606
|
+
"what_should_change": "Load DEBUG from environment variables.",
|
|
607
|
+
"proposed_diff": "--- a/app.py\n+++ b/app.py\n@@ -1,1 +1,2 @@\n-DEBUG = True\n+import os\n+DEBUG = os.getenv('DEBUG', 'False').lower() == 'true'\n",
|
|
608
|
+
"verification_steps": "Check DEBUG setting resolution in production.",
|
|
609
|
+
},
|
|
610
|
+
```
|
|
611
|
+
|
|
612
|
+
### [Low] TG-DB-004 - Missing Tenant Query Isolation in Multi-Tenant Models
|
|
613
|
+
- **Finding ID:** `TG-DB-004-e33fd263`
|
|
614
|
+
- **Location:** `harness/validate_v0_6_3_hardening.py:119`
|
|
615
|
+
- **Confidence Score:** `57/100` (Medium Confidence)
|
|
616
|
+
- **Cluster:** `cluster-tenant-isolation`
|
|
617
|
+
- **Description:** Django ORM .get(id=...) query lacking explicit tenant scope filter
|
|
618
|
+
```
|
|
619
|
+
snippet_v1 = """def process_invoice(req, inv_id):
|
|
620
|
+
# Retrieve invoice
|
|
621
|
+
inv = Invoice.objects.get(id=inv_id)
|
|
622
|
+
return inv
|
|
623
|
+
"""
|
|
624
|
+
```
|
|
625
|
+
|
|
626
|
+
### [Low] TG-DB-004 - Missing Tenant Query Isolation in Multi-Tenant Models
|
|
627
|
+
- **Finding ID:** `TG-DB-004-ff3f7499`
|
|
628
|
+
- **Location:** `harness/validate_v0_6_3_hardening.py:127`
|
|
629
|
+
- **Confidence Score:** `57/100` (Medium Confidence)
|
|
630
|
+
- **Cluster:** `cluster-tenant-isolation`
|
|
631
|
+
- **Description:** Django ORM .get(id=...) query lacking explicit tenant scope filter
|
|
632
|
+
```
|
|
633
|
+
snippet_v2 = """def process_invoice(req, inv_id):
|
|
634
|
+
# Retrieve invoice
|
|
635
|
+
inv = Invoice.objects.get(id=inv_id)
|
|
636
|
+
return inv
|
|
637
|
+
"""
|
|
638
|
+
```
|
|
639
|
+
|
|
640
|
+
### [Low] TG-DB-004 - Missing Tenant Query Isolation in Multi-Tenant Models
|
|
641
|
+
- **Finding ID:** `TG-DB-004-a7c00c05`
|
|
642
|
+
- **Location:** `harness/validate_v0_6_3_hardening.py:135`
|
|
643
|
+
- **Confidence Score:** `57/100` (Medium Confidence)
|
|
644
|
+
- **Cluster:** `cluster-tenant-isolation`
|
|
645
|
+
- **Description:** Django ORM .get(id=...) query lacking explicit tenant scope filter
|
|
646
|
+
```
|
|
647
|
+
snippet_v3 = """def process_invoice(req, inv_id):
|
|
648
|
+
# Different comment text here
|
|
649
|
+
inv = Invoice.objects.get(id=inv_id)
|
|
650
|
+
return inv
|
|
651
|
+
"""
|
|
652
|
+
```
|
|
653
|
+
|
|
654
|
+
### [Low] TG-DB-004 - Missing Tenant Query Isolation in Multi-Tenant Models
|
|
655
|
+
- **Finding ID:** `TG-DB-004-8b6c1463`
|
|
656
|
+
- **Location:** `harness/validate_v0_6_3_hardening.py:171`
|
|
657
|
+
- **Confidence Score:** `57/100` (Medium Confidence)
|
|
658
|
+
- **Cluster:** `cluster-tenant-isolation`
|
|
659
|
+
- **Description:** Django ORM .get(id=...) query lacking explicit tenant scope filter
|
|
660
|
+
```
|
|
661
|
+
"confidence_band": "Confirmed",
|
|
662
|
+
"target": {"file_path": "apps/billing/views.py", "line_start": 12, "line_end": 14},
|
|
663
|
+
"evidence": {"code_snippet": "Invoice.objects.get(id=inv_id)"},
|
|
664
|
+
"cluster_id": "cluster-tenant-isolation",
|
|
665
|
+
"recheck_status": "Confirmed Fixed",
|
|
666
|
+
```
|
|
667
|
+
|
|
668
|
+
### [Low] TG-AUTH-004 - Insecure Session Cookie Configuration
|
|
669
|
+
- **Finding ID:** `TG-AUTH-004-33adb2d9`
|
|
670
|
+
- **Location:** `harness/evaluate_portfolio_polyglot.py:107`
|
|
671
|
+
- **Confidence Score:** `56/100` (Medium Confidence)
|
|
672
|
+
- **Cluster:** `cluster-auth-bypass`
|
|
673
|
+
- **Description:** Session cookie secure flag disabled in Django settings
|
|
674
|
+
```
|
|
675
|
+
"expected_orm": "SQLAlchemy",
|
|
676
|
+
"ecosystem": "Python",
|
|
677
|
+
"test_bypass": ("python", "SESSION_COOKIE_SECURE = False", "auth_bypass"),
|
|
678
|
+
"test_tenant": ("python", "tenant_id"),
|
|
679
|
+
},
|
|
680
|
+
```
|
|
681
|
+
|
|
682
|
+
### [Low] TG-AUTH-004 - Insecure Session Cookie Configuration
|
|
683
|
+
- **Finding ID:** `TG-AUTH-004-56b1c90f`
|
|
684
|
+
- **Location:** `harness/evaluate_portfolio_polyglot.py:96`
|
|
685
|
+
- **Confidence Score:** `56/100` (Medium Confidence)
|
|
686
|
+
- **Cluster:** `cluster-auth-bypass`
|
|
687
|
+
- **Description:** Decorator disabling route-level authentication or CSRF protection
|
|
688
|
+
```
|
|
689
|
+
"expected_orm": "Django ORM",
|
|
690
|
+
"ecosystem": "Python",
|
|
691
|
+
"test_bypass": ("python", "@csrf_exempt", "auth_bypass"),
|
|
692
|
+
"test_tenant": ("python", "tenant"),
|
|
693
|
+
},
|
|
694
|
+
```
|
|
695
|
+
|
|
696
|
+
### [Low] TG-AUTH-004 - Insecure Session Cookie Configuration
|
|
697
|
+
- **Finding ID:** `TG-AUTH-004-4a33f7e7`
|
|
698
|
+
- **Location:** `harness/evaluate_portfolio_polyglot.py:239`
|
|
699
|
+
- **Confidence Score:** `56/100` (Medium Confidence)
|
|
700
|
+
- **Cluster:** `cluster-auth-bypass`
|
|
701
|
+
- **Description:** Attribute disabling ASP.NET authentication
|
|
702
|
+
```
|
|
703
|
+
"expected_orm": "Entity Framework Core",
|
|
704
|
+
"ecosystem": "C#",
|
|
705
|
+
"test_bypass": ("csharp", "[AllowAnonymous]", "auth_bypass"),
|
|
706
|
+
"test_tenant": ("csharp", ".Where(x => x.TenantId == tenantId)"),
|
|
707
|
+
},
|
|
708
|
+
```
|
|
709
|
+
|
|
710
|
+
### [Low] TG-AUTH-004 - Insecure Session Cookie Configuration
|
|
711
|
+
- **Finding ID:** `TG-AUTH-004-95eb27cd`
|
|
712
|
+
- **Location:** `harness/evaluate_portfolio_polyglot.py:876`
|
|
713
|
+
- **Confidence Score:** `56/100` (Medium Confidence)
|
|
714
|
+
- **Cluster:** `cluster-auth-bypass`
|
|
715
|
+
- **Description:** Attribute disabling ASP.NET authentication
|
|
716
|
+
```
|
|
717
|
+
| **4. 5-Factor Confidence Scorer** | 100% | Applied objective $0–100$ scoring with memory modifiers and false positive deductions. |
|
|
718
|
+
| **5. Adaptive Security Memory Engine** | 100% | Isolated memory workspace successfully recorded events and verified context cards $\le 2,000$ tokens. |
|
|
719
|
+
| **6. Polyglot Diff Guard** | 100% | Intercepted Go `InsecureSkipVerify`, Java `csrf().disable()`, C# `[AllowAnonymous]`, PHP `CURLOPT_SSL_VERIFYPEER`, Rust `unsafe {`, and tenant stripping. |
|
|
720
|
+
| **7. Governed Remediation (Ponytail)** | 100% | Enforced patch churn limits ($\le 35$ additions, $\le 25$ deletions) and pre-apply snapshot generation. |
|
|
721
|
+
| **8. Visual HTML Dashboard** | 100% | Generated self-contained, air-gapped dark-mode visual report with SVG circular gauge. |
|
|
722
|
+
```
|
|
723
|
+
|
|
724
|
+
### [Low] TG-AUTH-004 - Insecure Session Cookie Configuration
|
|
725
|
+
- **Finding ID:** `TG-AUTH-004-e838c41c`
|
|
726
|
+
- **Location:** `harness/validate_v1_3_0_polyglot.py:18`
|
|
727
|
+
- **Confidence Score:** `56/100` (Medium Confidence)
|
|
728
|
+
- **Cluster:** `cluster-auth-bypass`
|
|
729
|
+
- **Description:** Attribute disabling ASP.NET authentication
|
|
730
|
+
```
|
|
731
|
+
- Go (InsecureSkipVerify: true)
|
|
732
|
+
- Java (csrf().disable())
|
|
733
|
+
- C# ([AllowAnonymous])
|
|
734
|
+
- PHP (CURLOPT_SSL_VERIFYPEER => false)
|
|
735
|
+
- Rust (unsafe { ... })
|
|
736
|
+
```
|
|
737
|
+
|
|
738
|
+
### [Low] TG-AUTH-004 - Insecure Session Cookie Configuration
|
|
739
|
+
- **Finding ID:** `TG-AUTH-004-5c78d750`
|
|
740
|
+
- **Location:** `harness/validate_v1_3_0_polyglot.py:204`
|
|
741
|
+
- **Confidence Score:** `56/100` (Medium Confidence)
|
|
742
|
+
- **Cluster:** `cluster-auth-bypass`
|
|
743
|
+
- **Description:** Attribute disabling ASP.NET authentication
|
|
744
|
+
```
|
|
745
|
+
+++ b/UsersController.cs
|
|
746
|
+
@@ -15,3 +15,4 @@
|
|
747
|
+
+ [AllowAnonymous]
|
|
748
|
+
+ public IActionResult GetFinancialData() {
|
|
749
|
+
"""
|
|
750
|
+
```
|
|
751
|
+
|
|
752
|
+
### [Low] TG-AUTH-004 - Insecure Session Cookie Configuration
|
|
753
|
+
- **Finding ID:** `TG-AUTH-004-0d028be7`
|
|
754
|
+
- **Location:** `harness/validate_v1_3_0_polyglot.py:208`
|
|
755
|
+
- **Confidence Score:** `56/100` (Medium Confidence)
|
|
756
|
+
- **Cluster:** `cluster-auth-bypass`
|
|
757
|
+
- **Description:** Attribute disabling ASP.NET authentication
|
|
758
|
+
```
|
|
759
|
+
"""
|
|
760
|
+
viol_cs = diff_guard.check_diff_content(diff_cs, "UsersController.cs")
|
|
761
|
+
assert len(viol_cs) >= 1, "Failed to catch C# [AllowAnonymous]"
|
|
762
|
+
print(" [PASS] Caught C# ASP.NET [AllowAnonymous] bypass")
|
|
763
|
+
|
|
764
|
+
```
|
|
765
|
+
|
|
766
|
+
### [Low] TG-AUTH-004 - Insecure Session Cookie Configuration
|
|
767
|
+
- **Finding ID:** `TG-AUTH-004-3ae1d9c1`
|
|
768
|
+
- **Location:** `harness/validate_v1_3_0_polyglot.py:209`
|
|
769
|
+
- **Confidence Score:** `56/100` (Medium Confidence)
|
|
770
|
+
- **Cluster:** `cluster-auth-bypass`
|
|
771
|
+
- **Description:** Attribute disabling ASP.NET authentication
|
|
772
|
+
```
|
|
773
|
+
viol_cs = diff_guard.check_diff_content(diff_cs, "UsersController.cs")
|
|
774
|
+
assert len(viol_cs) >= 1, "Failed to catch C# [AllowAnonymous]"
|
|
775
|
+
print(" [PASS] Caught C# ASP.NET [AllowAnonymous] bypass")
|
|
776
|
+
|
|
777
|
+
# PHP CURLOPT_SSL_VERIFYPEER bypass
|
|
778
|
+
```
|
|
779
|
+
|
|
780
|
+
### [Low] TG-AUTH-004 - Insecure Session Cookie Configuration
|
|
781
|
+
- **Finding ID:** `TG-AUTH-004-ea07db54`
|
|
782
|
+
- **Location:** `harness/validate_v1_3_0_polyglot.py:193`
|
|
783
|
+
- **Confidence Score:** `56/100` (Medium Confidence)
|
|
784
|
+
- **Cluster:** `cluster-auth-bypass`
|
|
785
|
+
- **Description:** Spring Security CSRF protection explicitly disabled
|
|
786
|
+
```
|
|
787
|
+
+++ b/SecurityConfig.java
|
|
788
|
+
@@ -20,3 +20,4 @@
|
|
789
|
+
+ http.csrf().disable();
|
|
790
|
+
"""
|
|
791
|
+
viol_java = diff_guard.check_diff_content(diff_java, "SecurityConfig.java")
|
|
792
|
+
```
|
|
793
|
+
|
|
794
|
+
### [Low] TG-INPUT-005 - Unsafe Template Rendering & Disabled Autoescaping
|
|
795
|
+
- **Finding ID:** `TG-INPUT-005-0d595acd`
|
|
796
|
+
- **Location:** `harness/master_validation.py:314`
|
|
797
|
+
- **Confidence Score:** `54/100` (Medium Confidence)
|
|
798
|
+
- **Cluster:** `cluster-injection`
|
|
799
|
+
- **Description:** Flask render_template_string rendering untrusted input
|
|
800
|
+
```
|
|
801
|
+
"severity": SeverityLevel.HIGH,
|
|
802
|
+
"path": "rules/TG-INPUT-005-unsafe-template-rendering-and-escaping.md",
|
|
803
|
+
"vuln_sample": "return render_template_string(f'<h1>Hello {name}</h1>')",
|
|
804
|
+
"hard_sample": "return render_template('hello.html', name=name)",
|
|
805
|
+
"remediation": "Pass inputs as context variables in autoescaped template files or use Django's format_html() to safely construct HTML wrappers.",
|
|
806
|
+
```
|
|
807
|
+
|
|
808
|
+
### [Low] TG-INPUT-005 - Unsafe Template Rendering & Disabled Autoescaping
|
|
809
|
+
- **Finding ID:** `TG-INPUT-005-d7ef73f1`
|
|
810
|
+
- **Location:** `harness/validate_e2e.py:457`
|
|
811
|
+
- **Confidence Score:** `54/100` (Medium Confidence)
|
|
812
|
+
- **Cluster:** `cluster-injection`
|
|
813
|
+
- **Description:** Flask render_template_string rendering untrusted input
|
|
814
|
+
```
|
|
815
|
+
"",
|
|
816
|
+
"- **`TG-AUTH-008` (Untrusted Role/Tenant Header Injection):** Verified detection on client headers (`X-User-Role`, `X-Tenant-ID`) and verified FastAPI/DRF JWT token extraction remediations.",
|
|
817
|
+
"- **`TG-INPUT-005` (Unsafe Template Rendering & Disabled Autoescaping):** Verified detection on `mark_safe()`, `| safe`, and `render_template_string()`; verified Jinja2 context variable autoescaping and `format_html()` remediations.",
|
|
818
|
+
"- **`TG-INPUT-006` (Path Traversal & Unsafe Upload Storage):** Verified detection on `os.path.join(UPLOAD_DIR, filename)`; verified `secure_filename()` + UUID storage remediations.",
|
|
819
|
+
"- **`TG-DB-004` (Missing Tenant Query Isolation):** Verified detection on unscoped primary key queries; verified SQLAlchemy composite tenant filters and DRF ViewSet `get_queryset()` tenant isolation.",
|
|
820
|
+
```
|
|
821
|
+
|
|
822
|
+
### [Low] TG-DB-004 - Missing Tenant Query Isolation in Multi-Tenant Models
|
|
823
|
+
- **Finding ID:** `TG-DB-004-9a2f13c7`
|
|
824
|
+
- **Location:** `harness/validate_v0_6_1_scale.py:115`
|
|
825
|
+
- **Confidence Score:** `54/100` (Medium Confidence)
|
|
826
|
+
- **Cluster:** `cluster-tenant-isolation`
|
|
827
|
+
- **Description:** Django ORM .get(id=...) query lacking explicit tenant scope filter
|
|
828
|
+
```
|
|
829
|
+
"severity": "High",
|
|
830
|
+
"target": {"file_path": "apps/django_core/billing/views.py", "line_start": 42, "line_end": 42},
|
|
831
|
+
"evidence": {"code_snippet": "Invoice.objects.get(id=inv_id)"},
|
|
832
|
+
},
|
|
833
|
+
# FastAPI Microservice
|
|
834
|
+
```
|
|
835
|
+
|
|
836
|
+
### [Low] TG-DB-004 - Missing Tenant Query Isolation in Multi-Tenant Models
|
|
837
|
+
- **Finding ID:** `TG-DB-004-a932f5b8`
|
|
838
|
+
- **Location:** `harness/validate_v0_6_1_scale.py:193`
|
|
839
|
+
- **Confidence Score:** `54/100` (Medium Confidence)
|
|
840
|
+
- **Cluster:** `cluster-tenant-isolation`
|
|
841
|
+
- **Description:** Django ORM .get(id=...) query lacking explicit tenant scope filter
|
|
842
|
+
```
|
|
843
|
+
"confidence_band": "Confirmed",
|
|
844
|
+
"target": {"file_path": f"services/api/module_{i % 15}/views.py", "line_start": 10 + i, "line_end": 12 + i},
|
|
845
|
+
"evidence": {"code_snippet": f"Model_{i}.objects.get(id=id)"},
|
|
846
|
+
})
|
|
847
|
+
|
|
848
|
+
```
|
|
849
|
+
|
|
850
|
+
### [Low] TG-DB-004 - Missing Tenant Query Isolation in Multi-Tenant Models
|
|
851
|
+
- **Finding ID:** `TG-DB-004-14a2d74f`
|
|
852
|
+
- **Location:** `harness/validate_v1_0_0_memory.py:265`
|
|
853
|
+
- **Confidence Score:** `54/100` (Medium Confidence)
|
|
854
|
+
- **Cluster:** `cluster-tenant-isolation`
|
|
855
|
+
- **Description:** Django ORM .get(id=...) query lacking explicit tenant scope filter
|
|
856
|
+
```
|
|
857
|
+
- return Bill.objects.filter(id=id, tenant=tenant)
|
|
858
|
+
+def get_bill(id):
|
|
859
|
+
+ return Bill.objects.get(id=id)
|
|
860
|
+
"""
|
|
861
|
+
res_reg = diff_guard.audit_diff(regression_diff, check_memory=True, root_dir=test_root)
|
|
862
|
+
```
|
|
863
|
+
|
|
864
|
+
### [Low] TG-SUPPLY-004 - Unpinned CI Action
|
|
865
|
+
- **Finding ID:** `TG-SUPPLY-004-e52415c0`
|
|
866
|
+
- **Location:** `harness/validate_v0_6_2_modern_stacks.py:383`
|
|
867
|
+
- **Confidence Score:** `52/100` (Medium Confidence)
|
|
868
|
+
- **Cluster:** `cluster-supply-chain`
|
|
869
|
+
- **Description:** GitHub Action referenced by mutable tag instead of immutable commit SHA
|
|
870
|
+
```
|
|
871
|
+
runs-on: ubuntu-latest
|
|
872
|
+
steps:
|
|
873
|
+
- uses: actions/checkout@v2
|
|
874
|
+
- run: make test
|
|
875
|
+
""", encoding="utf-8")
|
|
876
|
+
```
|
|
877
|
+
|
|
878
|
+
### [Low] TG-SUPPLY-004 - Unpinned CI Action
|
|
879
|
+
- **Finding ID:** `TG-SUPPLY-004-b9d15743`
|
|
880
|
+
- **Location:** `harness/validate_v0_6_2_modern_stacks.py:404`
|
|
881
|
+
- **Confidence Score:** `52/100` (Medium Confidence)
|
|
882
|
+
- **Cluster:** `cluster-supply-chain`
|
|
883
|
+
- **Description:** GitHub Action referenced by mutable tag instead of immutable commit SHA
|
|
884
|
+
```
|
|
885
|
+
+++ b/.github/workflows/ci.yml
|
|
886
|
+
@@ -6,1 +6,1 @@
|
|
887
|
+
- - uses: actions/checkout@v2
|
|
888
|
+
+ - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
|
|
889
|
+
""",
|
|
890
|
+
```
|
|
891
|
+
|
|
892
|
+
### [Low] TG-INPUT-005 - Unsafe Template Rendering & Disabled Autoescaping
|
|
893
|
+
- **Finding ID:** `TG-INPUT-005-95cb57ba`
|
|
894
|
+
- **Location:** `harness/engine/fixture_manager.py:176`
|
|
895
|
+
- **Confidence Score:** `51/100` (Medium Confidence)
|
|
896
|
+
- **Cluster:** `cluster-injection`
|
|
897
|
+
- **Description:** Flask render_template_string rendering untrusted input
|
|
898
|
+
```
|
|
899
|
+
vulnerable_variant=FixtureVariant(
|
|
900
|
+
relative_path="examples/python/flask-vuln",
|
|
901
|
+
code_pattern="render_template_string(f'<h1>Hello {name}</h1>')",
|
|
902
|
+
expected_findings_count=1,
|
|
903
|
+
),
|
|
904
|
+
```
|
|
905
|
+
|
|
906
|
+
### [Low] TG-SUPPLY-004 - Unpinned CI Action
|
|
907
|
+
- **Finding ID:** `TG-SUPPLY-004-9240a873`
|
|
908
|
+
- **Location:** `harness/validate_v0_6_3_hardening.py:251`
|
|
909
|
+
- **Confidence Score:** `49/100` (Needs Review)
|
|
910
|
+
- **Cluster:** `cluster-supply-chain`
|
|
911
|
+
- **Description:** GitHub Action referenced by mutable tag instead of immutable commit SHA
|
|
912
|
+
```
|
|
913
|
+
+++ b/.github/workflows/deploy.yml
|
|
914
|
+
@@ -5,1 +5,2 @@
|
|
915
|
+
- - uses: actions/checkout@v2
|
|
916
|
+
+ - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29
|
|
917
|
+
+ with: { persist-credentials: false }
|
|
918
|
+
```
|
|
919
|
+
|
|
920
|
+
### [Low] TG-DIFF-003 - Unintentional Removal of Tenant Filter in Patch Deletions
|
|
921
|
+
- **Finding ID:** `TG-DIFF-003-3d00a189`
|
|
922
|
+
- **Location:** `harness/validate_v0_6_2_modern_stacks.py:262`
|
|
923
|
+
- **Confidence Score:** `44/100` (Needs Review)
|
|
924
|
+
- **Cluster:** `cluster-tenant-isolation`
|
|
925
|
+
- **Description:** Removal of tenant isolation boundary in patch deletion
|
|
926
|
+
```
|
|
927
|
+
+++ b/queries.py
|
|
928
|
+
@@ -7,1 +7,1 @@
|
|
929
|
+
- stmt = select(Account).where(Account.id == account_id)
|
|
930
|
+
+ stmt = select(Account).where(Account.id == account_id, Account.tenant_id == tenant_id)
|
|
931
|
+
""",
|
|
932
|
+
```
|
|
933
|
+
|
|
934
|
+
### [Low] TG-DB-004 - Missing Tenant Query Isolation in Multi-Tenant Models
|
|
935
|
+
- **Finding ID:** `TG-DB-004-6a739666`
|
|
936
|
+
- **Location:** `tests/test_v0_6_0_governed_remediation.py:79`
|
|
937
|
+
- **Confidence Score:** `24/100` (Needs Review)
|
|
938
|
+
- **Cluster:** `cluster-tenant-isolation`
|
|
939
|
+
- **Description:** Django ORM .get(id=...) query lacking explicit tenant scope filter
|
|
940
|
+
```
|
|
941
|
+
def get_invoice(request, invoice_id):
|
|
942
|
+
# Fetch invoice directly without tenant filter
|
|
943
|
+
invoice = Invoice.objects.get(id=invoice_id)
|
|
944
|
+
return JsonResponse({"id": invoice.id})
|
|
945
|
+
"""
|
|
946
|
+
```
|
|
947
|
+
|
|
948
|
+
### [Low] TG-DB-004 - Missing Tenant Query Isolation in Multi-Tenant Models
|
|
949
|
+
- **Finding ID:** `TG-DB-004-fe2c60e3`
|
|
950
|
+
- **Location:** `tests/test_v0_6_0_governed_remediation.py:86`
|
|
951
|
+
- **Confidence Score:** `24/100` (Needs Review)
|
|
952
|
+
- **Cluster:** `cluster-tenant-isolation`
|
|
953
|
+
- **Description:** Django ORM .get(id=...) query lacking explicit tenant scope filter
|
|
954
|
+
```
|
|
955
|
+
# Lines shifted down by 10 lines
|
|
956
|
+
def get_invoice(request, invoice_id):
|
|
957
|
+
invoice = Invoice.objects.get(id=invoice_id)
|
|
958
|
+
return JsonResponse({"id": invoice.id})
|
|
959
|
+
"""
|
|
960
|
+
```
|