@vibecheckai/cli 2.8.2 → 3.0.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/README.md +8 -8
- package/bin/_deprecations.js +35 -0
- package/bin/_router.js +46 -0
- package/bin/cli-hygiene.js +241 -0
- package/bin/guardrail.js +834 -0
- package/bin/runners/cli-utils.js +1070 -0
- package/bin/runners/context/ai-task-decomposer.js +337 -0
- package/bin/runners/context/analyzer.js +462 -0
- package/bin/runners/context/api-contracts.js +427 -0
- package/bin/runners/context/context-diff.js +342 -0
- package/bin/runners/context/context-pruner.js +291 -0
- package/bin/runners/context/dependency-graph.js +414 -0
- package/bin/runners/context/generators/claude.js +107 -0
- package/bin/runners/context/generators/codex.js +108 -0
- package/bin/runners/context/generators/copilot.js +119 -0
- package/bin/runners/context/generators/cursor.js +514 -0
- package/bin/runners/context/generators/mcp.js +151 -0
- package/bin/runners/context/generators/windsurf.js +180 -0
- package/bin/runners/context/git-context.js +302 -0
- package/bin/runners/context/index.js +1042 -0
- package/bin/runners/context/insights.js +173 -0
- package/bin/runners/context/mcp-server/generate-rules.js +337 -0
- package/bin/runners/context/mcp-server/index.js +1176 -0
- package/bin/runners/context/mcp-server/package.json +24 -0
- package/bin/runners/context/memory.js +200 -0
- package/bin/runners/context/monorepo.js +215 -0
- package/bin/runners/context/multi-repo-federation.js +404 -0
- package/bin/runners/context/patterns.js +253 -0
- package/bin/runners/context/proof-context.js +972 -0
- package/bin/runners/context/security-scanner.js +303 -0
- package/bin/runners/context/semantic-search.js +350 -0
- package/bin/runners/context/shared.js +264 -0
- package/bin/runners/context/team-conventions.js +310 -0
- package/bin/runners/lib/ai-bridge.js +416 -0
- package/bin/runners/lib/analysis-core.js +271 -0
- package/bin/runners/lib/analyzers.js +541 -0
- package/bin/runners/lib/audit-bridge.js +391 -0
- package/bin/runners/lib/auth-truth.js +193 -0
- package/bin/runners/lib/auth.js +215 -0
- package/bin/runners/lib/backup.js +62 -0
- package/bin/runners/lib/billing.js +107 -0
- package/bin/runners/lib/claims.js +118 -0
- package/bin/runners/lib/cli-ui.js +540 -0
- package/bin/runners/lib/compliance-bridge-new.js +0 -0
- package/bin/runners/lib/compliance-bridge.js +165 -0
- package/bin/runners/lib/contracts/auth-contract.js +194 -0
- package/bin/runners/lib/contracts/env-contract.js +178 -0
- package/bin/runners/lib/contracts/external-contract.js +198 -0
- package/bin/runners/lib/contracts/guard.js +168 -0
- package/bin/runners/lib/contracts/index.js +89 -0
- package/bin/runners/lib/contracts/plan-validator.js +311 -0
- package/bin/runners/lib/contracts/route-contract.js +192 -0
- package/bin/runners/lib/detect.js +89 -0
- package/bin/runners/lib/doctor/autofix.js +254 -0
- package/bin/runners/lib/doctor/index.js +37 -0
- package/bin/runners/lib/doctor/modules/dependencies.js +325 -0
- package/bin/runners/lib/doctor/modules/index.js +46 -0
- package/bin/runners/lib/doctor/modules/network.js +250 -0
- package/bin/runners/lib/doctor/modules/project.js +312 -0
- package/bin/runners/lib/doctor/modules/runtime.js +224 -0
- package/bin/runners/lib/doctor/modules/security.js +348 -0
- package/bin/runners/lib/doctor/modules/system.js +213 -0
- package/bin/runners/lib/doctor/modules/vibecheck.js +394 -0
- package/bin/runners/lib/doctor/reporter.js +262 -0
- package/bin/runners/lib/doctor/service.js +262 -0
- package/bin/runners/lib/doctor/types.js +113 -0
- package/bin/runners/lib/doctor/ui.js +263 -0
- package/bin/runners/lib/doctor-enhanced.js +233 -0
- package/bin/runners/lib/doctor-v2.js +608 -0
- package/bin/runners/lib/enforcement.js +72 -0
- package/bin/runners/lib/enterprise-detect.js +603 -0
- package/bin/runners/lib/enterprise-init.js +942 -0
- package/bin/runners/lib/entitlements-v2.js +381 -0
- package/bin/runners/lib/entitlements.generated.js +0 -0
- package/bin/runners/lib/entitlements.js +332 -0
- package/bin/runners/lib/env-template.js +66 -0
- package/bin/runners/lib/env.js +189 -0
- package/bin/runners/lib/error-handler.js +320 -0
- package/bin/runners/lib/firewall-prompt.js +50 -0
- package/bin/runners/lib/graph/graph-builder.js +265 -0
- package/bin/runners/lib/graph/html-renderer.js +413 -0
- package/bin/runners/lib/graph/index.js +32 -0
- package/bin/runners/lib/graph/runtime-collector.js +215 -0
- package/bin/runners/lib/graph/static-extractor.js +518 -0
- package/bin/runners/lib/init-wizard.js +308 -0
- package/bin/runners/lib/json-output.js +76 -0
- package/bin/runners/lib/llm.js +75 -0
- package/bin/runners/lib/meter.js +61 -0
- package/bin/runners/lib/missions/evidence.js +126 -0
- package/bin/runners/lib/missions/plan.js +69 -0
- package/bin/runners/lib/missions/templates.js +147 -0
- package/bin/runners/lib/patch.js +40 -0
- package/bin/runners/lib/permissions/auth-model.js +213 -0
- package/bin/runners/lib/permissions/idor-prover.js +205 -0
- package/bin/runners/lib/permissions/index.js +45 -0
- package/bin/runners/lib/permissions/matrix-builder.js +198 -0
- package/bin/runners/lib/pkgjson.js +28 -0
- package/bin/runners/lib/preflight.js +142 -0
- package/bin/runners/lib/reality-findings.js +84 -0
- package/bin/runners/lib/redact.js +29 -0
- package/bin/runners/lib/replay/capsule-manager.js +154 -0
- package/bin/runners/lib/replay/index.js +263 -0
- package/bin/runners/lib/replay/player.js +348 -0
- package/bin/runners/lib/replay/recorder.js +331 -0
- package/bin/runners/lib/report-engine.js +447 -0
- package/bin/runners/lib/report-html.js +1117 -0
- package/bin/runners/lib/report-templates.js +964 -0
- package/bin/runners/lib/route-detection.js +1140 -0
- package/bin/runners/lib/route-truth.js +477 -0
- package/bin/runners/lib/sandbox/index.js +59 -0
- package/bin/runners/lib/sandbox/proof-chain.js +399 -0
- package/bin/runners/lib/sandbox/sandbox-runner.js +205 -0
- package/bin/runners/lib/sandbox/worktree.js +174 -0
- package/bin/runners/lib/scan-cache.js +330 -0
- package/bin/runners/lib/scan-output-schema.js +344 -0
- package/bin/runners/lib/score-history.js +282 -0
- package/bin/runners/lib/security-bridge.js +249 -0
- package/bin/runners/lib/server-usage.js +513 -0
- package/bin/runners/lib/share-pack.js +239 -0
- package/bin/runners/lib/snippets.js +67 -0
- package/bin/runners/lib/truth.js +667 -0
- package/bin/runners/lib/unified-output.js +189 -0
- package/bin/runners/lib/validate-patch.js +156 -0
- package/bin/runners/lib/verification.js +345 -0
- package/bin/runners/reality/engine.js +917 -0
- package/bin/runners/reality/flows.js +122 -0
- package/bin/runners/reality/report.js +378 -0
- package/bin/runners/reality/session.js +193 -0
- package/bin/runners/runAIAgent.js +2 -0
- package/bin/runners/runAudit.js +2 -0
- package/bin/runners/runAuth.js +106 -0
- package/bin/runners/runAutopilot.js +2 -0
- package/bin/runners/runBadge.js +2 -0
- package/bin/runners/runCertify.js +2 -0
- package/bin/runners/runClaimVerifier.js +483 -0
- package/bin/runners/runContext.js +56 -0
- package/bin/runners/runContextCompiler.js +385 -0
- package/bin/runners/runCtx.js +187 -0
- package/bin/runners/runCtxGuard.js +176 -0
- package/bin/runners/runCtxSync.js +116 -0
- package/bin/runners/runDashboard.js +10 -0
- package/bin/runners/runDoctor.js +245 -0
- package/bin/runners/runEnhancedShip.js +2 -0
- package/bin/runners/runFix.js +735 -0
- package/bin/runners/runFixPacks.js +2 -0
- package/bin/runners/runGate.js +17 -0
- package/bin/runners/runGraph.js +283 -0
- package/bin/runners/runInit.js +260 -0
- package/bin/runners/runInitGha.js +101 -0
- package/bin/runners/runInstall.js +76 -0
- package/bin/runners/runInteractive.js +388 -0
- package/bin/runners/runLaunch.js +2 -0
- package/bin/runners/runMcp.js +19 -0
- package/bin/runners/runMdc.js +2 -0
- package/bin/runners/runMissionGenerator.js +282 -0
- package/bin/runners/runNaturalLanguage.js +3 -0
- package/bin/runners/runPR.js +96 -0
- package/bin/runners/runPermissions.js +290 -0
- package/bin/runners/runPromptFirewall.js +211 -0
- package/bin/runners/runProof.js +2 -0
- package/bin/runners/runProve.js +392 -0
- package/bin/runners/runReality.js +489 -0
- package/bin/runners/runRealitySniff.js +2 -0
- package/bin/runners/runReplay.js +469 -0
- package/bin/runners/runReport.js +478 -0
- package/bin/runners/runScan.js +835 -0
- package/bin/runners/runShare.js +34 -0
- package/bin/runners/runShip.js +1062 -0
- package/bin/runners/runStatus.js +136 -0
- package/bin/runners/runTruthpack.js +634 -0
- package/bin/runners/runUpgrade.js +2 -0
- package/bin/runners/runValidate.js +2 -0
- package/bin/runners/runVerifyAgentOutput.js +2 -0
- package/bin/runners/runWatch.js +230 -0
- package/bin/runners/utils.js +360 -0
- package/bin/scan.js +612 -0
- package/bin/vibecheck.js +834 -0
- package/package.json +11 -11
- package/dist/autopatch/verified-autopatch.d.ts +0 -111
- package/dist/autopatch/verified-autopatch.d.ts.map +0 -1
- package/dist/autopatch/verified-autopatch.js +0 -503
- package/dist/autopatch/verified-autopatch.js.map +0 -1
- package/dist/bundles/index.js +0 -8
- package/dist/bundles/vibecheck-core.js +0 -25799
- package/dist/bundles/vibecheck-security.js +0 -208693
- package/dist/bundles/vibecheck-ship.js +0 -2318
- package/dist/commands/baseline.d.ts +0 -7
- package/dist/commands/baseline.d.ts.map +0 -1
- package/dist/commands/baseline.js +0 -79
- package/dist/commands/baseline.js.map +0 -1
- package/dist/commands/cache.d.ts +0 -13
- package/dist/commands/cache.d.ts.map +0 -1
- package/dist/commands/cache.js +0 -165
- package/dist/commands/cache.js.map +0 -1
- package/dist/commands/checkpoint.d.ts +0 -8
- package/dist/commands/checkpoint.d.ts.map +0 -1
- package/dist/commands/checkpoint.js +0 -35
- package/dist/commands/checkpoint.js.map +0 -1
- package/dist/commands/doctor.d.ts +0 -17
- package/dist/commands/doctor.d.ts.map +0 -1
- package/dist/commands/doctor.js +0 -226
- package/dist/commands/doctor.js.map +0 -1
- package/dist/commands/evidence.d.ts +0 -45
- package/dist/commands/evidence.d.ts.map +0 -1
- package/dist/commands/evidence.js +0 -197
- package/dist/commands/evidence.js.map +0 -1
- package/dist/commands/explain.d.ts +0 -8
- package/dist/commands/explain.d.ts.map +0 -1
- package/dist/commands/explain.js +0 -52
- package/dist/commands/explain.js.map +0 -1
- package/dist/commands/fix-consolidated.d.ts +0 -19
- package/dist/commands/fix-consolidated.d.ts.map +0 -1
- package/dist/commands/fix-consolidated.js +0 -165
- package/dist/commands/fix-consolidated.js.map +0 -1
- package/dist/commands/index.d.ts +0 -8
- package/dist/commands/index.d.ts.map +0 -1
- package/dist/commands/index.js +0 -15
- package/dist/commands/index.js.map +0 -1
- package/dist/commands/init.d.ts +0 -8
- package/dist/commands/init.d.ts.map +0 -1
- package/dist/commands/init.js +0 -125
- package/dist/commands/init.js.map +0 -1
- package/dist/commands/launcher.d.ts +0 -10
- package/dist/commands/launcher.d.ts.map +0 -1
- package/dist/commands/launcher.js +0 -174
- package/dist/commands/launcher.js.map +0 -1
- package/dist/commands/on.d.ts +0 -8
- package/dist/commands/on.d.ts.map +0 -1
- package/dist/commands/on.js +0 -123
- package/dist/commands/on.js.map +0 -1
- package/dist/commands/replay.d.ts +0 -8
- package/dist/commands/replay.d.ts.map +0 -1
- package/dist/commands/replay.js +0 -52
- package/dist/commands/replay.js.map +0 -1
- package/dist/commands/scan-consolidated.d.ts +0 -61
- package/dist/commands/scan-consolidated.d.ts.map +0 -1
- package/dist/commands/scan-consolidated.js +0 -243
- package/dist/commands/scan-consolidated.js.map +0 -1
- package/dist/commands/scan-secrets.d.ts +0 -47
- package/dist/commands/scan-secrets.d.ts.map +0 -1
- package/dist/commands/scan-secrets.js +0 -225
- package/dist/commands/scan-secrets.js.map +0 -1
- package/dist/commands/scan-vulnerabilities-enhanced.d.ts +0 -41
- package/dist/commands/scan-vulnerabilities-enhanced.d.ts.map +0 -1
- package/dist/commands/scan-vulnerabilities-enhanced.js +0 -368
- package/dist/commands/scan-vulnerabilities-enhanced.js.map +0 -1
- package/dist/commands/scan-vulnerabilities-osv.d.ts +0 -58
- package/dist/commands/scan-vulnerabilities-osv.d.ts.map +0 -1
- package/dist/commands/scan-vulnerabilities-osv.js +0 -722
- package/dist/commands/scan-vulnerabilities-osv.js.map +0 -1
- package/dist/commands/scan-vulnerabilities.d.ts +0 -32
- package/dist/commands/scan-vulnerabilities.d.ts.map +0 -1
- package/dist/commands/scan-vulnerabilities.js +0 -283
- package/dist/commands/scan-vulnerabilities.js.map +0 -1
- package/dist/commands/secrets-allowlist.d.ts +0 -7
- package/dist/commands/secrets-allowlist.d.ts.map +0 -1
- package/dist/commands/secrets-allowlist.js +0 -85
- package/dist/commands/secrets-allowlist.js.map +0 -1
- package/dist/commands/ship-consolidated.d.ts +0 -58
- package/dist/commands/ship-consolidated.d.ts.map +0 -1
- package/dist/commands/ship-consolidated.js +0 -515
- package/dist/commands/ship-consolidated.js.map +0 -1
- package/dist/commands/stats.d.ts +0 -8
- package/dist/commands/stats.d.ts.map +0 -1
- package/dist/commands/stats.js +0 -134
- package/dist/commands/stats.js.map +0 -1
- package/dist/commands/upgrade.d.ts +0 -8
- package/dist/commands/upgrade.d.ts.map +0 -1
- package/dist/commands/upgrade.js +0 -30
- package/dist/commands/upgrade.js.map +0 -1
- package/dist/fix/applicator.d.ts +0 -44
- package/dist/fix/applicator.d.ts.map +0 -1
- package/dist/fix/applicator.js +0 -144
- package/dist/fix/applicator.js.map +0 -1
- package/dist/fix/backup.d.ts +0 -38
- package/dist/fix/backup.d.ts.map +0 -1
- package/dist/fix/backup.js +0 -154
- package/dist/fix/backup.js.map +0 -1
- package/dist/fix/engine.d.ts +0 -55
- package/dist/fix/engine.d.ts.map +0 -1
- package/dist/fix/engine.js +0 -285
- package/dist/fix/engine.js.map +0 -1
- package/dist/fix/index.d.ts +0 -5
- package/dist/fix/index.d.ts.map +0 -1
- package/dist/fix/index.js +0 -12
- package/dist/fix/index.js.map +0 -1
- package/dist/fix/interactive.d.ts +0 -22
- package/dist/fix/interactive.d.ts.map +0 -1
- package/dist/fix/interactive.js +0 -172
- package/dist/fix/interactive.js.map +0 -1
- package/dist/formatters/index.d.ts +0 -6
- package/dist/formatters/index.d.ts.map +0 -1
- package/dist/formatters/index.js +0 -11
- package/dist/formatters/index.js.map +0 -1
- package/dist/formatters/sarif-enhanced.d.ts +0 -78
- package/dist/formatters/sarif-enhanced.d.ts.map +0 -1
- package/dist/formatters/sarif-enhanced.js +0 -144
- package/dist/formatters/sarif-enhanced.js.map +0 -1
- package/dist/formatters/sarif-v2.d.ts +0 -121
- package/dist/formatters/sarif-v2.d.ts.map +0 -1
- package/dist/formatters/sarif-v2.js +0 -356
- package/dist/formatters/sarif-v2.js.map +0 -1
- package/dist/formatters/sarif.d.ts +0 -72
- package/dist/formatters/sarif.d.ts.map +0 -1
- package/dist/formatters/sarif.js +0 -146
- package/dist/formatters/sarif.js.map +0 -1
- package/dist/index.d.ts +0 -61
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js +0 -4388
- package/dist/index.js.map +0 -1
- package/dist/init/ci-generator.d.ts +0 -18
- package/dist/init/ci-generator.d.ts.map +0 -1
- package/dist/init/ci-generator.js +0 -317
- package/dist/init/ci-generator.js.map +0 -1
- package/dist/init/detect-framework.d.ts +0 -15
- package/dist/init/detect-framework.d.ts.map +0 -1
- package/dist/init/detect-framework.js +0 -301
- package/dist/init/detect-framework.js.map +0 -1
- package/dist/init/hooks-installer.d.ts +0 -22
- package/dist/init/hooks-installer.d.ts.map +0 -1
- package/dist/init/hooks-installer.js +0 -310
- package/dist/init/hooks-installer.js.map +0 -1
- package/dist/init/index.d.ts +0 -8
- package/dist/init/index.d.ts.map +0 -1
- package/dist/init/index.js +0 -22
- package/dist/init/index.js.map +0 -1
- package/dist/init/templates.d.ts +0 -402
- package/dist/init/templates.d.ts.map +0 -1
- package/dist/init/templates.js +0 -240
- package/dist/init/templates.js.map +0 -1
- package/dist/mcp/server.d.ts +0 -12
- package/dist/mcp/server.d.ts.map +0 -1
- package/dist/mcp/server.js +0 -42
- package/dist/mcp/server.js.map +0 -1
- package/dist/mcp/telemetry.d.ts +0 -40
- package/dist/mcp/telemetry.d.ts.map +0 -1
- package/dist/mcp/telemetry.js +0 -98
- package/dist/mcp/telemetry.js.map +0 -1
- package/dist/reality/no-dead-buttons/button-sweep-generator.d.ts +0 -32
- package/dist/reality/no-dead-buttons/button-sweep-generator.d.ts.map +0 -1
- package/dist/reality/no-dead-buttons/button-sweep-generator.js +0 -236
- package/dist/reality/no-dead-buttons/button-sweep-generator.js.map +0 -1
- package/dist/reality/no-dead-buttons/index.d.ts +0 -11
- package/dist/reality/no-dead-buttons/index.d.ts.map +0 -1
- package/dist/reality/no-dead-buttons/index.js +0 -18
- package/dist/reality/no-dead-buttons/index.js.map +0 -1
- package/dist/reality/no-dead-buttons/static-scanner.d.ts +0 -34
- package/dist/reality/no-dead-buttons/static-scanner.d.ts.map +0 -1
- package/dist/reality/no-dead-buttons/static-scanner.js +0 -230
- package/dist/reality/no-dead-buttons/static-scanner.js.map +0 -1
- package/dist/reality/reality-graph.d.ts +0 -192
- package/dist/reality/reality-graph.d.ts.map +0 -1
- package/dist/reality/reality-graph.js +0 -600
- package/dist/reality/reality-graph.js.map +0 -1
- package/dist/reality/reality-runner.d.ts +0 -89
- package/dist/reality/reality-runner.d.ts.map +0 -1
- package/dist/reality/reality-runner.js +0 -540
- package/dist/reality/reality-runner.js.map +0 -1
- package/dist/reality/receipt-generator.d.ts +0 -152
- package/dist/reality/receipt-generator.d.ts.map +0 -1
- package/dist/reality/receipt-generator.js +0 -495
- package/dist/reality/receipt-generator.js.map +0 -1
- package/dist/reality/runtime-tracer.d.ts +0 -75
- package/dist/reality/runtime-tracer.d.ts.map +0 -1
- package/dist/reality/runtime-tracer.js +0 -109
- package/dist/reality/runtime-tracer.js.map +0 -1
- package/dist/runtime/auth-utils.d.ts +0 -43
- package/dist/runtime/auth-utils.d.ts.map +0 -1
- package/dist/runtime/auth-utils.js +0 -130
- package/dist/runtime/auth-utils.js.map +0 -1
- package/dist/runtime/client.d.ts +0 -74
- package/dist/runtime/client.d.ts.map +0 -1
- package/dist/runtime/client.js +0 -222
- package/dist/runtime/client.js.map +0 -1
- package/dist/runtime/creds.d.ts +0 -48
- package/dist/runtime/creds.d.ts.map +0 -1
- package/dist/runtime/creds.js +0 -245
- package/dist/runtime/creds.js.map +0 -1
- package/dist/runtime/exit-codes.d.ts +0 -49
- package/dist/runtime/exit-codes.d.ts.map +0 -1
- package/dist/runtime/exit-codes.js +0 -93
- package/dist/runtime/exit-codes.js.map +0 -1
- package/dist/runtime/index.d.ts +0 -9
- package/dist/runtime/index.d.ts.map +0 -1
- package/dist/runtime/index.js +0 -25
- package/dist/runtime/index.js.map +0 -1
- package/dist/runtime/json-output.d.ts +0 -42
- package/dist/runtime/json-output.d.ts.map +0 -1
- package/dist/runtime/json-output.js +0 -59
- package/dist/runtime/json-output.js.map +0 -1
- package/dist/runtime/semver.d.ts +0 -37
- package/dist/runtime/semver.d.ts.map +0 -1
- package/dist/runtime/semver.js +0 -110
- package/dist/runtime/semver.js.map +0 -1
- package/dist/scan/dead-ui-detector.d.ts +0 -48
- package/dist/scan/dead-ui-detector.d.ts.map +0 -1
- package/dist/scan/dead-ui-detector.js +0 -170
- package/dist/scan/dead-ui-detector.js.map +0 -1
- package/dist/scan/playwright-sweep.d.ts +0 -40
- package/dist/scan/playwright-sweep.d.ts.map +0 -1
- package/dist/scan/playwright-sweep.js +0 -216
- package/dist/scan/playwright-sweep.js.map +0 -1
- package/dist/scan/proof-bundle.d.ts +0 -25
- package/dist/scan/proof-bundle.d.ts.map +0 -1
- package/dist/scan/proof-bundle.js +0 -203
- package/dist/scan/proof-bundle.js.map +0 -1
- package/dist/scan/proof-graph.d.ts +0 -59
- package/dist/scan/proof-graph.d.ts.map +0 -1
- package/dist/scan/proof-graph.js +0 -64
- package/dist/scan/proof-graph.js.map +0 -1
- package/dist/scan/reality-sniff.d.ts +0 -56
- package/dist/scan/reality-sniff.d.ts.map +0 -1
- package/dist/scan/reality-sniff.js +0 -200
- package/dist/scan/reality-sniff.js.map +0 -1
- package/dist/scan/structural-verifier.d.ts +0 -20
- package/dist/scan/structural-verifier.d.ts.map +0 -1
- package/dist/scan/structural-verifier.js +0 -112
- package/dist/scan/structural-verifier.js.map +0 -1
- package/dist/scan/verification-engine.d.ts +0 -47
- package/dist/scan/verification-engine.d.ts.map +0 -1
- package/dist/scan/verification-engine.js +0 -141
- package/dist/scan/verification-engine.js.map +0 -1
- package/dist/scanner/baseline.d.ts +0 -52
- package/dist/scanner/baseline.d.ts.map +0 -1
- package/dist/scanner/baseline.js +0 -85
- package/dist/scanner/baseline.js.map +0 -1
- package/dist/scanner/incremental.d.ts +0 -30
- package/dist/scanner/incremental.d.ts.map +0 -1
- package/dist/scanner/incremental.js +0 -82
- package/dist/scanner/incremental.js.map +0 -1
- package/dist/scanner/parallel.d.ts +0 -43
- package/dist/scanner/parallel.d.ts.map +0 -1
- package/dist/scanner/parallel.js +0 -99
- package/dist/scanner/parallel.js.map +0 -1
- package/dist/standalone.d.ts +0 -1
- package/dist/standalone.d.ts.map +0 -1
- package/dist/standalone.js +0 -1
- package/dist/standalone.js.map +0 -1
- package/dist/truth-pack/index.d.ts +0 -102
- package/dist/truth-pack/index.d.ts.map +0 -1
- package/dist/truth-pack/index.js +0 -694
- package/dist/truth-pack/index.js.map +0 -1
- package/dist/ui/frame.d.ts +0 -68
- package/dist/ui/frame.d.ts.map +0 -1
- package/dist/ui/frame.js +0 -165
- package/dist/ui/frame.js.map +0 -1
- package/dist/ui/index.d.ts +0 -5
- package/dist/ui/index.d.ts.map +0 -1
- package/dist/ui/index.js +0 -16
- package/dist/ui/index.js.map +0 -1
- package/dist/ui.d.ts +0 -36
- package/dist/ui.d.ts.map +0 -1
- package/dist/ui.js +0 -45
- package/dist/ui.js.map +0 -1
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
// bin/runners/lib/missions/plan.js
|
|
2
|
+
function scoreFinding(f) {
|
|
3
|
+
if (f.severity === "BLOCK") return 100;
|
|
4
|
+
if (f.severity === "WARN") return 50;
|
|
5
|
+
return 0;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
function missionFromFinding(f) {
|
|
9
|
+
const typeByCategory = {
|
|
10
|
+
Security: "REMOVE_OWNER_MODE",
|
|
11
|
+
Billing: "FIX_STRIPE_WEBHOOKS",
|
|
12
|
+
Entitlements: "ENFORCE_PAID_SURFACE",
|
|
13
|
+
GhostAuth: "ADD_SERVER_AUTH",
|
|
14
|
+
MissingRoute: "FIX_MISSING_ROUTE",
|
|
15
|
+
EnvContract: "FIX_ENV_CONTRACT",
|
|
16
|
+
FakeSuccess: "FIX_FAKE_SUCCESS",
|
|
17
|
+
DeadUI: "FIX_DEAD_UI",
|
|
18
|
+
AuthCoverage: "ADD_SERVER_AUTH"
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
return {
|
|
22
|
+
id: `M_${f.id}`,
|
|
23
|
+
type: typeByCategory[f.category] || "GENERIC_FIX",
|
|
24
|
+
title: f.title,
|
|
25
|
+
severity: f.severity,
|
|
26
|
+
category: f.category,
|
|
27
|
+
successCriteria: [
|
|
28
|
+
`Finding ${f.id} no longer appears in ship results`
|
|
29
|
+
],
|
|
30
|
+
targetFindingIds: [f.id]
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function planMissions(findings, { maxMissions = 12, blocksOnlyFirst = true } = {}) {
|
|
35
|
+
const sorted = [...findings].sort((a,b) => scoreFinding(b) - scoreFinding(a));
|
|
36
|
+
|
|
37
|
+
// Cost control: if there are BLOCKs, only plan for BLOCKs first
|
|
38
|
+
const hasBlocks = sorted.some(f => f.severity === "BLOCK");
|
|
39
|
+
const scoped = (blocksOnlyFirst && hasBlocks)
|
|
40
|
+
? sorted.filter(f => f.severity === "BLOCK")
|
|
41
|
+
: sorted;
|
|
42
|
+
|
|
43
|
+
const seen = new Set();
|
|
44
|
+
const filtered = [];
|
|
45
|
+
for (const f of scoped) {
|
|
46
|
+
const k = `${f.category}:${f.title}`;
|
|
47
|
+
if (f.severity === "WARN" && seen.has(k)) continue;
|
|
48
|
+
seen.add(k);
|
|
49
|
+
filtered.push(f);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const missions = filtered.slice(0, maxMissions).map(missionFromFinding);
|
|
53
|
+
|
|
54
|
+
const priority = {
|
|
55
|
+
REMOVE_OWNER_MODE: 1,
|
|
56
|
+
FIX_STRIPE_WEBHOOKS: 2,
|
|
57
|
+
ENFORCE_PAID_SURFACE: 3,
|
|
58
|
+
ADD_SERVER_AUTH: 4,
|
|
59
|
+
FIX_MISSING_ROUTE: 5,
|
|
60
|
+
FIX_FAKE_SUCCESS: 6,
|
|
61
|
+
FIX_ENV_CONTRACT: 7,
|
|
62
|
+
GENERIC_FIX: 99
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
missions.sort((a,b) => (priority[a.type] || 50) - (priority[b.type] || 50));
|
|
66
|
+
return missions;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
module.exports = { planMissions };
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
// bin/runners/lib/missions/templates.js
|
|
2
|
+
function templateForMissionType(type) {
|
|
3
|
+
switch (type) {
|
|
4
|
+
case "REMOVE_OWNER_MODE":
|
|
5
|
+
return {
|
|
6
|
+
intent: "Remove any env-based entitlement bypass. Ship must not allow secretless unlocks.",
|
|
7
|
+
do: [
|
|
8
|
+
"Delete OWNER_MODE logic or gate it with signed admin token AND non-production check.",
|
|
9
|
+
"Ensure entitlement checks require real verification (API key / token / server-side).",
|
|
10
|
+
"Add/adjust tests if present (at minimum remove bypass path)."
|
|
11
|
+
],
|
|
12
|
+
dont: [
|
|
13
|
+
"Do not replace with another env var.",
|
|
14
|
+
"Do not add 'temporary' backdoor."
|
|
15
|
+
],
|
|
16
|
+
success: [
|
|
17
|
+
"Owner mode bypass finding disappears from ship results."
|
|
18
|
+
]
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
case "FIX_STRIPE_WEBHOOKS":
|
|
22
|
+
return {
|
|
23
|
+
intent: "Make Stripe webhooks real: signature verified + raw body + idempotent event handling.",
|
|
24
|
+
do: [
|
|
25
|
+
"Use stripe.webhooks.constructEvent(rawBody, sigHeader, secret).",
|
|
26
|
+
"Ensure raw body is used (Next pages: bodyParser false; Next app: req.text()/arrayBuffer()).",
|
|
27
|
+
"Persist processed event.id and short-circuit on replays."
|
|
28
|
+
],
|
|
29
|
+
dont: [
|
|
30
|
+
"Do not trust parsed JSON body for signature verification.",
|
|
31
|
+
"Do not mutate billing state without dedupe."
|
|
32
|
+
],
|
|
33
|
+
success: [
|
|
34
|
+
"Webhook verification + idempotency findings disappear."
|
|
35
|
+
]
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
case "ENFORCE_PAID_SURFACE":
|
|
39
|
+
return {
|
|
40
|
+
intent: "Move paid gating to the server handler BEFORE doing work.",
|
|
41
|
+
do: [
|
|
42
|
+
"Add enforceFeature/enforceLimit (or equivalent) at top of handler.",
|
|
43
|
+
"Return a structured 402/403 error code used by CLI/UI to upsell.",
|
|
44
|
+
"Keep logic minimal; don't refactor unrelated code."
|
|
45
|
+
],
|
|
46
|
+
dont: [
|
|
47
|
+
"Do not rely on client/CLI-only gating.",
|
|
48
|
+
"Do not introduce new plans/tiers in this step."
|
|
49
|
+
],
|
|
50
|
+
success: [
|
|
51
|
+
"Paid surface missing enforcement finding disappears."
|
|
52
|
+
]
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
case "ADD_SERVER_AUTH":
|
|
56
|
+
return {
|
|
57
|
+
intent: "Ensure sensitive endpoints have real server-side auth enforcement.",
|
|
58
|
+
do: [
|
|
59
|
+
"Add session/JWT verification in handler or route hook.",
|
|
60
|
+
"If using Next middleware, ensure matcher covers the sensitive paths (but do not over-widen blindly).",
|
|
61
|
+
"Return 401/403 on missing/invalid auth."
|
|
62
|
+
],
|
|
63
|
+
dont: [
|
|
64
|
+
"Do not only hide UI routes.",
|
|
65
|
+
"Do not add fake auth helpers without evidence."
|
|
66
|
+
],
|
|
67
|
+
success: [
|
|
68
|
+
"GhostAuth findings disappear."
|
|
69
|
+
]
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
case "FIX_MISSING_ROUTE":
|
|
73
|
+
return {
|
|
74
|
+
intent: "Make the referenced route real OR stop referencing it.",
|
|
75
|
+
do: [
|
|
76
|
+
"If the UI calls /api/x, ensure server route exists and matches method/path.",
|
|
77
|
+
"If the route should not exist, remove the client reference safely.",
|
|
78
|
+
"Prefer minimal handler that returns correct status and shape if needed."
|
|
79
|
+
],
|
|
80
|
+
dont: [
|
|
81
|
+
"Do not invent new API surface unless required by evidence.",
|
|
82
|
+
"Do not add broad wildcard routes."
|
|
83
|
+
],
|
|
84
|
+
success: [
|
|
85
|
+
"MissingRoute findings disappear."
|
|
86
|
+
]
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
case "FIX_FAKE_SUCCESS":
|
|
90
|
+
return {
|
|
91
|
+
intent: "Remove success UI lies: success must be gated on awaited + verified network result.",
|
|
92
|
+
do: [
|
|
93
|
+
"Await the network call.",
|
|
94
|
+
"Gate toast.success / navigation behind res.ok/status checks.",
|
|
95
|
+
"Surface error toast on failure."
|
|
96
|
+
],
|
|
97
|
+
dont: [
|
|
98
|
+
"Do not just delete success feedback.",
|
|
99
|
+
"Do not swallow errors silently."
|
|
100
|
+
],
|
|
101
|
+
success: [
|
|
102
|
+
"FakeSuccess findings disappear."
|
|
103
|
+
]
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
case "FIX_ENV_CONTRACT":
|
|
107
|
+
return {
|
|
108
|
+
intent: "Make env reality explicit: used env vars must be declared in .env.example/.env.template.",
|
|
109
|
+
do: [
|
|
110
|
+
"Add missing used vars to env template with safe defaults or comments.",
|
|
111
|
+
"If truly optional, ensure code has explicit fallback and document it."
|
|
112
|
+
],
|
|
113
|
+
dont: [
|
|
114
|
+
"Do not introduce new env var usage unrelated to the finding."
|
|
115
|
+
],
|
|
116
|
+
success: [
|
|
117
|
+
"EnvContract findings disappear."
|
|
118
|
+
]
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
case "FIX_DEAD_UI":
|
|
122
|
+
return {
|
|
123
|
+
intent: "Make UI actions real: clicks must trigger real handler + real success criteria.",
|
|
124
|
+
do: [
|
|
125
|
+
"If click calls /api/*: ensure route exists server-side and returns success only on real ok.",
|
|
126
|
+
"If click should navigate: ensure href/router push is correct and target route exists.",
|
|
127
|
+
"If click should open modal: ensure state toggles and modal renders.",
|
|
128
|
+
"If action is disabled: remove click affordance or add aria-disabled + disabled styling consistently."
|
|
129
|
+
],
|
|
130
|
+
dont: [
|
|
131
|
+
"Do not silence by removing UI without replacing the feature.",
|
|
132
|
+
"Do not show success toast before awaiting and verifying."
|
|
133
|
+
],
|
|
134
|
+
success: ["Dead UI findings disappear from ship (after running reality again)."]
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
default:
|
|
138
|
+
return {
|
|
139
|
+
intent: "Fix the specific finding with smallest correct patch.",
|
|
140
|
+
do: ["Keep it minimal, evidence-based, and verifiable."],
|
|
141
|
+
dont: ["Do not refactor unrelated code."],
|
|
142
|
+
success: ["Target finding disappears."]
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
module.exports = { templateForMissionType };
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
// bin/runners/lib/patch.js
|
|
2
|
+
const fs = require("fs");
|
|
3
|
+
const path = require("path");
|
|
4
|
+
const { spawnSync } = require("child_process");
|
|
5
|
+
|
|
6
|
+
function ensureDir(p) {
|
|
7
|
+
fs.mkdirSync(p, { recursive: true });
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
function writeTempPatch(repoRoot, diffText) {
|
|
11
|
+
const dir = path.join(repoRoot, ".vibecheck", "tmp");
|
|
12
|
+
ensureDir(dir);
|
|
13
|
+
const p = path.join(dir, `patch_${Date.now()}.diff`);
|
|
14
|
+
fs.writeFileSync(p, diffText, "utf8");
|
|
15
|
+
return p;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function applyPatchWithGit(repoRoot, patchPath) {
|
|
19
|
+
const r = spawnSync("git", ["apply", "--reject", "--whitespace=fix", patchPath], {
|
|
20
|
+
cwd: repoRoot,
|
|
21
|
+
stdio: "pipe",
|
|
22
|
+
encoding: "utf8"
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
return { ok: r.status === 0, stdout: r.stdout, stderr: r.stderr, code: r.status };
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function applyUnifiedDiff(repoRoot, diffText) {
|
|
29
|
+
const patchPath = writeTempPatch(repoRoot, diffText);
|
|
30
|
+
|
|
31
|
+
const check = spawnSync("git", ["--version"], { stdio: "ignore" });
|
|
32
|
+
if (check.status !== 0) {
|
|
33
|
+
return { ok: false, error: "git not found; cannot apply unified diff safely" };
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const res = applyPatchWithGit(repoRoot, patchPath);
|
|
37
|
+
return res.ok ? { ok: true } : { ok: false, error: res.stderr || "git apply failed", details: res };
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
module.exports = { applyUnifiedDiff };
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Auth Model Extractor
|
|
3
|
+
* Extracts authorization model from code and contracts
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
"use strict";
|
|
7
|
+
|
|
8
|
+
const fs = require("fs");
|
|
9
|
+
const path = require("path");
|
|
10
|
+
const fg = require("fast-glob");
|
|
11
|
+
const parser = require("@babel/parser");
|
|
12
|
+
const traverse = require("@babel/traverse").default;
|
|
13
|
+
const t = require("@babel/types");
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Extract auth model from codebase
|
|
17
|
+
*/
|
|
18
|
+
async function extractAuthModel(repoRoot, truthpack) {
|
|
19
|
+
const model = {
|
|
20
|
+
version: "1.0.0",
|
|
21
|
+
generatedAt: new Date().toISOString(),
|
|
22
|
+
roles: [],
|
|
23
|
+
routes: [],
|
|
24
|
+
rbacPatterns: [],
|
|
25
|
+
evidence: []
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
// Extract from truthpack
|
|
29
|
+
if (truthpack?.auth) {
|
|
30
|
+
model.protectedPatterns = truthpack.auth.nextMatcherPatterns || [];
|
|
31
|
+
|
|
32
|
+
// Add middleware evidence
|
|
33
|
+
for (const mw of truthpack.auth.nextMiddleware || []) {
|
|
34
|
+
model.evidence.push({
|
|
35
|
+
type: "next_middleware",
|
|
36
|
+
file: mw.file,
|
|
37
|
+
signals: mw.signalTypes || []
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// Extract role patterns from code
|
|
43
|
+
const rolePatterns = await extractRolePatterns(repoRoot);
|
|
44
|
+
model.rbacPatterns = rolePatterns;
|
|
45
|
+
|
|
46
|
+
// Infer roles from patterns
|
|
47
|
+
model.roles = inferRoles(rolePatterns, truthpack);
|
|
48
|
+
|
|
49
|
+
// Build route auth map
|
|
50
|
+
model.routes = buildRouteAuthMap(truthpack, model.roles);
|
|
51
|
+
|
|
52
|
+
return model;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Extract RBAC patterns from code
|
|
57
|
+
*/
|
|
58
|
+
async function extractRolePatterns(repoRoot) {
|
|
59
|
+
const patterns = [];
|
|
60
|
+
|
|
61
|
+
const files = await fg(["**/*.{ts,tsx,js,jsx}"], {
|
|
62
|
+
cwd: repoRoot,
|
|
63
|
+
absolute: true,
|
|
64
|
+
ignore: ["**/node_modules/**", "**/.next/**", "**/dist/**", "**/build/**"]
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
for (const fileAbs of files) {
|
|
68
|
+
const fileRel = path.relative(repoRoot, fileAbs).replace(/\\/g, "/");
|
|
69
|
+
const code = fs.readFileSync(fileAbs, "utf8");
|
|
70
|
+
|
|
71
|
+
// Look for role-related patterns
|
|
72
|
+
const roleMatches = [
|
|
73
|
+
// role === 'admin'
|
|
74
|
+
/role\s*===?\s*['"](\w+)['"]/gi,
|
|
75
|
+
// isAdmin, isUser
|
|
76
|
+
/\b(is(?:Admin|User|Manager|Owner|Moderator))\b/gi,
|
|
77
|
+
// hasRole('admin')
|
|
78
|
+
/hasRole\s*\(\s*['"](\w+)['"]\s*\)/gi,
|
|
79
|
+
// checkPermission('edit')
|
|
80
|
+
/check(?:Permission|Auth)\s*\(\s*['"](\w+)['"]\s*\)/gi,
|
|
81
|
+
// [role: 'admin']
|
|
82
|
+
/role:\s*['"](\w+)['"]/gi
|
|
83
|
+
];
|
|
84
|
+
|
|
85
|
+
for (const pattern of roleMatches) {
|
|
86
|
+
let match;
|
|
87
|
+
while ((match = pattern.exec(code)) !== null) {
|
|
88
|
+
patterns.push({
|
|
89
|
+
type: "role_check",
|
|
90
|
+
file: fileRel,
|
|
91
|
+
role: match[1],
|
|
92
|
+
line: code.substring(0, match.index).split("\n").length
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
return patterns;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Infer roles from patterns
|
|
103
|
+
*/
|
|
104
|
+
function inferRoles(patterns, truthpack) {
|
|
105
|
+
const roleNames = new Set();
|
|
106
|
+
|
|
107
|
+
// Common roles
|
|
108
|
+
roleNames.add("user");
|
|
109
|
+
roleNames.add("admin");
|
|
110
|
+
|
|
111
|
+
// From patterns
|
|
112
|
+
for (const p of patterns) {
|
|
113
|
+
if (p.role) {
|
|
114
|
+
roleNames.add(p.role.toLowerCase());
|
|
115
|
+
}
|
|
116
|
+
// Extract from isAdmin -> admin
|
|
117
|
+
if (p.role?.startsWith("is")) {
|
|
118
|
+
roleNames.add(p.role.substring(2).toLowerCase());
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// Build role objects
|
|
123
|
+
const roles = [];
|
|
124
|
+
for (const name of roleNames) {
|
|
125
|
+
const role = {
|
|
126
|
+
name,
|
|
127
|
+
routes: [],
|
|
128
|
+
evidence: patterns.filter(p =>
|
|
129
|
+
p.role?.toLowerCase() === name ||
|
|
130
|
+
p.role?.toLowerCase() === `is${name}`
|
|
131
|
+
)
|
|
132
|
+
};
|
|
133
|
+
roles.push(role);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
return roles;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Build route auth map
|
|
141
|
+
*/
|
|
142
|
+
function buildRouteAuthMap(truthpack, roles) {
|
|
143
|
+
const routes = [];
|
|
144
|
+
const serverRoutes = truthpack?.routes?.server || [];
|
|
145
|
+
const protectedPatterns = truthpack?.auth?.nextMatcherPatterns || [];
|
|
146
|
+
|
|
147
|
+
for (const route of serverRoutes) {
|
|
148
|
+
const isProtected = protectedPatterns.some(p => matchesPattern(route.path, p));
|
|
149
|
+
|
|
150
|
+
const routeAuth = {
|
|
151
|
+
path: route.path,
|
|
152
|
+
method: route.method,
|
|
153
|
+
handler: route.handler,
|
|
154
|
+
declared: {
|
|
155
|
+
protected: isProtected,
|
|
156
|
+
roles: inferRouteRoles(route, roles),
|
|
157
|
+
public: !isProtected && isPublicRoute(route.path)
|
|
158
|
+
},
|
|
159
|
+
actual: null // Filled by runtime verification
|
|
160
|
+
};
|
|
161
|
+
|
|
162
|
+
routes.push(routeAuth);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
return routes;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Infer which roles can access a route
|
|
170
|
+
*/
|
|
171
|
+
function inferRouteRoles(route, roles) {
|
|
172
|
+
const routeRoles = [];
|
|
173
|
+
|
|
174
|
+
// Admin routes
|
|
175
|
+
if (route.path.includes("/admin")) {
|
|
176
|
+
routeRoles.push("admin");
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
// User routes (most authenticated routes)
|
|
180
|
+
if (!route.path.includes("/admin") && !route.path.includes("/public")) {
|
|
181
|
+
routeRoles.push("user");
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
return routeRoles;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
function isPublicRoute(path) {
|
|
188
|
+
const publicPatterns = [
|
|
189
|
+
/^\/api\/health/i,
|
|
190
|
+
/^\/api\/status/i,
|
|
191
|
+
/^\/api\/public\//i,
|
|
192
|
+
/^\/_next\//i,
|
|
193
|
+
/^\/favicon/i
|
|
194
|
+
];
|
|
195
|
+
return publicPatterns.some(p => p.test(path));
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
function matchesPattern(path, pattern) {
|
|
199
|
+
const normPattern = pattern.replace(/\*/g, ".*").replace(/\//g, "\\/");
|
|
200
|
+
try {
|
|
201
|
+
const rx = new RegExp(`^${normPattern}`, "i");
|
|
202
|
+
return rx.test(path);
|
|
203
|
+
} catch {
|
|
204
|
+
return false;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
module.exports = {
|
|
209
|
+
extractAuthModel,
|
|
210
|
+
extractRolePatterns,
|
|
211
|
+
inferRoles,
|
|
212
|
+
buildRouteAuthMap
|
|
213
|
+
};
|
|
@@ -0,0 +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
|
+
};
|