@vibecheckai/cli 3.2.2 → 3.2.4
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/bin/.generated +25 -25
- package/bin/dev/run-v2-torture.js +30 -30
- package/bin/runners/ENHANCEMENT_GUIDE.md +121 -121
- package/bin/runners/lib/__tests__/entitlements-v2.test.js +295 -295
- package/bin/runners/lib/agent-firewall/ai/false-positive-analyzer.js +474 -0
- package/bin/runners/lib/agent-firewall/claims/extractor.js +117 -28
- package/bin/runners/lib/agent-firewall/evidence/env-evidence.js +23 -14
- package/bin/runners/lib/agent-firewall/evidence/route-evidence.js +72 -1
- package/bin/runners/lib/agent-firewall/interceptor/base.js +2 -2
- package/bin/runners/lib/agent-firewall/policy/default-policy.json +6 -0
- package/bin/runners/lib/agent-firewall/policy/engine.js +34 -3
- package/bin/runners/lib/agent-firewall/policy/rules/fake-success.js +29 -4
- package/bin/runners/lib/agent-firewall/policy/rules/ghost-route.js +12 -0
- package/bin/runners/lib/agent-firewall/truthpack/loader.js +21 -0
- package/bin/runners/lib/agent-firewall/utils/ignore-checker.js +118 -0
- package/bin/runners/lib/analyzers.js +606 -325
- package/bin/runners/lib/auth-truth.js +193 -193
- package/bin/runners/lib/backup.js +62 -62
- package/bin/runners/lib/billing.js +107 -107
- package/bin/runners/lib/claims.js +118 -118
- package/bin/runners/lib/cli-ui.js +540 -540
- package/bin/runners/lib/contracts/auth-contract.js +202 -202
- package/bin/runners/lib/contracts/env-contract.js +181 -181
- package/bin/runners/lib/contracts/external-contract.js +206 -206
- package/bin/runners/lib/contracts/guard.js +168 -168
- package/bin/runners/lib/contracts/index.js +89 -89
- package/bin/runners/lib/contracts/plan-validator.js +311 -311
- package/bin/runners/lib/contracts/route-contract.js +199 -199
- package/bin/runners/lib/contracts.js +804 -804
- package/bin/runners/lib/detect.js +89 -89
- package/bin/runners/lib/doctor/autofix.js +254 -254
- package/bin/runners/lib/doctor/index.js +37 -37
- package/bin/runners/lib/doctor/modules/dependencies.js +325 -325
- package/bin/runners/lib/doctor/modules/index.js +46 -46
- package/bin/runners/lib/doctor/modules/network.js +250 -250
- package/bin/runners/lib/doctor/modules/project.js +312 -312
- package/bin/runners/lib/doctor/modules/runtime.js +224 -224
- package/bin/runners/lib/doctor/modules/security.js +348 -348
- package/bin/runners/lib/doctor/modules/system.js +213 -213
- package/bin/runners/lib/doctor/modules/vibecheck.js +394 -394
- package/bin/runners/lib/doctor/reporter.js +262 -262
- package/bin/runners/lib/doctor/service.js +262 -262
- package/bin/runners/lib/doctor/types.js +113 -113
- package/bin/runners/lib/doctor/ui.js +263 -263
- package/bin/runners/lib/doctor-v2.js +608 -608
- package/bin/runners/lib/drift.js +425 -425
- package/bin/runners/lib/enforcement.js +72 -72
- package/bin/runners/lib/engines/accessibility-engine.js +190 -0
- package/bin/runners/lib/engines/api-consistency-engine.js +162 -0
- package/bin/runners/lib/engines/ast-cache.js +99 -0
- package/bin/runners/lib/engines/code-quality-engine.js +255 -0
- package/bin/runners/lib/engines/console-logs-engine.js +115 -0
- package/bin/runners/lib/engines/cross-file-analysis-engine.js +268 -0
- package/bin/runners/lib/engines/dead-code-engine.js +198 -0
- package/bin/runners/lib/engines/deprecated-api-engine.js +226 -0
- package/bin/runners/lib/engines/empty-catch-engine.js +150 -0
- package/bin/runners/lib/engines/file-filter.js +131 -0
- package/bin/runners/lib/engines/hardcoded-secrets-engine.js +251 -0
- package/bin/runners/lib/engines/mock-data-engine.js +272 -0
- package/bin/runners/lib/engines/parallel-processor.js +71 -0
- package/bin/runners/lib/engines/performance-issues-engine.js +265 -0
- package/bin/runners/lib/engines/security-vulnerabilities-engine.js +243 -0
- package/bin/runners/lib/engines/todo-fixme-engine.js +115 -0
- package/bin/runners/lib/engines/type-aware-engine.js +152 -0
- package/bin/runners/lib/engines/unsafe-regex-engine.js +225 -0
- package/bin/runners/lib/engines/vibecheck-engines/README.md +53 -0
- package/bin/runners/lib/engines/vibecheck-engines/index.js +15 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/ast-cache.js +164 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/code-quality-engine.js +291 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/console-logs-engine.js +83 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/dead-code-engine.js +198 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/deprecated-api-engine.js +275 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/empty-catch-engine.js +167 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/file-filter.js +217 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/hardcoded-secrets-engine.js +139 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/mock-data-engine.js +140 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/parallel-processor.js +164 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/performance-issues-engine.js +234 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/type-aware-engine.js +217 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/unsafe-regex-engine.js +78 -0
- package/bin/runners/lib/engines/vibecheck-engines/package.json +13 -0
- package/bin/runners/lib/enterprise-detect.js +603 -603
- package/bin/runners/lib/enterprise-init.js +942 -942
- package/bin/runners/lib/env-resolver.js +417 -417
- package/bin/runners/lib/env-template.js +66 -66
- package/bin/runners/lib/env.js +189 -189
- package/bin/runners/lib/extractors/client-calls.js +990 -990
- package/bin/runners/lib/extractors/fastify-route-dump.js +573 -573
- package/bin/runners/lib/extractors/fastify-routes.js +426 -426
- package/bin/runners/lib/extractors/index.js +363 -363
- package/bin/runners/lib/extractors/next-routes.js +524 -524
- package/bin/runners/lib/extractors/proof-graph.js +431 -431
- package/bin/runners/lib/extractors/route-matcher.js +451 -451
- package/bin/runners/lib/extractors/truthpack-v2.js +377 -377
- package/bin/runners/lib/extractors/ui-bindings.js +547 -547
- package/bin/runners/lib/findings-schema.js +281 -281
- package/bin/runners/lib/firewall-prompt.js +50 -50
- package/bin/runners/lib/global-flags.js +213 -213
- package/bin/runners/lib/graph/graph-builder.js +265 -265
- package/bin/runners/lib/graph/html-renderer.js +413 -413
- package/bin/runners/lib/graph/index.js +32 -32
- package/bin/runners/lib/graph/runtime-collector.js +215 -215
- package/bin/runners/lib/graph/static-extractor.js +518 -518
- package/bin/runners/lib/html-report.js +650 -650
- package/bin/runners/lib/interactive-menu.js +1496 -1496
- package/bin/runners/lib/llm.js +75 -75
- package/bin/runners/lib/meter.js +61 -61
- package/bin/runners/lib/missions/evidence.js +126 -126
- package/bin/runners/lib/patch.js +40 -40
- package/bin/runners/lib/permissions/auth-model.js +213 -213
- package/bin/runners/lib/permissions/idor-prover.js +205 -205
- package/bin/runners/lib/permissions/index.js +45 -45
- package/bin/runners/lib/permissions/matrix-builder.js +198 -198
- package/bin/runners/lib/pkgjson.js +28 -28
- package/bin/runners/lib/policy.js +295 -295
- package/bin/runners/lib/preflight.js +142 -142
- package/bin/runners/lib/reality/correlation-detectors.js +359 -359
- package/bin/runners/lib/reality/index.js +318 -318
- package/bin/runners/lib/reality/request-hashing.js +416 -416
- package/bin/runners/lib/reality/request-mapper.js +453 -453
- package/bin/runners/lib/reality/safety-rails.js +463 -463
- package/bin/runners/lib/reality/semantic-snapshot.js +408 -408
- package/bin/runners/lib/reality/toast-detector.js +393 -393
- package/bin/runners/lib/reality-findings.js +84 -84
- package/bin/runners/lib/receipts.js +179 -179
- package/bin/runners/lib/redact.js +29 -29
- package/bin/runners/lib/replay/capsule-manager.js +154 -154
- package/bin/runners/lib/replay/index.js +263 -263
- package/bin/runners/lib/replay/player.js +348 -348
- package/bin/runners/lib/replay/recorder.js +331 -331
- package/bin/runners/lib/report-output.js +187 -187
- package/bin/runners/lib/report.js +135 -135
- package/bin/runners/lib/route-detection.js +1140 -1140
- package/bin/runners/lib/sandbox/index.js +59 -59
- package/bin/runners/lib/sandbox/proof-chain.js +399 -399
- package/bin/runners/lib/sandbox/sandbox-runner.js +205 -205
- package/bin/runners/lib/sandbox/worktree.js +174 -174
- package/bin/runners/lib/scan-output.js +525 -190
- package/bin/runners/lib/schema-validator.js +350 -350
- package/bin/runners/lib/schemas/contracts.schema.json +160 -160
- package/bin/runners/lib/schemas/finding.schema.json +100 -100
- package/bin/runners/lib/schemas/mission-pack.schema.json +206 -206
- package/bin/runners/lib/schemas/proof-graph.schema.json +176 -176
- package/bin/runners/lib/schemas/reality-report.schema.json +162 -162
- package/bin/runners/lib/schemas/share-pack.schema.json +180 -180
- package/bin/runners/lib/schemas/ship-report.schema.json +117 -117
- package/bin/runners/lib/schemas/truthpack-v2.schema.json +303 -303
- package/bin/runners/lib/schemas/validator.js +438 -438
- package/bin/runners/lib/score-history.js +282 -282
- package/bin/runners/lib/share-pack.js +239 -239
- package/bin/runners/lib/snippets.js +67 -67
- package/bin/runners/lib/status-output.js +253 -253
- package/bin/runners/lib/terminal-ui.js +351 -271
- package/bin/runners/lib/upsell.js +510 -510
- package/bin/runners/lib/usage.js +153 -153
- package/bin/runners/lib/validate-patch.js +156 -156
- package/bin/runners/lib/verdict-engine.js +628 -628
- package/bin/runners/reality/engine.js +917 -917
- package/bin/runners/reality/flows.js +122 -122
- package/bin/runners/reality/report.js +378 -378
- package/bin/runners/reality/session.js +193 -193
- package/bin/runners/runGuard.js +168 -168
- package/bin/runners/runProof.zip +0 -0
- package/bin/runners/runProve.js +8 -0
- package/bin/runners/runReality.js +14 -0
- package/bin/runners/runScan.js +17 -1
- package/bin/runners/runTruth.js +15 -3
- package/mcp-server/tier-auth.js +4 -4
- package/mcp-server/tools/index.js +72 -72
- package/package.json +1 -1
|
@@ -1,205 +1,205 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* IDOR Prover
|
|
3
|
-
* Detects Insecure Direct Object Reference vulnerabilities
|
|
4
|
-
* Tests if User A can access User B's resources
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
"use strict";
|
|
8
|
-
|
|
9
|
-
const crypto = require("crypto");
|
|
10
|
-
|
|
11
|
-
function sha256(text) {
|
|
12
|
-
return crypto.createHash("sha256").update(text).digest("hex").slice(0, 16);
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* Detect potential IDOR routes from auth model
|
|
17
|
-
*/
|
|
18
|
-
function detectIDORCandidates(authModel) {
|
|
19
|
-
const candidates = [];
|
|
20
|
-
|
|
21
|
-
for (const route of authModel.routes) {
|
|
22
|
-
// Look for patterns like /users/:id, /invoices/:id, /orders/:id
|
|
23
|
-
const idorPatterns = [
|
|
24
|
-
/\/users\/:[^/]+/i,
|
|
25
|
-
/\/accounts\/:[^/]+/i,
|
|
26
|
-
/\/profiles\/:[^/]+/i,
|
|
27
|
-
/\/invoices\/:[^/]+/i,
|
|
28
|
-
/\/orders\/:[^/]+/i,
|
|
29
|
-
/\/documents\/:[^/]+/i,
|
|
30
|
-
/\/files\/:[^/]+/i,
|
|
31
|
-
/\/projects\/:[^/]+/i,
|
|
32
|
-
/\/teams\/:[^/]+/i,
|
|
33
|
-
/\/organizations\/:[^/]+/i
|
|
34
|
-
];
|
|
35
|
-
|
|
36
|
-
for (const pattern of idorPatterns) {
|
|
37
|
-
if (pattern.test(route.path)) {
|
|
38
|
-
candidates.push({
|
|
39
|
-
path: route.path,
|
|
40
|
-
method: route.method,
|
|
41
|
-
handler: route.handler,
|
|
42
|
-
paramName: extractParamName(route.path),
|
|
43
|
-
resourceType: extractResourceType(route.path)
|
|
44
|
-
});
|
|
45
|
-
break;
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
return candidates;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
function extractParamName(path) {
|
|
54
|
-
const match = path.match(/:([^/]+)/);
|
|
55
|
-
return match ? match[1] : "id";
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
function extractResourceType(path) {
|
|
59
|
-
const parts = path.split("/").filter(Boolean);
|
|
60
|
-
for (let i = 0; i < parts.length; i++) {
|
|
61
|
-
if (parts[i].startsWith(":") && i > 0) {
|
|
62
|
-
return parts[i - 1];
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
return "resource";
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
/**
|
|
69
|
-
* Build IDOR test plan
|
|
70
|
-
*/
|
|
71
|
-
function buildIDORTestPlan(candidates, options = {}) {
|
|
72
|
-
const plan = {
|
|
73
|
-
version: "1.0.0",
|
|
74
|
-
generatedAt: new Date().toISOString(),
|
|
75
|
-
tests: [],
|
|
76
|
-
safeMode: options.safe !== false
|
|
77
|
-
};
|
|
78
|
-
|
|
79
|
-
for (const candidate of candidates) {
|
|
80
|
-
const test = {
|
|
81
|
-
id: `idor_${sha256(candidate.path)}`,
|
|
82
|
-
route: candidate.path,
|
|
83
|
-
method: candidate.method,
|
|
84
|
-
resourceType: candidate.resourceType,
|
|
85
|
-
paramName: candidate.paramName,
|
|
86
|
-
steps: [
|
|
87
|
-
{
|
|
88
|
-
description: `Login as User A`,
|
|
89
|
-
action: "auth",
|
|
90
|
-
role: "user_a"
|
|
91
|
-
},
|
|
92
|
-
{
|
|
93
|
-
description: `Access own resource: ${candidate.path.replace(`:${candidate.paramName}`, 'USER_A_ID')}`,
|
|
94
|
-
action: "request",
|
|
95
|
-
path: candidate.path,
|
|
96
|
-
param: "USER_A_ID",
|
|
97
|
-
expectStatus: [200, 201]
|
|
98
|
-
},
|
|
99
|
-
{
|
|
100
|
-
description: `Attempt to access User B's resource: ${candidate.path.replace(`:${candidate.paramName}`, 'USER_B_ID')}`,
|
|
101
|
-
action: "request",
|
|
102
|
-
path: candidate.path,
|
|
103
|
-
param: "USER_B_ID",
|
|
104
|
-
expectStatus: [403, 404]
|
|
105
|
-
}
|
|
106
|
-
],
|
|
107
|
-
violation: {
|
|
108
|
-
condition: "step[2].status === 200",
|
|
109
|
-
severity: "BLOCK",
|
|
110
|
-
type: "idor",
|
|
111
|
-
message: `User A can access User B's ${candidate.resourceType}`
|
|
112
|
-
}
|
|
113
|
-
};
|
|
114
|
-
|
|
115
|
-
plan.tests.push(test);
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
return plan;
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
/**
|
|
122
|
-
* Execute IDOR test (requires browser context)
|
|
123
|
-
*/
|
|
124
|
-
async function executeIDORTest(page, test, users) {
|
|
125
|
-
const result = {
|
|
126
|
-
testId: test.id,
|
|
127
|
-
route: test.route,
|
|
128
|
-
passed: true,
|
|
129
|
-
steps: [],
|
|
130
|
-
violation: null
|
|
131
|
-
};
|
|
132
|
-
|
|
133
|
-
// This is a placeholder - actual implementation requires:
|
|
134
|
-
// 1. Two test user accounts
|
|
135
|
-
// 2. Known resource IDs for each user
|
|
136
|
-
// 3. Ability to switch between sessions
|
|
137
|
-
|
|
138
|
-
if (!users?.userA || !users?.userB) {
|
|
139
|
-
result.skipped = true;
|
|
140
|
-
result.reason = "IDOR tests require two configured test users";
|
|
141
|
-
return result;
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
// Step 1: Login as User A
|
|
145
|
-
// Step 2: Access own resource - should succeed
|
|
146
|
-
// Step 3: Access User B's resource - should fail
|
|
147
|
-
|
|
148
|
-
// For now, return a template result
|
|
149
|
-
result.steps = test.steps.map((step, i) => ({
|
|
150
|
-
...step,
|
|
151
|
-
executed: false,
|
|
152
|
-
reason: "IDOR testing requires explicit --idor --safe flag and user configuration"
|
|
153
|
-
}));
|
|
154
|
-
|
|
155
|
-
return result;
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
/**
|
|
159
|
-
* Format IDOR test plan for display
|
|
160
|
-
*/
|
|
161
|
-
function formatIDORPlan(plan) {
|
|
162
|
-
const lines = [];
|
|
163
|
-
|
|
164
|
-
lines.push("# IDOR Test Plan\n");
|
|
165
|
-
lines.push(`Generated: ${plan.generatedAt}`);
|
|
166
|
-
lines.push(`Safe Mode: ${plan.safeMode ? "Yes" : "No"}`);
|
|
167
|
-
lines.push(`Tests: ${plan.tests.length}\n`);
|
|
168
|
-
|
|
169
|
-
if (plan.tests.length === 0) {
|
|
170
|
-
lines.push("No IDOR candidates detected.\n");
|
|
171
|
-
return lines.join("\n");
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
lines.push("## Candidates\n");
|
|
175
|
-
|
|
176
|
-
for (const test of plan.tests) {
|
|
177
|
-
lines.push(`### ${test.resourceType}: ${test.route}`);
|
|
178
|
-
lines.push(`Method: ${test.method}`);
|
|
179
|
-
lines.push(`Parameter: ${test.paramName}\n`);
|
|
180
|
-
|
|
181
|
-
lines.push("**Test Steps:**");
|
|
182
|
-
for (const step of test.steps) {
|
|
183
|
-
lines.push(`1. ${step.description}`);
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
lines.push("\n**Violation Condition:**");
|
|
187
|
-
lines.push(`If ${test.violation.condition}: ${test.violation.message}\n`);
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
lines.push("---\n");
|
|
191
|
-
lines.push("⚠️ **Safety Notice**");
|
|
192
|
-
lines.push("IDOR tests modify data access patterns. Only run on:");
|
|
193
|
-
lines.push("- Local development environments");
|
|
194
|
-
lines.push("- Staging with explicit consent");
|
|
195
|
-
lines.push("- With dedicated test accounts\n");
|
|
196
|
-
|
|
197
|
-
return lines.join("\n");
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
module.exports = {
|
|
201
|
-
detectIDORCandidates,
|
|
202
|
-
buildIDORTestPlan,
|
|
203
|
-
executeIDORTest,
|
|
204
|
-
formatIDORPlan
|
|
205
|
-
};
|
|
1
|
+
/**
|
|
2
|
+
* IDOR Prover
|
|
3
|
+
* Detects Insecure Direct Object Reference vulnerabilities
|
|
4
|
+
* Tests if User A can access User B's resources
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
"use strict";
|
|
8
|
+
|
|
9
|
+
const crypto = require("crypto");
|
|
10
|
+
|
|
11
|
+
function sha256(text) {
|
|
12
|
+
return crypto.createHash("sha256").update(text).digest("hex").slice(0, 16);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Detect potential IDOR routes from auth model
|
|
17
|
+
*/
|
|
18
|
+
function detectIDORCandidates(authModel) {
|
|
19
|
+
const candidates = [];
|
|
20
|
+
|
|
21
|
+
for (const route of authModel.routes) {
|
|
22
|
+
// Look for patterns like /users/:id, /invoices/:id, /orders/:id
|
|
23
|
+
const idorPatterns = [
|
|
24
|
+
/\/users\/:[^/]+/i,
|
|
25
|
+
/\/accounts\/:[^/]+/i,
|
|
26
|
+
/\/profiles\/:[^/]+/i,
|
|
27
|
+
/\/invoices\/:[^/]+/i,
|
|
28
|
+
/\/orders\/:[^/]+/i,
|
|
29
|
+
/\/documents\/:[^/]+/i,
|
|
30
|
+
/\/files\/:[^/]+/i,
|
|
31
|
+
/\/projects\/:[^/]+/i,
|
|
32
|
+
/\/teams\/:[^/]+/i,
|
|
33
|
+
/\/organizations\/:[^/]+/i
|
|
34
|
+
];
|
|
35
|
+
|
|
36
|
+
for (const pattern of idorPatterns) {
|
|
37
|
+
if (pattern.test(route.path)) {
|
|
38
|
+
candidates.push({
|
|
39
|
+
path: route.path,
|
|
40
|
+
method: route.method,
|
|
41
|
+
handler: route.handler,
|
|
42
|
+
paramName: extractParamName(route.path),
|
|
43
|
+
resourceType: extractResourceType(route.path)
|
|
44
|
+
});
|
|
45
|
+
break;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
return candidates;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function extractParamName(path) {
|
|
54
|
+
const match = path.match(/:([^/]+)/);
|
|
55
|
+
return match ? match[1] : "id";
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function extractResourceType(path) {
|
|
59
|
+
const parts = path.split("/").filter(Boolean);
|
|
60
|
+
for (let i = 0; i < parts.length; i++) {
|
|
61
|
+
if (parts[i].startsWith(":") && i > 0) {
|
|
62
|
+
return parts[i - 1];
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
return "resource";
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Build IDOR test plan
|
|
70
|
+
*/
|
|
71
|
+
function buildIDORTestPlan(candidates, options = {}) {
|
|
72
|
+
const plan = {
|
|
73
|
+
version: "1.0.0",
|
|
74
|
+
generatedAt: new Date().toISOString(),
|
|
75
|
+
tests: [],
|
|
76
|
+
safeMode: options.safe !== false
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
for (const candidate of candidates) {
|
|
80
|
+
const test = {
|
|
81
|
+
id: `idor_${sha256(candidate.path)}`,
|
|
82
|
+
route: candidate.path,
|
|
83
|
+
method: candidate.method,
|
|
84
|
+
resourceType: candidate.resourceType,
|
|
85
|
+
paramName: candidate.paramName,
|
|
86
|
+
steps: [
|
|
87
|
+
{
|
|
88
|
+
description: `Login as User A`,
|
|
89
|
+
action: "auth",
|
|
90
|
+
role: "user_a"
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
description: `Access own resource: ${candidate.path.replace(`:${candidate.paramName}`, 'USER_A_ID')}`,
|
|
94
|
+
action: "request",
|
|
95
|
+
path: candidate.path,
|
|
96
|
+
param: "USER_A_ID",
|
|
97
|
+
expectStatus: [200, 201]
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
description: `Attempt to access User B's resource: ${candidate.path.replace(`:${candidate.paramName}`, 'USER_B_ID')}`,
|
|
101
|
+
action: "request",
|
|
102
|
+
path: candidate.path,
|
|
103
|
+
param: "USER_B_ID",
|
|
104
|
+
expectStatus: [403, 404]
|
|
105
|
+
}
|
|
106
|
+
],
|
|
107
|
+
violation: {
|
|
108
|
+
condition: "step[2].status === 200",
|
|
109
|
+
severity: "BLOCK",
|
|
110
|
+
type: "idor",
|
|
111
|
+
message: `User A can access User B's ${candidate.resourceType}`
|
|
112
|
+
}
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
plan.tests.push(test);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
return plan;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Execute IDOR test (requires browser context)
|
|
123
|
+
*/
|
|
124
|
+
async function executeIDORTest(page, test, users) {
|
|
125
|
+
const result = {
|
|
126
|
+
testId: test.id,
|
|
127
|
+
route: test.route,
|
|
128
|
+
passed: true,
|
|
129
|
+
steps: [],
|
|
130
|
+
violation: null
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
// This is a placeholder - actual implementation requires:
|
|
134
|
+
// 1. Two test user accounts
|
|
135
|
+
// 2. Known resource IDs for each user
|
|
136
|
+
// 3. Ability to switch between sessions
|
|
137
|
+
|
|
138
|
+
if (!users?.userA || !users?.userB) {
|
|
139
|
+
result.skipped = true;
|
|
140
|
+
result.reason = "IDOR tests require two configured test users";
|
|
141
|
+
return result;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// Step 1: Login as User A
|
|
145
|
+
// Step 2: Access own resource - should succeed
|
|
146
|
+
// Step 3: Access User B's resource - should fail
|
|
147
|
+
|
|
148
|
+
// For now, return a template result
|
|
149
|
+
result.steps = test.steps.map((step, i) => ({
|
|
150
|
+
...step,
|
|
151
|
+
executed: false,
|
|
152
|
+
reason: "IDOR testing requires explicit --idor --safe flag and user configuration"
|
|
153
|
+
}));
|
|
154
|
+
|
|
155
|
+
return result;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Format IDOR test plan for display
|
|
160
|
+
*/
|
|
161
|
+
function formatIDORPlan(plan) {
|
|
162
|
+
const lines = [];
|
|
163
|
+
|
|
164
|
+
lines.push("# IDOR Test Plan\n");
|
|
165
|
+
lines.push(`Generated: ${plan.generatedAt}`);
|
|
166
|
+
lines.push(`Safe Mode: ${plan.safeMode ? "Yes" : "No"}`);
|
|
167
|
+
lines.push(`Tests: ${plan.tests.length}\n`);
|
|
168
|
+
|
|
169
|
+
if (plan.tests.length === 0) {
|
|
170
|
+
lines.push("No IDOR candidates detected.\n");
|
|
171
|
+
return lines.join("\n");
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
lines.push("## Candidates\n");
|
|
175
|
+
|
|
176
|
+
for (const test of plan.tests) {
|
|
177
|
+
lines.push(`### ${test.resourceType}: ${test.route}`);
|
|
178
|
+
lines.push(`Method: ${test.method}`);
|
|
179
|
+
lines.push(`Parameter: ${test.paramName}\n`);
|
|
180
|
+
|
|
181
|
+
lines.push("**Test Steps:**");
|
|
182
|
+
for (const step of test.steps) {
|
|
183
|
+
lines.push(`1. ${step.description}`);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
lines.push("\n**Violation Condition:**");
|
|
187
|
+
lines.push(`If ${test.violation.condition}: ${test.violation.message}\n`);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
lines.push("---\n");
|
|
191
|
+
lines.push("⚠️ **Safety Notice**");
|
|
192
|
+
lines.push("IDOR tests modify data access patterns. Only run on:");
|
|
193
|
+
lines.push("- Local development environments");
|
|
194
|
+
lines.push("- Staging with explicit consent");
|
|
195
|
+
lines.push("- With dedicated test accounts\n");
|
|
196
|
+
|
|
197
|
+
return lines.join("\n");
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
module.exports = {
|
|
201
|
+
detectIDORCandidates,
|
|
202
|
+
buildIDORTestPlan,
|
|
203
|
+
executeIDORTest,
|
|
204
|
+
formatIDORPlan
|
|
205
|
+
};
|
|
@@ -1,45 +1,45 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Permissions Module Index
|
|
3
|
-
* Exports all permission verification functionality
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
"use strict";
|
|
7
|
-
|
|
8
|
-
const {
|
|
9
|
-
extractAuthModel,
|
|
10
|
-
extractRolePatterns,
|
|
11
|
-
inferRoles,
|
|
12
|
-
buildRouteAuthMap
|
|
13
|
-
} = require("./auth-model");
|
|
14
|
-
|
|
15
|
-
const {
|
|
16
|
-
buildAuthZMatrix,
|
|
17
|
-
detectViolations,
|
|
18
|
-
formatMatrix
|
|
19
|
-
} = require("./matrix-builder");
|
|
20
|
-
|
|
21
|
-
const {
|
|
22
|
-
detectIDORCandidates,
|
|
23
|
-
buildIDORTestPlan,
|
|
24
|
-
executeIDORTest,
|
|
25
|
-
formatIDORPlan
|
|
26
|
-
} = require("./idor-prover");
|
|
27
|
-
|
|
28
|
-
module.exports = {
|
|
29
|
-
// Auth model extraction
|
|
30
|
-
extractAuthModel,
|
|
31
|
-
extractRolePatterns,
|
|
32
|
-
inferRoles,
|
|
33
|
-
buildRouteAuthMap,
|
|
34
|
-
|
|
35
|
-
// AuthZ matrix
|
|
36
|
-
buildAuthZMatrix,
|
|
37
|
-
detectViolations,
|
|
38
|
-
formatMatrix,
|
|
39
|
-
|
|
40
|
-
// IDOR detection
|
|
41
|
-
detectIDORCandidates,
|
|
42
|
-
buildIDORTestPlan,
|
|
43
|
-
executeIDORTest,
|
|
44
|
-
formatIDORPlan
|
|
45
|
-
};
|
|
1
|
+
/**
|
|
2
|
+
* Permissions Module Index
|
|
3
|
+
* Exports all permission verification functionality
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
"use strict";
|
|
7
|
+
|
|
8
|
+
const {
|
|
9
|
+
extractAuthModel,
|
|
10
|
+
extractRolePatterns,
|
|
11
|
+
inferRoles,
|
|
12
|
+
buildRouteAuthMap
|
|
13
|
+
} = require("./auth-model");
|
|
14
|
+
|
|
15
|
+
const {
|
|
16
|
+
buildAuthZMatrix,
|
|
17
|
+
detectViolations,
|
|
18
|
+
formatMatrix
|
|
19
|
+
} = require("./matrix-builder");
|
|
20
|
+
|
|
21
|
+
const {
|
|
22
|
+
detectIDORCandidates,
|
|
23
|
+
buildIDORTestPlan,
|
|
24
|
+
executeIDORTest,
|
|
25
|
+
formatIDORPlan
|
|
26
|
+
} = require("./idor-prover");
|
|
27
|
+
|
|
28
|
+
module.exports = {
|
|
29
|
+
// Auth model extraction
|
|
30
|
+
extractAuthModel,
|
|
31
|
+
extractRolePatterns,
|
|
32
|
+
inferRoles,
|
|
33
|
+
buildRouteAuthMap,
|
|
34
|
+
|
|
35
|
+
// AuthZ matrix
|
|
36
|
+
buildAuthZMatrix,
|
|
37
|
+
detectViolations,
|
|
38
|
+
formatMatrix,
|
|
39
|
+
|
|
40
|
+
// IDOR detection
|
|
41
|
+
detectIDORCandidates,
|
|
42
|
+
buildIDORTestPlan,
|
|
43
|
+
executeIDORTest,
|
|
44
|
+
formatIDORPlan
|
|
45
|
+
};
|