@vibecheckai/cli 3.2.4 ā 3.2.6
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/lib/__tests__/entitlements-v2.test.js +295 -295
- package/bin/runners/lib/api-client.js +269 -0
- 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/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/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/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.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/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/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/runAgent.d.ts +5 -0
- package/bin/runners/runFirewall.d.ts +5 -0
- package/bin/runners/runFirewallHook.d.ts +5 -0
- package/bin/runners/runGuard.js +168 -168
- package/bin/runners/runScan.js +82 -0
- package/bin/runners/runTruth.d.ts +5 -0
- package/bin/vibecheck.js +45 -20
- package/mcp-server/index.js +85 -0
- package/mcp-server/lib/api-client.js +269 -0
- package/mcp-server/package.json +1 -1
- package/mcp-server/tier-auth.js +173 -113
- package/mcp-server/tools/index.js +72 -72
- package/mcp-server/vibecheck-mcp-server-3.2.0.tgz +0 -0
- package/package.json +1 -1
package/bin/runners/runGuard.js
CHANGED
|
@@ -1,168 +1,168 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* vibecheck guard - Unified trust boundary enforcement
|
|
3
|
-
*
|
|
4
|
-
* Combines: validate + claim-verifier + prompt-firewall
|
|
5
|
-
*
|
|
6
|
-
* Usage:
|
|
7
|
-
* vibecheck guard # Run all checks
|
|
8
|
-
* vibecheck guard --claims # Verify AI claims against truthpack
|
|
9
|
-
* vibecheck guard --prompts # Check for prompt injection
|
|
10
|
-
* vibecheck guard --hallucinations # Detect AI hallucination patterns
|
|
11
|
-
*/
|
|
12
|
-
|
|
13
|
-
const path = require("path");
|
|
14
|
-
const fs = require("fs");
|
|
15
|
-
|
|
16
|
-
// Import underlying implementations
|
|
17
|
-
const { runValidate } = require("./runValidate");
|
|
18
|
-
const { runPromptFirewall } = require("./runPromptFirewall");
|
|
19
|
-
|
|
20
|
-
// ANSI colors
|
|
21
|
-
const c = {
|
|
22
|
-
reset: "\x1b[0m",
|
|
23
|
-
dim: "\x1b[2m",
|
|
24
|
-
bold: "\x1b[1m",
|
|
25
|
-
cyan: "\x1b[36m",
|
|
26
|
-
green: "\x1b[32m",
|
|
27
|
-
yellow: "\x1b[33m",
|
|
28
|
-
red: "\x1b[31m",
|
|
29
|
-
magenta: "\x1b[35m",
|
|
30
|
-
};
|
|
31
|
-
|
|
32
|
-
function printHelp() {
|
|
33
|
-
console.log(`
|
|
34
|
-
${c.cyan}āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā${c.reset}
|
|
35
|
-
${c.bold}vibecheck guard${c.reset} - Trust boundary enforcement for AI outputs
|
|
36
|
-
${c.cyan}āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā${c.reset}
|
|
37
|
-
|
|
38
|
-
${c.green}USAGE${c.reset}
|
|
39
|
-
vibecheck guard [options]
|
|
40
|
-
|
|
41
|
-
${c.yellow}OPTIONS${c.reset}
|
|
42
|
-
--claims Verify AI claims against truthpack (route_exists, auth_enforced, etc.)
|
|
43
|
-
--prompts Check code for prompt injection vulnerabilities
|
|
44
|
-
--hallucinations Detect AI hallucination patterns in generated code
|
|
45
|
-
--file <path> Check specific file(s)
|
|
46
|
-
--json Output JSON for CI integration
|
|
47
|
-
--strict Fail on warnings (default: fail on errors only)
|
|
48
|
-
|
|
49
|
-
${c.magenta}EXAMPLES${c.reset}
|
|
50
|
-
vibecheck guard # Run all checks
|
|
51
|
-
vibecheck guard --claims --file api.ts # Verify claims in specific file
|
|
52
|
-
vibecheck guard --prompts # Prompt injection scan
|
|
53
|
-
vibecheck guard --json # CI-friendly output
|
|
54
|
-
|
|
55
|
-
${c.dim}This command unifies trust boundary checks for AI-generated code.${c.reset}
|
|
56
|
-
`);
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
async function runGuard(args = []) {
|
|
60
|
-
// Parse arguments
|
|
61
|
-
if (args.includes("--help") || args.includes("-h")) {
|
|
62
|
-
printHelp();
|
|
63
|
-
return 0;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
const runClaims = args.includes("--claims") || (!args.includes("--prompts") && !args.includes("--hallucinations"));
|
|
67
|
-
const runPrompts = args.includes("--prompts") || (!args.includes("--claims") && !args.includes("--hallucinations"));
|
|
68
|
-
const runHallucinations = args.includes("--hallucinations") || (!args.includes("--claims") && !args.includes("--prompts"));
|
|
69
|
-
const jsonOutput = args.includes("--json");
|
|
70
|
-
const strict = args.includes("--strict");
|
|
71
|
-
|
|
72
|
-
const results = {
|
|
73
|
-
claims: null,
|
|
74
|
-
prompts: null,
|
|
75
|
-
hallucinations: null,
|
|
76
|
-
verdict: "PASS",
|
|
77
|
-
errors: 0,
|
|
78
|
-
warnings: 0,
|
|
79
|
-
};
|
|
80
|
-
|
|
81
|
-
console.log(`
|
|
82
|
-
${c.cyan}āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā${c.reset}
|
|
83
|
-
${c.bold}š”ļø VIBECHECK GUARD${c.reset} - Trust Boundary Enforcement
|
|
84
|
-
${c.cyan}āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā${c.reset}
|
|
85
|
-
`);
|
|
86
|
-
|
|
87
|
-
// Run claims verification (validates AI claims against truthpack)
|
|
88
|
-
if (runClaims) {
|
|
89
|
-
console.log(`${c.dim}āø Verifying AI claims against truthpack...${c.reset}`);
|
|
90
|
-
try {
|
|
91
|
-
const validateArgs = args.filter(a => !["--claims", "--prompts", "--hallucinations"].includes(a));
|
|
92
|
-
const exitCode = await runValidate(validateArgs);
|
|
93
|
-
results.claims = { exitCode, status: exitCode === 0 ? "pass" : "fail" };
|
|
94
|
-
if (exitCode !== 0) {
|
|
95
|
-
results.errors++;
|
|
96
|
-
results.verdict = "FAIL";
|
|
97
|
-
}
|
|
98
|
-
console.log(exitCode === 0
|
|
99
|
-
? ` ${c.green}ā${c.reset} Claims verified`
|
|
100
|
-
: ` ${c.red}ā${c.reset} Claim verification failed`);
|
|
101
|
-
} catch (e) {
|
|
102
|
-
results.claims = { error: e.message };
|
|
103
|
-
console.log(` ${c.yellow}ā ${c.reset} Claims check skipped: ${e.message}`);
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
// Run prompt injection detection
|
|
108
|
-
if (runPrompts) {
|
|
109
|
-
console.log(`${c.dim}āø Scanning for prompt injection vulnerabilities...${c.reset}`);
|
|
110
|
-
try {
|
|
111
|
-
const firewallArgs = args.filter(a => !["--claims", "--prompts", "--hallucinations"].includes(a));
|
|
112
|
-
const exitCode = await runPromptFirewall(firewallArgs);
|
|
113
|
-
results.prompts = { exitCode, status: exitCode === 0 ? "pass" : "fail" };
|
|
114
|
-
if (exitCode !== 0) {
|
|
115
|
-
results.warnings++;
|
|
116
|
-
if (strict) results.verdict = "FAIL";
|
|
117
|
-
}
|
|
118
|
-
console.log(exitCode === 0
|
|
119
|
-
? ` ${c.green}ā${c.reset} No prompt injection risks`
|
|
120
|
-
: ` ${c.yellow}ā ${c.reset} Prompt injection risks detected`);
|
|
121
|
-
} catch (e) {
|
|
122
|
-
results.prompts = { error: e.message };
|
|
123
|
-
console.log(` ${c.yellow}ā ${c.reset} Prompt check skipped: ${e.message}`);
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
// Run hallucination detection
|
|
128
|
-
if (runHallucinations) {
|
|
129
|
-
console.log(`${c.dim}āø Detecting hallucination patterns...${c.reset}`);
|
|
130
|
-
// Use validate with hallucination focus
|
|
131
|
-
try {
|
|
132
|
-
const validateArgs = ["--hallucinations", ...args.filter(a => !["--claims", "--prompts", "--hallucinations"].includes(a))];
|
|
133
|
-
const exitCode = await runValidate(validateArgs);
|
|
134
|
-
results.hallucinations = { exitCode, status: exitCode === 0 ? "pass" : "fail" };
|
|
135
|
-
if (exitCode !== 0) {
|
|
136
|
-
results.warnings++;
|
|
137
|
-
if (strict) results.verdict = "FAIL";
|
|
138
|
-
}
|
|
139
|
-
console.log(exitCode === 0
|
|
140
|
-
? ` ${c.green}ā${c.reset} No hallucination patterns`
|
|
141
|
-
: ` ${c.yellow}ā ${c.reset} Potential hallucinations detected`);
|
|
142
|
-
} catch (e) {
|
|
143
|
-
results.hallucinations = { error: e.message };
|
|
144
|
-
console.log(` ${c.yellow}ā ${c.reset} Hallucination check skipped: ${e.message}`);
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
// Summary
|
|
149
|
-
console.log(`
|
|
150
|
-
${c.cyan}āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā${c.reset}`);
|
|
151
|
-
|
|
152
|
-
if (results.verdict === "PASS") {
|
|
153
|
-
console.log(` ${c.green}${c.bold}ā GUARD PASS${c.reset} - All trust boundaries intact`);
|
|
154
|
-
} else {
|
|
155
|
-
console.log(` ${c.red}${c.bold}ā GUARD FAIL${c.reset} - Trust boundary violations detected`);
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
console.log(`${c.cyan}āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā${c.reset}
|
|
159
|
-
`);
|
|
160
|
-
|
|
161
|
-
if (jsonOutput) {
|
|
162
|
-
console.log(JSON.stringify(results, null, 2));
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
return results.verdict === "PASS" ? 0 : (results.errors > 0 ? 2 : 1);
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
module.exports = { runGuard };
|
|
1
|
+
/**
|
|
2
|
+
* vibecheck guard - Unified trust boundary enforcement
|
|
3
|
+
*
|
|
4
|
+
* Combines: validate + claim-verifier + prompt-firewall
|
|
5
|
+
*
|
|
6
|
+
* Usage:
|
|
7
|
+
* vibecheck guard # Run all checks
|
|
8
|
+
* vibecheck guard --claims # Verify AI claims against truthpack
|
|
9
|
+
* vibecheck guard --prompts # Check for prompt injection
|
|
10
|
+
* vibecheck guard --hallucinations # Detect AI hallucination patterns
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
const path = require("path");
|
|
14
|
+
const fs = require("fs");
|
|
15
|
+
|
|
16
|
+
// Import underlying implementations
|
|
17
|
+
const { runValidate } = require("./runValidate");
|
|
18
|
+
const { runPromptFirewall } = require("./runPromptFirewall");
|
|
19
|
+
|
|
20
|
+
// ANSI colors
|
|
21
|
+
const c = {
|
|
22
|
+
reset: "\x1b[0m",
|
|
23
|
+
dim: "\x1b[2m",
|
|
24
|
+
bold: "\x1b[1m",
|
|
25
|
+
cyan: "\x1b[36m",
|
|
26
|
+
green: "\x1b[32m",
|
|
27
|
+
yellow: "\x1b[33m",
|
|
28
|
+
red: "\x1b[31m",
|
|
29
|
+
magenta: "\x1b[35m",
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
function printHelp() {
|
|
33
|
+
console.log(`
|
|
34
|
+
${c.cyan}āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā${c.reset}
|
|
35
|
+
${c.bold}vibecheck guard${c.reset} - Trust boundary enforcement for AI outputs
|
|
36
|
+
${c.cyan}āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā${c.reset}
|
|
37
|
+
|
|
38
|
+
${c.green}USAGE${c.reset}
|
|
39
|
+
vibecheck guard [options]
|
|
40
|
+
|
|
41
|
+
${c.yellow}OPTIONS${c.reset}
|
|
42
|
+
--claims Verify AI claims against truthpack (route_exists, auth_enforced, etc.)
|
|
43
|
+
--prompts Check code for prompt injection vulnerabilities
|
|
44
|
+
--hallucinations Detect AI hallucination patterns in generated code
|
|
45
|
+
--file <path> Check specific file(s)
|
|
46
|
+
--json Output JSON for CI integration
|
|
47
|
+
--strict Fail on warnings (default: fail on errors only)
|
|
48
|
+
|
|
49
|
+
${c.magenta}EXAMPLES${c.reset}
|
|
50
|
+
vibecheck guard # Run all checks
|
|
51
|
+
vibecheck guard --claims --file api.ts # Verify claims in specific file
|
|
52
|
+
vibecheck guard --prompts # Prompt injection scan
|
|
53
|
+
vibecheck guard --json # CI-friendly output
|
|
54
|
+
|
|
55
|
+
${c.dim}This command unifies trust boundary checks for AI-generated code.${c.reset}
|
|
56
|
+
`);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
async function runGuard(args = []) {
|
|
60
|
+
// Parse arguments
|
|
61
|
+
if (args.includes("--help") || args.includes("-h")) {
|
|
62
|
+
printHelp();
|
|
63
|
+
return 0;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const runClaims = args.includes("--claims") || (!args.includes("--prompts") && !args.includes("--hallucinations"));
|
|
67
|
+
const runPrompts = args.includes("--prompts") || (!args.includes("--claims") && !args.includes("--hallucinations"));
|
|
68
|
+
const runHallucinations = args.includes("--hallucinations") || (!args.includes("--claims") && !args.includes("--prompts"));
|
|
69
|
+
const jsonOutput = args.includes("--json");
|
|
70
|
+
const strict = args.includes("--strict");
|
|
71
|
+
|
|
72
|
+
const results = {
|
|
73
|
+
claims: null,
|
|
74
|
+
prompts: null,
|
|
75
|
+
hallucinations: null,
|
|
76
|
+
verdict: "PASS",
|
|
77
|
+
errors: 0,
|
|
78
|
+
warnings: 0,
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
console.log(`
|
|
82
|
+
${c.cyan}āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā${c.reset}
|
|
83
|
+
${c.bold}š”ļø VIBECHECK GUARD${c.reset} - Trust Boundary Enforcement
|
|
84
|
+
${c.cyan}āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā${c.reset}
|
|
85
|
+
`);
|
|
86
|
+
|
|
87
|
+
// Run claims verification (validates AI claims against truthpack)
|
|
88
|
+
if (runClaims) {
|
|
89
|
+
console.log(`${c.dim}āø Verifying AI claims against truthpack...${c.reset}`);
|
|
90
|
+
try {
|
|
91
|
+
const validateArgs = args.filter(a => !["--claims", "--prompts", "--hallucinations"].includes(a));
|
|
92
|
+
const exitCode = await runValidate(validateArgs);
|
|
93
|
+
results.claims = { exitCode, status: exitCode === 0 ? "pass" : "fail" };
|
|
94
|
+
if (exitCode !== 0) {
|
|
95
|
+
results.errors++;
|
|
96
|
+
results.verdict = "FAIL";
|
|
97
|
+
}
|
|
98
|
+
console.log(exitCode === 0
|
|
99
|
+
? ` ${c.green}ā${c.reset} Claims verified`
|
|
100
|
+
: ` ${c.red}ā${c.reset} Claim verification failed`);
|
|
101
|
+
} catch (e) {
|
|
102
|
+
results.claims = { error: e.message };
|
|
103
|
+
console.log(` ${c.yellow}ā ${c.reset} Claims check skipped: ${e.message}`);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// Run prompt injection detection
|
|
108
|
+
if (runPrompts) {
|
|
109
|
+
console.log(`${c.dim}āø Scanning for prompt injection vulnerabilities...${c.reset}`);
|
|
110
|
+
try {
|
|
111
|
+
const firewallArgs = args.filter(a => !["--claims", "--prompts", "--hallucinations"].includes(a));
|
|
112
|
+
const exitCode = await runPromptFirewall(firewallArgs);
|
|
113
|
+
results.prompts = { exitCode, status: exitCode === 0 ? "pass" : "fail" };
|
|
114
|
+
if (exitCode !== 0) {
|
|
115
|
+
results.warnings++;
|
|
116
|
+
if (strict) results.verdict = "FAIL";
|
|
117
|
+
}
|
|
118
|
+
console.log(exitCode === 0
|
|
119
|
+
? ` ${c.green}ā${c.reset} No prompt injection risks`
|
|
120
|
+
: ` ${c.yellow}ā ${c.reset} Prompt injection risks detected`);
|
|
121
|
+
} catch (e) {
|
|
122
|
+
results.prompts = { error: e.message };
|
|
123
|
+
console.log(` ${c.yellow}ā ${c.reset} Prompt check skipped: ${e.message}`);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// Run hallucination detection
|
|
128
|
+
if (runHallucinations) {
|
|
129
|
+
console.log(`${c.dim}āø Detecting hallucination patterns...${c.reset}`);
|
|
130
|
+
// Use validate with hallucination focus
|
|
131
|
+
try {
|
|
132
|
+
const validateArgs = ["--hallucinations", ...args.filter(a => !["--claims", "--prompts", "--hallucinations"].includes(a))];
|
|
133
|
+
const exitCode = await runValidate(validateArgs);
|
|
134
|
+
results.hallucinations = { exitCode, status: exitCode === 0 ? "pass" : "fail" };
|
|
135
|
+
if (exitCode !== 0) {
|
|
136
|
+
results.warnings++;
|
|
137
|
+
if (strict) results.verdict = "FAIL";
|
|
138
|
+
}
|
|
139
|
+
console.log(exitCode === 0
|
|
140
|
+
? ` ${c.green}ā${c.reset} No hallucination patterns`
|
|
141
|
+
: ` ${c.yellow}ā ${c.reset} Potential hallucinations detected`);
|
|
142
|
+
} catch (e) {
|
|
143
|
+
results.hallucinations = { error: e.message };
|
|
144
|
+
console.log(` ${c.yellow}ā ${c.reset} Hallucination check skipped: ${e.message}`);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// Summary
|
|
149
|
+
console.log(`
|
|
150
|
+
${c.cyan}āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā${c.reset}`);
|
|
151
|
+
|
|
152
|
+
if (results.verdict === "PASS") {
|
|
153
|
+
console.log(` ${c.green}${c.bold}ā GUARD PASS${c.reset} - All trust boundaries intact`);
|
|
154
|
+
} else {
|
|
155
|
+
console.log(` ${c.red}${c.bold}ā GUARD FAIL${c.reset} - Trust boundary violations detected`);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
console.log(`${c.cyan}āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā${c.reset}
|
|
159
|
+
`);
|
|
160
|
+
|
|
161
|
+
if (jsonOutput) {
|
|
162
|
+
console.log(JSON.stringify(results, null, 2));
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
return results.verdict === "PASS" ? 0 : (results.errors > 0 ? 2 : 1);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
module.exports = { runGuard };
|
package/bin/runners/runScan.js
CHANGED
|
@@ -18,6 +18,13 @@ const { withErrorHandling, createUserError } = require("./lib/error-handler");
|
|
|
18
18
|
const { enforceLimit, trackUsage } = require("./lib/entitlements");
|
|
19
19
|
const { emitScanStart, emitScanComplete } = require("./lib/audit-bridge");
|
|
20
20
|
const { parseGlobalFlags, shouldShowBanner } = require("./lib/global-flags");
|
|
21
|
+
const {
|
|
22
|
+
createScan,
|
|
23
|
+
updateScanProgress,
|
|
24
|
+
submitScanResults,
|
|
25
|
+
reportScanError,
|
|
26
|
+
isApiAvailable
|
|
27
|
+
} = require("./lib/api-client");
|
|
21
28
|
|
|
22
29
|
// āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
23
30
|
// ENHANCED TERMINAL UI & OUTPUT MODULES
|
|
@@ -703,6 +710,27 @@ async function runScan(args) {
|
|
|
703
710
|
emitScanStart(projectPath, args);
|
|
704
711
|
const projectName = path.basename(projectPath);
|
|
705
712
|
|
|
713
|
+
// Initialize API integration
|
|
714
|
+
let apiScan = null;
|
|
715
|
+
let apiConnected = false;
|
|
716
|
+
|
|
717
|
+
// Try to connect to API for dashboard integration
|
|
718
|
+
try {
|
|
719
|
+
apiConnected = await isApiAvailable();
|
|
720
|
+
if (apiConnected) {
|
|
721
|
+
// Create scan record in dashboard
|
|
722
|
+
apiScan = await createScan({
|
|
723
|
+
localPath: projectPath,
|
|
724
|
+
branch: opts.branch || 'main',
|
|
725
|
+
enableLLM: opts.llm || false,
|
|
726
|
+
});
|
|
727
|
+
console.log(`${colors.info}š”${ansi.reset} Connected to dashboard (Scan ID: ${apiScan.scanId})`);
|
|
728
|
+
}
|
|
729
|
+
} catch (err) {
|
|
730
|
+
// API connection is optional, continue without it
|
|
731
|
+
console.log(`${colors.dim}ā¹${ansi.reset} Dashboard integration unavailable`);
|
|
732
|
+
}
|
|
733
|
+
|
|
706
734
|
// Validate project path
|
|
707
735
|
if (!fs.existsSync(projectPath)) {
|
|
708
736
|
throw createUserError(`Project path does not exist: ${projectPath}`, "ValidationError");
|
|
@@ -1228,6 +1256,28 @@ async function runScan(args) {
|
|
|
1228
1256
|
durationMs: timings.total,
|
|
1229
1257
|
});
|
|
1230
1258
|
|
|
1259
|
+
// Submit results to dashboard if connected
|
|
1260
|
+
if (apiConnected && apiScan) {
|
|
1261
|
+
try {
|
|
1262
|
+
await submitScanResults(apiScan.scanId, {
|
|
1263
|
+
verdict: verdict.verdict,
|
|
1264
|
+
score: report.score?.overall || 0,
|
|
1265
|
+
findings: report.findings || [],
|
|
1266
|
+
filesScanned: report.stats?.filesScanned || 0,
|
|
1267
|
+
linesScanned: report.stats?.linesScanned || 0,
|
|
1268
|
+
durationMs: timings.total,
|
|
1269
|
+
metadata: {
|
|
1270
|
+
layers,
|
|
1271
|
+
profile: opts.profile,
|
|
1272
|
+
version: require('../../package.json').version,
|
|
1273
|
+
},
|
|
1274
|
+
});
|
|
1275
|
+
console.log(`${colors.success}ā${ansi.reset} Results sent to dashboard`);
|
|
1276
|
+
} catch (err) {
|
|
1277
|
+
console.log(`${colors.warning}ā ${ansi.reset} Failed to send results to dashboard: ${err.message}`);
|
|
1278
|
+
}
|
|
1279
|
+
}
|
|
1280
|
+
|
|
1231
1281
|
return getExitCodeFromUnified ? getExitCodeFromUnified(verdict) : getExitCode(verdict);
|
|
1232
1282
|
} else {
|
|
1233
1283
|
// Legacy fallback output when unified output system isn't available
|
|
@@ -1316,6 +1366,28 @@ async function runScan(args) {
|
|
|
1316
1366
|
issueCount: criticalCount + warningCount,
|
|
1317
1367
|
durationMs: timings.total,
|
|
1318
1368
|
});
|
|
1369
|
+
|
|
1370
|
+
// Submit results to dashboard if connected
|
|
1371
|
+
if (apiConnected && apiScan) {
|
|
1372
|
+
try {
|
|
1373
|
+
await submitScanResults(apiScan.scanId, {
|
|
1374
|
+
verdict,
|
|
1375
|
+
score: verdict === 'SHIP' ? 100 : verdict === 'WARN' ? 70 : 40,
|
|
1376
|
+
findings: normalizedLegacyFindings,
|
|
1377
|
+
filesScanned: result.stats?.filesScanned || 0,
|
|
1378
|
+
linesScanned: result.stats?.linesScanned || 0,
|
|
1379
|
+
durationMs: timings.total,
|
|
1380
|
+
metadata: {
|
|
1381
|
+
layers,
|
|
1382
|
+
profile: opts.profile,
|
|
1383
|
+
version: require('../../package.json').version,
|
|
1384
|
+
},
|
|
1385
|
+
});
|
|
1386
|
+
console.log(`${colors.success}ā${ansi.reset} Results sent to dashboard`);
|
|
1387
|
+
} catch (err) {
|
|
1388
|
+
console.log(`${colors.warning}ā ${ansi.reset} Failed to send results to dashboard: ${err.message}`);
|
|
1389
|
+
}
|
|
1390
|
+
}
|
|
1319
1391
|
|
|
1320
1392
|
return verdict === 'SHIP' ? 0 : verdict === 'WARN' ? 1 : 2;
|
|
1321
1393
|
}
|
|
@@ -1334,6 +1406,16 @@ async function runScan(args) {
|
|
|
1334
1406
|
errorMessage: error.message,
|
|
1335
1407
|
durationMs: Date.now() - startTime,
|
|
1336
1408
|
});
|
|
1409
|
+
|
|
1410
|
+
// Report error to dashboard if connected
|
|
1411
|
+
if (apiConnected && apiScan) {
|
|
1412
|
+
try {
|
|
1413
|
+
await reportScanError(apiScan.scanId, error);
|
|
1414
|
+
console.log(`${colors.info}š”${ansi.reset} Error reported to dashboard`);
|
|
1415
|
+
} catch (err) {
|
|
1416
|
+
console.log(`${colors.warning}ā ${ansi.reset} Failed to report error to dashboard: ${err.message}`);
|
|
1417
|
+
}
|
|
1418
|
+
}
|
|
1337
1419
|
|
|
1338
1420
|
return exitCode;
|
|
1339
1421
|
}
|
package/bin/vibecheck.js
CHANGED
|
@@ -1123,35 +1123,60 @@ async function main() {
|
|
|
1123
1123
|
process.env.VIBECHECK_LOCAL === '1';
|
|
1124
1124
|
|
|
1125
1125
|
// Auth check (unless skipAuth or offline mode)
|
|
1126
|
-
|
|
1126
|
+
// Only allow login, logout, whoami, and help without auth
|
|
1127
|
+
const authExemptCommands = ['login', 'logout', 'whoami', 'help', '--help', '-h', 'version', '--version'];
|
|
1128
|
+
const needsAuth = !authExemptCommands.includes(cmd) && !cmdDef.skipAuth && !isOffline;
|
|
1129
|
+
|
|
1130
|
+
if (needsAuth) {
|
|
1127
1131
|
const auth = getAuthModule();
|
|
1128
1132
|
const { key } = auth.getApiKey();
|
|
1129
1133
|
authInfo.key = key;
|
|
1130
1134
|
|
|
1135
|
+
// If no API key, prompt for login
|
|
1136
|
+
if (!key) {
|
|
1137
|
+
console.log(`\n ${c.red}ā Authentication Required${c.reset}`);
|
|
1138
|
+
console.log(` Please log in to use vibecheck.\n`);
|
|
1139
|
+
console.log(` ${c.cyan}Options:${c.reset}`);
|
|
1140
|
+
console.log(` 1. Press ${c.yellow}Enter${c.reset} to open browser and sign up`);
|
|
1141
|
+
console.log(` 2. Visit ${c.underline}https://vibecheckai.dev${c.reset} directly`);
|
|
1142
|
+
console.log(` 3. Run ${c.cyan}vibecheck login${c.reset} after getting your API key\n`);
|
|
1143
|
+
|
|
1144
|
+
// Wait for Enter key
|
|
1145
|
+
const readline = getReadline();
|
|
1146
|
+
readline.createInterface({
|
|
1147
|
+
input: process.stdin,
|
|
1148
|
+
output: process.stdout
|
|
1149
|
+
}).question('', async () => {
|
|
1150
|
+
try {
|
|
1151
|
+
const https = getHttps();
|
|
1152
|
+
const url = 'https://vibecheckai.dev';
|
|
1153
|
+
console.log(`\n Opening ${c.underline}${url}${c.reset} in your browser...\n`);
|
|
1154
|
+
|
|
1155
|
+
// Try to open browser
|
|
1156
|
+
const start = process.platform === 'darwin' ? 'open' :
|
|
1157
|
+
process.platform === 'win32' ? 'start' : 'xdg-open';
|
|
1158
|
+
require('child_process').exec(`${start} ${url}`);
|
|
1159
|
+
} catch (e) {
|
|
1160
|
+
console.log(` Could not open browser. Please visit: ${c.underline}https://vibecheckai.dev${c.reset}`);
|
|
1161
|
+
}
|
|
1162
|
+
process.exit(0);
|
|
1163
|
+
});
|
|
1164
|
+
|
|
1165
|
+
// Keep process alive
|
|
1166
|
+
return new Promise(() => {});
|
|
1167
|
+
}
|
|
1168
|
+
|
|
1131
1169
|
const access = await checkCommandAccess(cmd, cmdArgs, authInfo);
|
|
1132
1170
|
|
|
1133
1171
|
if (!access.allowed) {
|
|
1134
1172
|
console.log(access.reason);
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
if (access.downgrade && !config.quiet) {
|
|
1140
|
-
const upsell = getUpsell();
|
|
1141
|
-
console.log(upsell.formatDowngrade(cmd, {
|
|
1142
|
-
currentTier: access.tier,
|
|
1143
|
-
effectiveMode: access.downgrade,
|
|
1144
|
-
caps: access.caps,
|
|
1145
|
-
}));
|
|
1146
|
-
}
|
|
1147
|
-
|
|
1148
|
-
// Tier badge
|
|
1149
|
-
if (!config.quiet && !config.noBanner) {
|
|
1150
|
-
if (access.tier === "pro") {
|
|
1151
|
-
console.log(`${c.magenta}${sym.arrowRight} PRO${c.reset} ${c.dim}feature${c.reset}`);
|
|
1152
|
-
} else if (access.tier === "complete") {
|
|
1153
|
-
console.log(`${c.yellow}${sym.arrowRight} COMPLETE${c.reset} ${c.dim}feature${c.reset}`);
|
|
1173
|
+
|
|
1174
|
+
// Show upgrade prompt if tier insufficient
|
|
1175
|
+
if (access.upgradeUrl) {
|
|
1176
|
+
console.log(`\n ${c.cyan}Upgrade:${c.reset} ${access.upgradeUrl}`);
|
|
1154
1177
|
}
|
|
1178
|
+
|
|
1179
|
+
return 1;
|
|
1155
1180
|
}
|
|
1156
1181
|
|
|
1157
1182
|
authInfo.access = access;
|
package/mcp-server/index.js
CHANGED
|
@@ -33,6 +33,15 @@ import { fileURLToPath } from "url";
|
|
|
33
33
|
import { execFile } from "child_process";
|
|
34
34
|
import { promisify } from "util";
|
|
35
35
|
|
|
36
|
+
// Import API client for dashboard integration
|
|
37
|
+
const {
|
|
38
|
+
createScan,
|
|
39
|
+
updateScanProgress,
|
|
40
|
+
submitScanResults,
|
|
41
|
+
reportScanError,
|
|
42
|
+
isApiAvailable
|
|
43
|
+
} = require("./lib/api-client");
|
|
44
|
+
|
|
36
45
|
const execFileAsync = promisify(execFile);
|
|
37
46
|
|
|
38
47
|
const __filename = fileURLToPath(import.meta.url);
|
|
@@ -1360,6 +1369,27 @@ class VibecheckMCP {
|
|
|
1360
1369
|
const profile = args?.profile || "quick";
|
|
1361
1370
|
const only = args?.only;
|
|
1362
1371
|
|
|
1372
|
+
// Initialize API integration
|
|
1373
|
+
let apiScan = null;
|
|
1374
|
+
let apiConnected = false;
|
|
1375
|
+
|
|
1376
|
+
// Try to connect to API for dashboard integration
|
|
1377
|
+
try {
|
|
1378
|
+
apiConnected = await isApiAvailable();
|
|
1379
|
+
if (apiConnected) {
|
|
1380
|
+
// Create scan record in dashboard
|
|
1381
|
+
apiScan = await createScan({
|
|
1382
|
+
localPath: projectPath,
|
|
1383
|
+
branch: 'main',
|
|
1384
|
+
enableLLM: false,
|
|
1385
|
+
});
|
|
1386
|
+
console.error(`[MCP] Connected to dashboard (Scan ID: ${apiScan.scanId})`);
|
|
1387
|
+
}
|
|
1388
|
+
} catch (err) {
|
|
1389
|
+
// API connection is optional, continue without it
|
|
1390
|
+
console.error(`[MCP] Dashboard integration unavailable: ${err.message}`);
|
|
1391
|
+
}
|
|
1392
|
+
|
|
1363
1393
|
let output = "# š vibecheck Scan\n\n";
|
|
1364
1394
|
output += `**Profile:** ${profile}\n`;
|
|
1365
1395
|
output += `**Path:** ${projectPath}\n\n`;
|
|
@@ -1375,6 +1405,28 @@ class VibecheckMCP {
|
|
|
1375
1405
|
const summary = await this.parseSummaryFromDisk(projectPath);
|
|
1376
1406
|
if (summary) {
|
|
1377
1407
|
output += this.formatScanOutput(summary, projectPath);
|
|
1408
|
+
|
|
1409
|
+
// Submit results to dashboard if connected
|
|
1410
|
+
if (apiConnected && apiScan) {
|
|
1411
|
+
try {
|
|
1412
|
+
await submitScanResults(apiScan.scanId, {
|
|
1413
|
+
verdict: summary.verdict || 'UNKNOWN',
|
|
1414
|
+
score: summary.score?.overall || 0,
|
|
1415
|
+
findings: summary.findings || [],
|
|
1416
|
+
filesScanned: summary.stats?.filesScanned || 0,
|
|
1417
|
+
linesScanned: summary.stats?.linesScanned || 0,
|
|
1418
|
+
durationMs: summary.timings?.total || 0,
|
|
1419
|
+
metadata: {
|
|
1420
|
+
profile,
|
|
1421
|
+
source: 'mcp-server',
|
|
1422
|
+
version: CONFIG.VERSION,
|
|
1423
|
+
},
|
|
1424
|
+
});
|
|
1425
|
+
console.error(`[MCP] Results sent to dashboard`);
|
|
1426
|
+
} catch (err) {
|
|
1427
|
+
console.error(`[MCP] Failed to send results to dashboard: ${err.message}`);
|
|
1428
|
+
}
|
|
1429
|
+
}
|
|
1378
1430
|
}
|
|
1379
1431
|
output += "\n---\n_Context Enhanced by vibecheck AI_\n";
|
|
1380
1432
|
return this.success(output);
|
|
@@ -1383,10 +1435,43 @@ class VibecheckMCP {
|
|
|
1383
1435
|
const summary = await this.parseSummaryFromDisk(projectPath);
|
|
1384
1436
|
if (summary) {
|
|
1385
1437
|
output += this.formatScanOutput(summary, projectPath);
|
|
1438
|
+
|
|
1439
|
+
// Submit results to dashboard if connected
|
|
1440
|
+
if (apiConnected && apiScan) {
|
|
1441
|
+
try {
|
|
1442
|
+
await submitScanResults(apiScan.scanId, {
|
|
1443
|
+
verdict: summary.verdict || 'UNKNOWN',
|
|
1444
|
+
score: summary.score?.overall || 0,
|
|
1445
|
+
findings: summary.findings || [],
|
|
1446
|
+
filesScanned: summary.stats?.filesScanned || 0,
|
|
1447
|
+
linesScanned: summary.stats?.linesScanned || 0,
|
|
1448
|
+
durationMs: summary.timings?.total || 0,
|
|
1449
|
+
metadata: {
|
|
1450
|
+
profile,
|
|
1451
|
+
source: 'mcp-server',
|
|
1452
|
+
version: CONFIG.VERSION,
|
|
1453
|
+
error: err.message,
|
|
1454
|
+
},
|
|
1455
|
+
});
|
|
1456
|
+
console.error(`[MCP] Results sent to dashboard (with error)`);
|
|
1457
|
+
} catch (err) {
|
|
1458
|
+
console.error(`[MCP] Failed to send results to dashboard: ${err.message}`);
|
|
1459
|
+
}
|
|
1460
|
+
}
|
|
1386
1461
|
output += `\nā ļø Scan completed with findings (exit code ${err.code || 1})\n`;
|
|
1387
1462
|
return this.success(output);
|
|
1388
1463
|
}
|
|
1389
1464
|
|
|
1465
|
+
// Report error to dashboard if connected
|
|
1466
|
+
if (apiConnected && apiScan) {
|
|
1467
|
+
try {
|
|
1468
|
+
await reportScanError(apiScan.scanId, err);
|
|
1469
|
+
console.error(`[MCP] Error reported to dashboard`);
|
|
1470
|
+
} catch (err) {
|
|
1471
|
+
console.error(`[MCP] Failed to report error to dashboard: ${err.message}`);
|
|
1472
|
+
}
|
|
1473
|
+
}
|
|
1474
|
+
|
|
1390
1475
|
return this.error(`Scan failed: ${err.message}`, {
|
|
1391
1476
|
code: "SCAN_ERROR",
|
|
1392
1477
|
suggestion: "Check that the project path is valid and contains scanable code",
|