@vibecheckai/cli 3.2.5 → 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/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 +108 -103
- package/mcp-server/tools/index.js +72 -72
- 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/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",
|