@hoanghainh/komagu 2.0.0 → 2.1.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.
Files changed (143) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/README.md +1 -1
  3. package/assess/lsa/examples/eval-run-4/ground-truth.json +823 -0
  4. package/assess/lsa/examples/eval-run-4/iter0-gptoss-a/ai-run-stats.json +58 -0
  5. package/assess/lsa/examples/eval-run-4/iter0-gptoss-a/coverage.json +85 -0
  6. package/assess/lsa/examples/eval-run-4/iter0-gptoss-a/findings/priv-privilege-001.json +822 -0
  7. package/assess/lsa/examples/eval-run-4/iter0-gptoss-a/findings/priv-privilege-002.json +393 -0
  8. package/assess/lsa/examples/eval-run-4/iter0-gptoss-a/findings.json +4477 -0
  9. package/assess/lsa/examples/eval-run-4/iter0-gptoss-a/mass-assignment.candidates.json +232 -0
  10. package/assess/lsa/examples/eval-run-4/iter0-gptoss-a/routes/routes-001.json +425 -0
  11. package/assess/lsa/examples/eval-run-4/iter0-gptoss-a/routes/routes-002.json +333 -0
  12. package/assess/lsa/examples/eval-run-4/iter0-gptoss-a/routes/routes-003.json +400 -0
  13. package/assess/lsa/examples/eval-run-4/iter0-gptoss-a/routes/routes-004.json +403 -0
  14. package/assess/lsa/examples/eval-run-4/iter0-gptoss-a/routes/routes-005.json +398 -0
  15. package/assess/lsa/examples/eval-run-4/iter0-gptoss-a/routes/routes-006.json +63 -0
  16. package/assess/lsa/examples/eval-run-4/iter0-gptoss-a/score.json +120 -0
  17. package/assess/lsa/examples/eval-run-4/iter1-gptoss-a/ai-run-stats.json +55 -0
  18. package/assess/lsa/examples/eval-run-4/iter1-gptoss-a/coverage.json +50 -0
  19. package/assess/lsa/examples/eval-run-4/iter1-gptoss-a/findings/priv-privilege-001.json +613 -0
  20. package/assess/lsa/examples/eval-run-4/iter1-gptoss-a/findings/priv-privilege-002.json +287 -0
  21. package/assess/lsa/examples/eval-run-4/iter1-gptoss-a/findings.json +4870 -0
  22. package/assess/lsa/examples/eval-run-4/iter1-gptoss-a/mass-assignment.candidates.json +232 -0
  23. package/assess/lsa/examples/eval-run-4/iter1-gptoss-a/routes/routes-001.json +425 -0
  24. package/assess/lsa/examples/eval-run-4/iter1-gptoss-a/routes/routes-002.json +333 -0
  25. package/assess/lsa/examples/eval-run-4/iter1-gptoss-a/routes/routes-003.json +400 -0
  26. package/assess/lsa/examples/eval-run-4/iter1-gptoss-a/routes/routes-004.json +403 -0
  27. package/assess/lsa/examples/eval-run-4/iter1-gptoss-a/routes/routes-005.json +398 -0
  28. package/assess/lsa/examples/eval-run-4/iter1-gptoss-a/routes/routes-006.json +63 -0
  29. package/assess/lsa/examples/eval-run-4/iter1-gptoss-a/score.json +107 -0
  30. package/assess/lsa/examples/eval-run-4/iter1-gptoss-b/ai-run-stats.json +58 -0
  31. package/assess/lsa/examples/eval-run-4/iter1-gptoss-b/coverage.json +92 -0
  32. package/assess/lsa/examples/eval-run-4/iter1-gptoss-b/findings/priv-privilege-001.json +645 -0
  33. package/assess/lsa/examples/eval-run-4/iter1-gptoss-b/findings/priv-privilege-002.json +222 -0
  34. package/assess/lsa/examples/eval-run-4/iter1-gptoss-b/findings.json +4859 -0
  35. package/assess/lsa/examples/eval-run-4/iter1-gptoss-b/mass-assignment.candidates.json +232 -0
  36. package/assess/lsa/examples/eval-run-4/iter1-gptoss-b/routes/routes-001.json +425 -0
  37. package/assess/lsa/examples/eval-run-4/iter1-gptoss-b/routes/routes-002.json +333 -0
  38. package/assess/lsa/examples/eval-run-4/iter1-gptoss-b/routes/routes-003.json +400 -0
  39. package/assess/lsa/examples/eval-run-4/iter1-gptoss-b/routes/routes-004.json +403 -0
  40. package/assess/lsa/examples/eval-run-4/iter1-gptoss-b/routes/routes-005.json +398 -0
  41. package/assess/lsa/examples/eval-run-4/iter1-gptoss-b/routes/routes-006.json +63 -0
  42. package/assess/lsa/examples/eval-run-4/iter1-gptoss-b/score.json +121 -0
  43. package/assess/lsa/examples/eval-run-4/iter1-qwen-a-incomplete/coverage.json +111 -0
  44. package/assess/lsa/examples/eval-run-4/iter1-qwen-a-incomplete/findings/priv-privilege-001.json +6 -0
  45. package/assess/lsa/examples/eval-run-4/iter1-qwen-a-incomplete/findings/priv-privilege-002.json +344 -0
  46. package/assess/lsa/examples/eval-run-4/iter1-qwen-a-incomplete/findings.json +3544 -0
  47. package/assess/lsa/examples/eval-run-4/iter1-qwen-a-incomplete/mass-assignment.candidates.json +232 -0
  48. package/assess/lsa/examples/eval-run-4/iter1-qwen-a-incomplete/routes/routes-001.json +425 -0
  49. package/assess/lsa/examples/eval-run-4/iter1-qwen-a-incomplete/routes/routes-002.json +333 -0
  50. package/assess/lsa/examples/eval-run-4/iter1-qwen-a-incomplete/routes/routes-003.json +400 -0
  51. package/assess/lsa/examples/eval-run-4/iter1-qwen-a-incomplete/routes/routes-004.json +403 -0
  52. package/assess/lsa/examples/eval-run-4/iter1-qwen-a-incomplete/routes/routes-005.json +398 -0
  53. package/assess/lsa/examples/eval-run-4/iter1-qwen-a-incomplete/routes/routes-006.json +63 -0
  54. package/assess/lsa/examples/eval-run-4/iter1-qwen-a-incomplete/score.json +123 -0
  55. package/assess/lsa/examples/eval-run-4/iter2-gptoss-a/ai-run-stats.json +50 -0
  56. package/assess/lsa/examples/eval-run-4/iter2-gptoss-a/coverage.json +42 -0
  57. package/assess/lsa/examples/eval-run-4/iter2-gptoss-a/findings/priv-privilege-001.json +540 -0
  58. package/assess/lsa/examples/eval-run-4/iter2-gptoss-a/findings/priv-privilege-002.json +238 -0
  59. package/assess/lsa/examples/eval-run-4/iter2-gptoss-a/findings.json +4383 -0
  60. package/assess/lsa/examples/eval-run-4/iter2-gptoss-a/findings.sarif +8729 -0
  61. package/assess/lsa/examples/eval-run-4/iter2-gptoss-a/mass-assignment.candidates.json +232 -0
  62. package/assess/lsa/examples/eval-run-4/iter2-gptoss-a/report.ja.md +1911 -0
  63. package/assess/lsa/examples/eval-run-4/iter2-gptoss-a/report.md +1911 -0
  64. package/assess/lsa/examples/eval-run-4/iter2-gptoss-a/routes/routes-001.json +425 -0
  65. package/assess/lsa/examples/eval-run-4/iter2-gptoss-a/routes/routes-002.json +333 -0
  66. package/assess/lsa/examples/eval-run-4/iter2-gptoss-a/routes/routes-003.json +400 -0
  67. package/assess/lsa/examples/eval-run-4/iter2-gptoss-a/routes/routes-004.json +403 -0
  68. package/assess/lsa/examples/eval-run-4/iter2-gptoss-a/routes/routes-005.json +398 -0
  69. package/assess/lsa/examples/eval-run-4/iter2-gptoss-a/routes/routes-006.json +63 -0
  70. package/assess/lsa/examples/eval-run-4/iter2-gptoss-a/score.json +101 -0
  71. package/assess/lsa/examples/eval-run-4/iter2-gptoss-a/stack-profile.json +226 -0
  72. package/assess/lsa/examples/eval-run-4/iter2-gptoss-b/ai-run-stats.json +54 -0
  73. package/assess/lsa/examples/eval-run-4/iter2-gptoss-b/coverage.json +66 -0
  74. package/assess/lsa/examples/eval-run-4/iter2-gptoss-b/findings/priv-privilege-001.json +440 -0
  75. package/assess/lsa/examples/eval-run-4/iter2-gptoss-b/findings/priv-privilege-002.json +229 -0
  76. package/assess/lsa/examples/eval-run-4/iter2-gptoss-b/findings.json +3424 -0
  77. package/assess/lsa/examples/eval-run-4/iter2-gptoss-b/mass-assignment.candidates.json +232 -0
  78. package/assess/lsa/examples/eval-run-4/iter2-gptoss-b/routes/routes-001.json +425 -0
  79. package/assess/lsa/examples/eval-run-4/iter2-gptoss-b/routes/routes-002.json +333 -0
  80. package/assess/lsa/examples/eval-run-4/iter2-gptoss-b/routes/routes-003.json +400 -0
  81. package/assess/lsa/examples/eval-run-4/iter2-gptoss-b/routes/routes-004.json +403 -0
  82. package/assess/lsa/examples/eval-run-4/iter2-gptoss-b/routes/routes-005.json +398 -0
  83. package/assess/lsa/examples/eval-run-4/iter2-gptoss-b/routes/routes-006.json +63 -0
  84. package/assess/lsa/examples/eval-run-4/iter2-gptoss-b/score.json +120 -0
  85. package/assess/lsa/examples/eval-run-5/gptoss-a/ai-run-stats.json +88 -0
  86. package/assess/lsa/examples/eval-run-5/gptoss-a/coverage.json +36 -0
  87. package/assess/lsa/examples/eval-run-5/gptoss-a/findings/priv-privilege-001.json +530 -0
  88. package/assess/lsa/examples/eval-run-5/gptoss-a/findings/priv-privilege-002.json +248 -0
  89. package/assess/lsa/examples/eval-run-5/gptoss-a/findings.json +4766 -0
  90. package/assess/lsa/examples/eval-run-5/gptoss-a/findings.sarif +9326 -0
  91. package/assess/lsa/examples/eval-run-5/gptoss-a/mass-assignment.candidates.json +232 -0
  92. package/assess/lsa/examples/eval-run-5/gptoss-a/report.ja.md +2011 -0
  93. package/assess/lsa/examples/eval-run-5/gptoss-a/report.md +2011 -0
  94. package/assess/lsa/examples/eval-run-5/gptoss-a/routes/routes-001.json +425 -0
  95. package/assess/lsa/examples/eval-run-5/gptoss-a/routes/routes-002.json +333 -0
  96. package/assess/lsa/examples/eval-run-5/gptoss-a/routes/routes-003.json +400 -0
  97. package/assess/lsa/examples/eval-run-5/gptoss-a/routes/routes-004.json +403 -0
  98. package/assess/lsa/examples/eval-run-5/gptoss-a/routes/routes-005.json +398 -0
  99. package/assess/lsa/examples/eval-run-5/gptoss-a/routes/routes-006.json +63 -0
  100. package/assess/lsa/examples/eval-run-5/gptoss-a/score.json +80 -0
  101. package/assess/lsa/examples/eval-run-5/gptoss-a/stack-profile.json +226 -0
  102. package/assess/lsa/examples/eval-run-5/gptoss-b/ai-run-stats.json +83 -0
  103. package/assess/lsa/examples/eval-run-5/gptoss-b/coverage.json +44 -0
  104. package/assess/lsa/examples/eval-run-5/gptoss-b/findings/priv-privilege-001.json +579 -0
  105. package/assess/lsa/examples/eval-run-5/gptoss-b/findings/priv-privilege-002.json +268 -0
  106. package/assess/lsa/examples/eval-run-5/gptoss-b/findings.json +3913 -0
  107. package/assess/lsa/examples/eval-run-5/gptoss-b/mass-assignment.candidates.json +232 -0
  108. package/assess/lsa/examples/eval-run-5/gptoss-b/routes/routes-001.json +425 -0
  109. package/assess/lsa/examples/eval-run-5/gptoss-b/routes/routes-002.json +333 -0
  110. package/assess/lsa/examples/eval-run-5/gptoss-b/routes/routes-003.json +400 -0
  111. package/assess/lsa/examples/eval-run-5/gptoss-b/routes/routes-004.json +403 -0
  112. package/assess/lsa/examples/eval-run-5/gptoss-b/routes/routes-005.json +398 -0
  113. package/assess/lsa/examples/eval-run-5/gptoss-b/routes/routes-006.json +63 -0
  114. package/assess/lsa/examples/eval-run-5/gptoss-b/score.json +94 -0
  115. package/assess/lsa/examples/eval-run-5/ground-truth.json +823 -0
  116. package/assess/lsa/knowledge/injection-patterns.md +8 -1
  117. package/assess/lsa/knowledge/stacks/nextjs.md +62 -0
  118. package/assess/lsa/prompts/35-privilege-auditor.md +3 -1
  119. package/assess/lsa/prompts/_shared-rules.md +1 -0
  120. package/assess/lsa/scripts/detect_stack.py +5 -1
  121. package/assess/lsa/scripts/find_injection.py +34 -5
  122. package/assess/lsa/scripts/lsa_common.py +9 -2
  123. package/assess/lsa/scripts/make_batches.py +2 -1
  124. package/assess/lsa/scripts/map_routes.py +10 -2
  125. package/assess/lsa/scripts/nextjs_routes.py +236 -0
  126. package/assess/lsa/templates/audit-config.json +1 -1
  127. package/assess/lsa/tests/EVAL-RESULTS.md +156 -0
  128. package/assess/lsa/tests/score_findings.py +58 -0
  129. package/assess/lsa/tests/test_default_scope.py +86 -0
  130. package/assess/lsa/tests/test_eval_run_4.py +73 -0
  131. package/assess/lsa/tests/test_eval_run_5.py +73 -0
  132. package/assess/lsa/tests/test_js_tagged_sql.py +112 -0
  133. package/assess/lsa/tests/test_nextjs.py +198 -0
  134. package/assess/lsa/tests/test_privilege_tier2.py +30 -0
  135. package/operate/ai/anchoring.py +130 -0
  136. package/operate/ai/client.py +13 -0
  137. package/operate/ai/context.py +105 -0
  138. package/operate/ai/runner.py +197 -69
  139. package/operate/cli/__init__.py +1 -1
  140. package/operate/cli/commands/scan.py +1 -1
  141. package/operate/tests/test_ai_anchoring.py +184 -0
  142. package/operate/tests/test_headless_ai.py +148 -1
  143. package/package.json +1 -1
@@ -0,0 +1,822 @@
1
+ {
2
+ "batch_id": "privilege-001",
3
+ "findings": [
4
+ {
5
+ "finding_id": "BFLA-0003-1",
6
+ "category": "bfla",
7
+ "subtype": "missing_role_check",
8
+ "title": "Classic\u2011ASP member deletion without role check",
9
+ "route_id": "R-0003",
10
+ "endpoint": {
11
+ "method": "GET|POST",
12
+ "path": "/classic-asp/shop/member.asp?mode=delete"
13
+ },
14
+ "location": {
15
+ "file": "classic-asp/shop/member.asp",
16
+ "start_line": 1,
17
+ "end_line": 11
18
+ },
19
+ "evidence": [
20
+ {
21
+ "file": "classic-asp/shop/member.asp",
22
+ "line": 1,
23
+ "code": "<!--#include file=\"inc/auth.asp\"-->",
24
+ "why": "auth guard only checks session, no role"
25
+ },
26
+ {
27
+ "file": "classic-asp/shop/member.asp",
28
+ "line": 10,
29
+ "code": "conn.Execute \"DELETE FROM members WHERE member_id = \" & Request.QueryString(\"member_id\")",
30
+ "why": "privileged action, no role check"
31
+ }
32
+ ],
33
+ "attack_scenario": "A logged\u2011in user can delete any member by supplying a member_id in the query string.",
34
+ "impact": "Any authenticated user can delete arbitrary members, including administrators.",
35
+ "severity": "critical",
36
+ "confidence": "high",
37
+ "cwe": [
38
+ "CWE-285"
39
+ ],
40
+ "owasp": [
41
+ "API5:2023"
42
+ ],
43
+ "recommendation": "Add a server\u2011side role check that ensures the current user has the 'Admin' role before executing the delete.",
44
+ "fix_example": "If Not CheckRole(\"Admin\") Then Response.Status = \"403 Forbidden\" : Response.End",
45
+ "status": "unverified"
46
+ },
47
+ {
48
+ "finding_id": "BFLA-0007-1",
49
+ "category": "bfla",
50
+ "subtype": "missing_role_check",
51
+ "title": "ASP.NET MVC DeleteUser action lacks admin role check",
52
+ "route_id": "R-0007",
53
+ "endpoint": {
54
+ "method": "POST",
55
+ "path": "/Admin/DeleteUser"
56
+ },
57
+ "location": {
58
+ "file": "Web/Controllers/AdminController.cs",
59
+ "start_line": 6,
60
+ "end_line": 18
61
+ },
62
+ "evidence": [
63
+ {
64
+ "file": "Web/Controllers/AdminController.cs",
65
+ "line": 6,
66
+ "code": "[Authorize]",
67
+ "why": "ensures authentication only"
68
+ },
69
+ {
70
+ "file": "Web/Controllers/AdminController.cs",
71
+ "line": 12,
72
+ "code": "public ActionResult DeleteUser(int id)",
73
+ "why": "no role check on method"
74
+ }
75
+ ],
76
+ "attack_scenario": "Any authenticated user can delete any user account.",
77
+ "impact": "Privilege escalation to delete arbitrary user accounts.",
78
+ "severity": "critical",
79
+ "confidence": "high",
80
+ "cwe": [
81
+ "CWE-285"
82
+ ],
83
+ "owasp": [
84
+ "API5:2023"
85
+ ],
86
+ "recommendation": "Add [Authorize(Roles = \"Admin\")] to the DeleteUser action.",
87
+ "fix_example": "[Authorize(Roles = \"Admin\")] public ActionResult DeleteUser(int id) { \u2026 }",
88
+ "status": "unverified"
89
+ },
90
+ {
91
+ "finding_id": "BFLA-0009-1",
92
+ "category": "bfla",
93
+ "subtype": "role_from_request",
94
+ "title": "ASP.NET MVC Export action trusts request query for admin access",
95
+ "route_id": "R-0009",
96
+ "endpoint": {
97
+ "method": "GET",
98
+ "path": "/Admin/Export"
99
+ },
100
+ "location": {
101
+ "file": "Web/Controllers/AdminController.cs",
102
+ "start_line": 30,
103
+ "end_line": 37
104
+ },
105
+ "evidence": [
106
+ {
107
+ "file": "Web/Controllers/AdminController.cs",
108
+ "line": 32,
109
+ "code": "if (Request.QueryString[\"isAdmin\"] == \"true\") { \u2026 }",
110
+ "why": "role derived from client request"
111
+ }
112
+ ],
113
+ "attack_scenario": "A logged\u2011in user can set ?isAdmin=true to export all users.",
114
+ "impact": "Unauthorized data export of all user records.",
115
+ "severity": "critical",
116
+ "confidence": "high",
117
+ "cwe": [
118
+ "CWE-269",
119
+ "CWE-285"
120
+ ],
121
+ "owasp": [
122
+ "API5:2023"
123
+ ],
124
+ "recommendation": "Remove reliance on client query and enforce server\u2011side role check.",
125
+ "fix_example": "if (!User.IsInRole(\"Admin\")) { return new HttpStatusCodeResult(403); }",
126
+ "status": "unverified"
127
+ },
128
+ {
129
+ "finding_id": "BFLA-0023-1",
130
+ "category": "bfla",
131
+ "subtype": "missing_role_check",
132
+ "title": "Spring MVC delete user action missing admin role check",
133
+ "route_id": "R-0023",
134
+ "endpoint": {
135
+ "method": "POST",
136
+ "path": "/admin/users/{id}/delete"
137
+ },
138
+ "location": {
139
+ "file": "src/main/java/com/acme/web/AdminUserController.java",
140
+ "start_line": 13,
141
+ "end_line": 17
142
+ },
143
+ "evidence": [
144
+ {
145
+ "file": "src/main/java/com/acme/web/AdminUserController.java",
146
+ "line": 13,
147
+ "code": "@RequestMapping(value = \"/{id}/delete\", method = RequestMethod.POST)",
148
+ "why": "no @PreAuthorize on method"
149
+ }
150
+ ],
151
+ "attack_scenario": "Any authenticated user can delete any user account.",
152
+ "impact": "Privilege escalation to delete arbitrary user accounts.",
153
+ "severity": "critical",
154
+ "confidence": "high",
155
+ "cwe": [
156
+ "CWE-285"
157
+ ],
158
+ "owasp": [
159
+ "API5:2023"
160
+ ],
161
+ "recommendation": "Add @PreAuthorize(\"hasRole('ADMIN')\") to the delete method.",
162
+ "fix_example": "@PreAuthorize(\"hasRole('ADMIN')\") @RequestMapping(value = \"/{id}/delete\", method = RequestMethod.POST) public String delete(@PathVariable(\"id\") Long id) { \u2026 }",
163
+ "status": "unverified"
164
+ },
165
+ {
166
+ "finding_id": "BFLA-0030-1",
167
+ "category": "bfla",
168
+ "subtype": "missing_role_check",
169
+ "title": "Express admin delete user route missing admin guard",
170
+ "route_id": "R-0030",
171
+ "endpoint": {
172
+ "method": "POST",
173
+ "path": "/admin/users/:id/delete"
174
+ },
175
+ "location": {
176
+ "file": "routes/admin.js",
177
+ "start_line": 8,
178
+ "end_line": 10
179
+ },
180
+ "evidence": [
181
+ {
182
+ "file": "routes/admin.js",
183
+ "line": 8,
184
+ "code": "router.post('/admin/users/:id/delete', ensureLoggedIn, function (req, res) { \u2026 }",
185
+ "why": "only ensures login, no admin check"
186
+ }
187
+ ],
188
+ "attack_scenario": "Any logged\u2011in user can delete any user account.",
189
+ "impact": "Privilege escalation to delete arbitrary user accounts.",
190
+ "severity": "critical",
191
+ "confidence": "high",
192
+ "cwe": [
193
+ "CWE-285"
194
+ ],
195
+ "owasp": [
196
+ "API5:2023"
197
+ ],
198
+ "recommendation": "Add an admin guard middleware before the handler.",
199
+ "fix_example": "router.post('/admin/users/:id/delete', ensureLoggedIn, requireAdmin, function (req, res) { \u2026 }",
200
+ "status": "unverified"
201
+ },
202
+ {
203
+ "finding_id": "BFLA-0032-1",
204
+ "category": "bfla",
205
+ "subtype": "role_from_request",
206
+ "title": "Express export route trusts client query for admin access",
207
+ "route_id": "R-0032",
208
+ "endpoint": {
209
+ "method": "GET",
210
+ "path": "/reports/export"
211
+ },
212
+ "location": {
213
+ "file": "routes/admin.js",
214
+ "start_line": 16,
215
+ "end_line": 18
216
+ },
217
+ "evidence": [
218
+ {
219
+ "file": "routes/admin.js",
220
+ "line": 17,
221
+ "code": "if (req.query.isAdmin === 'true') { res.json([]); }",
222
+ "why": "role derived from client query"
223
+ }
224
+ ],
225
+ "attack_scenario": "Any logged\u2011in user can export all user data by setting ?isAdmin=true.",
226
+ "impact": "Unauthorized data export of all user records.",
227
+ "severity": "critical",
228
+ "confidence": "high",
229
+ "cwe": [
230
+ "CWE-269",
231
+ "CWE-285"
232
+ ],
233
+ "owasp": [
234
+ "API5:2023"
235
+ ],
236
+ "recommendation": "Remove client\u2011controlled isAdmin flag and enforce server\u2011side role check.",
237
+ "fix_example": "if (!req.user.isAdmin) { return res.sendStatus(403); }",
238
+ "status": "unverified"
239
+ },
240
+ {
241
+ "finding_id": "BFLA-0057-1",
242
+ "category": "bfla",
243
+ "subtype": "missing_role_check",
244
+ "title": "PHP admin view user without role check",
245
+ "route_id": "R-0057",
246
+ "endpoint": {
247
+ "method": "GET",
248
+ "path": "/php-plain/admin.php?action=view"
249
+ },
250
+ "location": {
251
+ "file": "php-plain/admin.php",
252
+ "start_line": 5,
253
+ "end_line": 9
254
+ },
255
+ "evidence": [
256
+ {
257
+ "file": "php-plain/admin.php",
258
+ "line": 6,
259
+ "code": "case 'view': $uid = (int)$_GET['uid']; $r = mysql_query(\"SELECT * FROM users WHERE id = \" . $uid);",
260
+ "why": "privileged action, no role check"
261
+ }
262
+ ],
263
+ "attack_scenario": "A logged\u2011in user can view any user record by supplying a uid.",
264
+ "impact": "Unauthorized disclosure of arbitrary user data.",
265
+ "severity": "critical",
266
+ "confidence": "high",
267
+ "cwe": [
268
+ "CWE-285"
269
+ ],
270
+ "owasp": [
271
+ "API5:2023"
272
+ ],
273
+ "recommendation": "Add a role check that ensures the current user is an administrator before executing the query.",
274
+ "fix_example": "if ($_SESSION['role'] !== 'admin') { http_response_code(403); exit; }",
275
+ "status": "unverified"
276
+ },
277
+ {
278
+ "finding_id": "BFLA-0058-1",
279
+ "category": "bfla",
280
+ "subtype": "missing_role_check",
281
+ "title": "PHP admin delete user without role check",
282
+ "route_id": "R-0058",
283
+ "endpoint": {
284
+ "method": "POST",
285
+ "path": "/php-plain/admin.php?action=delete"
286
+ },
287
+ "location": {
288
+ "file": "php-plain/admin.php",
289
+ "start_line": 10,
290
+ "end_line": 13
291
+ },
292
+ "evidence": [
293
+ {
294
+ "file": "php-plain/admin.php",
295
+ "line": 10,
296
+ "code": "case 'delete': $id = $_POST['id']; mysql_query(\"DELETE FROM users WHERE id = $id\");",
297
+ "why": "privileged action, no role check"
298
+ }
299
+ ],
300
+ "attack_scenario": "A logged\u2011in user can delete any user record by posting an id.",
301
+ "impact": "Privilege escalation to delete arbitrary user accounts.",
302
+ "severity": "critical",
303
+ "confidence": "high",
304
+ "cwe": [
305
+ "CWE-285"
306
+ ],
307
+ "owasp": [
308
+ "API5:2023"
309
+ ],
310
+ "recommendation": "Add a role check that ensures the current user is an administrator before executing the delete.",
311
+ "fix_example": "if ($_SESSION['role'] !== 'admin') { http_response_code(403); exit; }",
312
+ "status": "unverified"
313
+ },
314
+ {
315
+ "finding_id": "BFLA-0066-1",
316
+ "category": "bfla",
317
+ "subtype": "missing_role_check",
318
+ "title": "PHP admin delete user without role check",
319
+ "route_id": "R-0066",
320
+ "endpoint": {
321
+ "method": "POST",
322
+ "path": "/php-plain/admin/delete_user.php"
323
+ },
324
+ "location": {
325
+ "file": "php-plain/admin/delete_user.php",
326
+ "start_line": 1,
327
+ "end_line": 8
328
+ },
329
+ "evidence": [
330
+ {
331
+ "file": "php-plain/admin/delete_user.php",
332
+ "line": 5,
333
+ "code": "$id = (int)$_POST['id']; $stmt = $db->prepare(\"DELETE FROM users WHERE id = ?\");",
334
+ "why": "privileged action, no role check"
335
+ }
336
+ ],
337
+ "attack_scenario": "A logged\u2011in user can delete any user record by posting an id.",
338
+ "impact": "Privilege escalation to delete arbitrary user accounts.",
339
+ "severity": "critical",
340
+ "confidence": "high",
341
+ "cwe": [
342
+ "CWE-285"
343
+ ],
344
+ "owasp": [
345
+ "API5:2023"
346
+ ],
347
+ "recommendation": "Add a role check that ensures the current user is an administrator before executing the delete.",
348
+ "fix_example": "if ($_SESSION['role'] !== 'admin') { http_response_code(403); exit; }",
349
+ "status": "unverified"
350
+ },
351
+ {
352
+ "finding_id": "BFLA-0067-1",
353
+ "category": "bfla",
354
+ "subtype": "role_from_request",
355
+ "title": "PHP admin promote user trusts client input for role change",
356
+ "route_id": "R-0067",
357
+ "endpoint": {
358
+ "method": "POST",
359
+ "path": "/php-plain/admin/promote.php"
360
+ },
361
+ "location": {
362
+ "file": "php-plain/admin/promote.php",
363
+ "start_line": 5,
364
+ "end_line": 8
365
+ },
366
+ "evidence": [
367
+ {
368
+ "file": "php-plain/admin/promote.php",
369
+ "line": 5,
370
+ "code": "if ($_POST['is_admin'] == '1') { $stmt = $db->prepare(\"UPDATE users SET role = 'admin' WHERE id = ?\");",
371
+ "why": "role derived from client request"
372
+ }
373
+ ],
374
+ "attack_scenario": "A logged\u2011in user can promote themselves to admin by posting is_admin=1.",
375
+ "impact": "Privilege escalation to admin role.",
376
+ "severity": "critical",
377
+ "confidence": "high",
378
+ "cwe": [
379
+ "CWE-269",
380
+ "CWE-285"
381
+ ],
382
+ "owasp": [
383
+ "API5:2023"
384
+ ],
385
+ "recommendation": "Remove client\u2011controlled role assignment and enforce server\u2011side role check.",
386
+ "fix_example": "if ($_SESSION['role'] !== 'admin') { http_response_code(403); exit; }",
387
+ "status": "unverified"
388
+ },
389
+ {
390
+ "finding_id": "BFLA-0067-2",
391
+ "category": "bfla",
392
+ "subtype": "missing_role_check",
393
+ "title": "PHP admin promote user missing role check",
394
+ "route_id": "R-0067",
395
+ "endpoint": {
396
+ "method": "POST",
397
+ "path": "/php-plain/admin/promote.php"
398
+ },
399
+ "location": {
400
+ "file": "php-plain/admin/promote.php",
401
+ "start_line": 1,
402
+ "end_line": 8
403
+ },
404
+ "evidence": [
405
+ {
406
+ "file": "php-plain/admin/promote.php",
407
+ "line": 1,
408
+ "code": "<?php require_once '../inc/auth.php'; require_once '../inc/db.php';",
409
+ "why": "auth guard only checks session, no role"
410
+ }
411
+ ],
412
+ "attack_scenario": "A logged\u2011in user can promote themselves to admin by posting is_admin=1.",
413
+ "impact": "Privilege escalation to admin role.",
414
+ "severity": "critical",
415
+ "confidence": "high",
416
+ "cwe": [
417
+ "CWE-285"
418
+ ],
419
+ "owasp": [
420
+ "API5:2023"
421
+ ],
422
+ "recommendation": "Add a server\u2011side role check before executing the role update.",
423
+ "fix_example": "if ($_SESSION['role'] !== 'admin') { http_response_code(403); exit; }",
424
+ "status": "unverified"
425
+ },
426
+ {
427
+ "finding_id": "BFLA-0059-1",
428
+ "category": "bfla",
429
+ "subtype": "client_side_role_check",
430
+ "title": "PHP manage users page uses client\u2011side role check for delete link",
431
+ "route_id": "R-0059",
432
+ "endpoint": {
433
+ "method": "GET",
434
+ "path": "/php-plain/manage_users.php"
435
+ },
436
+ "location": {
437
+ "file": "php-plain/manage_users.php",
438
+ "start_line": 10,
439
+ "end_line": 12
440
+ },
441
+ "evidence": [
442
+ {
443
+ "file": "php-plain/manage_users.php",
444
+ "line": 11,
445
+ "code": "<?php if ($_SESSION['role'] == 'admin'): ?><li><a href=\"/manage_users.php\">Delete users</a></li><?php endif; ?>",
446
+ "why": "role check only in markup, not enforced server\u2011side"
447
+ }
448
+ ],
449
+ "attack_scenario": "A logged\u2011in user can submit a delete request even if the link is not shown.",
450
+ "impact": "Privilege escalation to delete arbitrary user accounts.",
451
+ "severity": "critical",
452
+ "confidence": "high",
453
+ "cwe": [
454
+ "CWE-602",
455
+ "CWE-285"
456
+ ],
457
+ "owasp": [
458
+ "API5:2023"
459
+ ],
460
+ "recommendation": "Enforce role check on the delete handler, not just in the UI.",
461
+ "fix_example": "if ($_SESSION['role'] !== 'admin') { http_response_code(403); exit; }",
462
+ "status": "unverified"
463
+ },
464
+ {
465
+ "finding_id": "BFLA-0063-1",
466
+ "category": "bfla",
467
+ "subtype": "role_from_request",
468
+ "title": "PHP profile update allows client to set role",
469
+ "route_id": "R-0063",
470
+ "endpoint": {
471
+ "method": "POST",
472
+ "path": "/php-plain/profile.php"
473
+ },
474
+ "location": {
475
+ "file": "php-plain/profile.php",
476
+ "start_line": 6,
477
+ "end_line": 11
478
+ },
479
+ "evidence": [
480
+ {
481
+ "file": "php-plain/profile.php",
482
+ "line": 10,
483
+ "code": "$user->role = $_POST['role'];",
484
+ "why": "role derived from client request"
485
+ }
486
+ ],
487
+ "attack_scenario": "A user can change their own role to admin.",
488
+ "impact": "Privilege escalation to admin role.",
489
+ "severity": "critical",
490
+ "confidence": "high",
491
+ "cwe": [
492
+ "CWE-269",
493
+ "CWE-285"
494
+ ],
495
+ "owasp": [
496
+ "API5:2023"
497
+ ],
498
+ "recommendation": "Remove client\u2011controlled role assignment and enforce server\u2011side role check.",
499
+ "fix_example": "if ($_SESSION['role'] !== 'admin') { http_response_code(403); exit; }",
500
+ "status": "unverified"
501
+ },
502
+ {
503
+ "finding_id": "MASS-0011-1",
504
+ "category": "mass_assignment",
505
+ "subtype": "whole_object_binding",
506
+ "title": "PHP profile update binds entire POST payload to user object",
507
+ "candidate_id": "M-0011",
508
+ "endpoint": null,
509
+ "location": {
510
+ "file": "php-plain/profile.php",
511
+ "start_line": 5,
512
+ "end_line": 11
513
+ },
514
+ "evidence": [
515
+ {
516
+ "file": "php-plain/profile.php",
517
+ "line": 6,
518
+ "code": "foreach ($_POST as $field => $value) { $user->$field = $value; }",
519
+ "why": "binds all request fields"
520
+ },
521
+ {
522
+ "file": "php-plain/profile.php",
523
+ "line": 10,
524
+ "code": "$user->role = $_POST['role'];",
525
+ "why": "privileged field bound"
526
+ }
527
+ ],
528
+ "attack_vector": {
529
+ "method": "POST",
530
+ "path": "/php-plain/profile.php",
531
+ "fields": {
532
+ "role": "admin"
533
+ },
534
+ "readback": "GET /php-plain/profile.php"
535
+ },
536
+ "impact": "Privilege escalation via role field.",
537
+ "severity": "critical",
538
+ "confidence": "high",
539
+ "cwe": [
540
+ "CWE-915"
541
+ ],
542
+ "owasp": [
543
+ "API3:2023"
544
+ ],
545
+ "recommendation": "Copy only allowed fields from the request.",
546
+ "fix_example": "$user->name = $_POST['name']; $user->email = $_POST['email'];",
547
+ "status": "unverified"
548
+ },
549
+ {
550
+ "finding_id": "MASS-0012-1",
551
+ "category": "mass_assignment",
552
+ "subtype": "privileged_field_writable",
553
+ "title": "PHP profile update allows client to set role",
554
+ "candidate_id": "M-0012",
555
+ "endpoint": null,
556
+ "location": {
557
+ "file": "php-plain/profile.php",
558
+ "start_line": 5,
559
+ "end_line": 11
560
+ },
561
+ "evidence": [
562
+ {
563
+ "file": "php-plain/profile.php",
564
+ "line": 10,
565
+ "code": "$user->role = $_POST['role'];",
566
+ "why": "privileged field writable"
567
+ }
568
+ ],
569
+ "attack_vector": {
570
+ "method": "POST",
571
+ "path": "/php-plain/profile.php",
572
+ "fields": {
573
+ "role": "admin"
574
+ },
575
+ "readback": "GET /php-plain/profile.php"
576
+ },
577
+ "impact": "Privilege escalation via role field.",
578
+ "severity": "critical",
579
+ "confidence": "high",
580
+ "cwe": [
581
+ "CWE-915",
582
+ "CWE-269"
583
+ ],
584
+ "owasp": [
585
+ "API3:2023"
586
+ ],
587
+ "recommendation": "Remove role field from client input and enforce server\u2011side role check.",
588
+ "fix_example": "$user->role = $_SESSION['role'];",
589
+ "status": "unverified"
590
+ },
591
+ {
592
+ "finding_id": "MASS-0003-1",
593
+ "category": "mass_assignment",
594
+ "subtype": "needs_review",
595
+ "title": "Java Account update binds entire request body to Account entity",
596
+ "candidate_id": "M-0003",
597
+ "endpoint": null,
598
+ "location": {
599
+ "file": "src/main/java/com/acme/web/AccountController.java",
600
+ "start_line": 13,
601
+ "end_line": 16
602
+ },
603
+ "evidence": [
604
+ {
605
+ "file": "src/main/java/com/acme/web/AccountController.java",
606
+ "line": 14,
607
+ "code": "public String save(@ModelAttribute Account account) { accountDao.save(account); }",
608
+ "why": "binds all fields from request"
609
+ }
610
+ ],
611
+ "impact": "Potential privilege escalation if Account contains privileged fields such as balance or owner.",
612
+ "severity": "medium",
613
+ "confidence": "medium",
614
+ "cwe": [
615
+ "CWE-915"
616
+ ],
617
+ "owasp": [
618
+ "API3:2023"
619
+ ],
620
+ "recommendation": "Limit binding to non\u2011privileged fields or use DTOs.",
621
+ "status": "needs_review"
622
+ },
623
+ {
624
+ "finding_id": "MASS-0004-1",
625
+ "category": "mass_assignment",
626
+ "subtype": "needs_review",
627
+ "title": "Java Account update binds entire request body to Account entity",
628
+ "candidate_id": "M-0004",
629
+ "endpoint": null,
630
+ "location": {
631
+ "file": "src/main/java/com/acme/web/AccountController.java",
632
+ "start_line": 13,
633
+ "end_line": 16
634
+ },
635
+ "evidence": [
636
+ {
637
+ "file": "src/main/java/com/acme/web/AccountController.java",
638
+ "line": 14,
639
+ "code": "public String save(@ModelAttribute Account account) { accountDao.save(account); }",
640
+ "why": "binds all fields from request"
641
+ }
642
+ ],
643
+ "impact": "Potential privilege escalation if Account contains privileged fields such as balance or owner.",
644
+ "severity": "medium",
645
+ "confidence": "medium",
646
+ "cwe": [
647
+ "CWE-915"
648
+ ],
649
+ "owasp": [
650
+ "API3:2023"
651
+ ],
652
+ "recommendation": "Limit binding to non\u2011privileged fields or use DTOs.",
653
+ "status": "needs_review"
654
+ },
655
+ {
656
+ "finding_id": "MASS-0005-1",
657
+ "category": "mass_assignment",
658
+ "subtype": "needs_review",
659
+ "title": "Java BeanUtils.populate binds request parameters to Account entity",
660
+ "candidate_id": "M-0005",
661
+ "endpoint": null,
662
+ "location": {
663
+ "file": "src/main/java/com/acme/web/ProfileServlet.java",
664
+ "start_line": 10,
665
+ "end_line": 13
666
+ },
667
+ "evidence": [
668
+ {
669
+ "file": "src/main/java/com/acme/web/ProfileServlet.java",
670
+ "line": 12,
671
+ "code": "BeanUtils.populate(account, request.getParameterMap());",
672
+ "why": "binds all request parameters"
673
+ }
674
+ ],
675
+ "impact": "Potential privilege escalation if Account contains privileged fields such as balance or owner.",
676
+ "severity": "medium",
677
+ "confidence": "medium",
678
+ "cwe": [
679
+ "CWE-915"
680
+ ],
681
+ "owasp": [
682
+ "API3:2023"
683
+ ],
684
+ "recommendation": "Limit binding to non\u2011privileged fields or use DTOs.",
685
+ "status": "needs_review"
686
+ }
687
+ ],
688
+ "privilege_route_verdicts": [
689
+ {
690
+ "route_id": "R-0003",
691
+ "verdict": "vulnerable",
692
+ "finding_ids": [
693
+ "BFLA-0003-1"
694
+ ]
695
+ },
696
+ {
697
+ "route_id": "R-0007",
698
+ "verdict": "vulnerable",
699
+ "finding_ids": [
700
+ "BFLA-0007-1"
701
+ ]
702
+ },
703
+ {
704
+ "route_id": "R-0009",
705
+ "verdict": "vulnerable",
706
+ "finding_ids": [
707
+ "BFLA-0009-1"
708
+ ]
709
+ },
710
+ {
711
+ "route_id": "R-0023",
712
+ "verdict": "vulnerable",
713
+ "finding_ids": [
714
+ "BFLA-0023-1"
715
+ ]
716
+ },
717
+ {
718
+ "route_id": "R-0030",
719
+ "verdict": "vulnerable",
720
+ "finding_ids": [
721
+ "BFLA-0030-1"
722
+ ]
723
+ },
724
+ {
725
+ "route_id": "R-0032",
726
+ "verdict": "vulnerable",
727
+ "finding_ids": [
728
+ "BFLA-0032-1"
729
+ ]
730
+ },
731
+ {
732
+ "route_id": "R-0057",
733
+ "verdict": "vulnerable",
734
+ "finding_ids": [
735
+ "BFLA-0057-1"
736
+ ]
737
+ },
738
+ {
739
+ "route_id": "R-0058",
740
+ "verdict": "vulnerable",
741
+ "finding_ids": [
742
+ "BFLA-0058-1"
743
+ ]
744
+ },
745
+ {
746
+ "route_id": "R-0066",
747
+ "verdict": "vulnerable",
748
+ "finding_ids": [
749
+ "BFLA-0066-1"
750
+ ]
751
+ },
752
+ {
753
+ "route_id": "R-0067",
754
+ "verdict": "vulnerable",
755
+ "finding_ids": [
756
+ "BFLA-0067-1",
757
+ "BFLA-0067-2"
758
+ ]
759
+ },
760
+ {
761
+ "route_id": "R-0059",
762
+ "verdict": "vulnerable",
763
+ "finding_ids": [
764
+ "BFLA-0059-1"
765
+ ]
766
+ },
767
+ {
768
+ "route_id": "R-0063",
769
+ "verdict": "vulnerable",
770
+ "finding_ids": [
771
+ "BFLA-0063-1"
772
+ ]
773
+ }
774
+ ],
775
+ "candidate_verdicts": [
776
+ {
777
+ "candidate_id": "M-0011",
778
+ "verdict": "vulnerable",
779
+ "finding_ids": [
780
+ "MASS-0011-1"
781
+ ]
782
+ },
783
+ {
784
+ "candidate_id": "M-0012",
785
+ "verdict": "vulnerable",
786
+ "finding_ids": [
787
+ "MASS-0012-1"
788
+ ]
789
+ },
790
+ {
791
+ "candidate_id": "M-0001",
792
+ "verdict": "safe",
793
+ "reason": "no privileged field"
794
+ },
795
+ {
796
+ "candidate_id": "M-0002",
797
+ "verdict": "safe",
798
+ "reason": "no privileged field"
799
+ },
800
+ {
801
+ "candidate_id": "M-0003",
802
+ "verdict": "needs_review",
803
+ "finding_ids": [
804
+ "MASS-0003-1"
805
+ ]
806
+ },
807
+ {
808
+ "candidate_id": "M-0004",
809
+ "verdict": "needs_review",
810
+ "finding_ids": [
811
+ "MASS-0004-1"
812
+ ]
813
+ },
814
+ {
815
+ "candidate_id": "M-0005",
816
+ "verdict": "needs_review",
817
+ "finding_ids": [
818
+ "MASS-0005-1"
819
+ ]
820
+ }
821
+ ]
822
+ }