@quantracode/vibecheck 0.0.1 → 0.0.2
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 +6 -6
- package/dist/index.d.ts +0 -2
- package/dist/index.js +7902 -8
- package/package.json +13 -7
- package/dist/__tests__/cli.test.d.ts +0 -2
- package/dist/__tests__/cli.test.d.ts.map +0 -1
- package/dist/__tests__/cli.test.js +0 -243
- package/dist/__tests__/fixtures/safe-app/app/api/users/route.js +0 -36
- package/dist/__tests__/fixtures/vulnerable-app/app/api/users/route.js +0 -28
- package/dist/__tests__/fixtures/vulnerable-app/lib/config.d.ts +0 -4
- package/dist/__tests__/fixtures/vulnerable-app/lib/config.d.ts.map +0 -1
- package/dist/__tests__/fixtures/vulnerable-app/lib/config.js +0 -6
- package/dist/__tests__/scanners/env-config.test.d.ts +0 -2
- package/dist/__tests__/scanners/env-config.test.d.ts.map +0 -1
- package/dist/__tests__/scanners/env-config.test.js +0 -142
- package/dist/__tests__/scanners/nextjs-middleware.test.d.ts +0 -2
- package/dist/__tests__/scanners/nextjs-middleware.test.d.ts.map +0 -1
- package/dist/__tests__/scanners/nextjs-middleware.test.js +0 -193
- package/dist/__tests__/scanners/scanner-packs.test.d.ts +0 -2
- package/dist/__tests__/scanners/scanner-packs.test.d.ts.map +0 -1
- package/dist/__tests__/scanners/scanner-packs.test.js +0 -126
- package/dist/__tests__/scanners/unused-security-imports.test.d.ts +0 -2
- package/dist/__tests__/scanners/unused-security-imports.test.d.ts.map +0 -1
- package/dist/__tests__/scanners/unused-security-imports.test.js +0 -145
- package/dist/commands/demo-artifact.d.ts +0 -7
- package/dist/commands/demo-artifact.d.ts.map +0 -1
- package/dist/commands/demo-artifact.js +0 -322
- package/dist/commands/evaluate.d.ts +0 -30
- package/dist/commands/evaluate.d.ts.map +0 -1
- package/dist/commands/evaluate.js +0 -258
- package/dist/commands/explain.d.ts +0 -12
- package/dist/commands/explain.d.ts.map +0 -1
- package/dist/commands/explain.js +0 -214
- package/dist/commands/index.d.ts +0 -7
- package/dist/commands/index.d.ts.map +0 -1
- package/dist/commands/index.js +0 -6
- package/dist/commands/intent.d.ts +0 -21
- package/dist/commands/intent.d.ts.map +0 -1
- package/dist/commands/intent.js +0 -192
- package/dist/commands/scan.d.ts +0 -44
- package/dist/commands/scan.d.ts.map +0 -1
- package/dist/commands/scan.js +0 -497
- package/dist/commands/waivers.d.ts +0 -30
- package/dist/commands/waivers.d.ts.map +0 -1
- package/dist/commands/waivers.js +0 -249
- package/dist/index.d.ts.map +0 -1
- package/dist/phase3/index.d.ts +0 -11
- package/dist/phase3/index.d.ts.map +0 -1
- package/dist/phase3/index.js +0 -12
- package/dist/phase3/intent-miner.d.ts +0 -32
- package/dist/phase3/intent-miner.d.ts.map +0 -1
- package/dist/phase3/intent-miner.js +0 -323
- package/dist/phase3/proof-trace-builder.d.ts +0 -42
- package/dist/phase3/proof-trace-builder.d.ts.map +0 -1
- package/dist/phase3/proof-trace-builder.js +0 -441
- package/dist/phase3/scanners/auth-by-ui-server-gap.d.ts +0 -15
- package/dist/phase3/scanners/auth-by-ui-server-gap.d.ts.map +0 -1
- package/dist/phase3/scanners/auth-by-ui-server-gap.js +0 -237
- package/dist/phase3/scanners/comment-claim-unproven.d.ts +0 -14
- package/dist/phase3/scanners/comment-claim-unproven.d.ts.map +0 -1
- package/dist/phase3/scanners/comment-claim-unproven.js +0 -161
- package/dist/phase3/scanners/index.d.ts +0 -31
- package/dist/phase3/scanners/index.d.ts.map +0 -1
- package/dist/phase3/scanners/index.js +0 -40
- package/dist/phase3/scanners/middleware-assumed-not-matching.d.ts +0 -14
- package/dist/phase3/scanners/middleware-assumed-not-matching.d.ts.map +0 -1
- package/dist/phase3/scanners/middleware-assumed-not-matching.js +0 -172
- package/dist/phase3/scanners/validation-claimed-missing.d.ts +0 -15
- package/dist/phase3/scanners/validation-claimed-missing.d.ts.map +0 -1
- package/dist/phase3/scanners/validation-claimed-missing.js +0 -204
- package/dist/scanners/abuse/compute-abuse.d.ts +0 -20
- package/dist/scanners/abuse/compute-abuse.d.ts.map +0 -1
- package/dist/scanners/abuse/compute-abuse.js +0 -509
- package/dist/scanners/abuse/index.d.ts +0 -12
- package/dist/scanners/abuse/index.d.ts.map +0 -1
- package/dist/scanners/abuse/index.js +0 -15
- package/dist/scanners/auth/index.d.ts +0 -5
- package/dist/scanners/auth/index.d.ts.map +0 -1
- package/dist/scanners/auth/index.js +0 -10
- package/dist/scanners/auth/middleware-gap.d.ts +0 -22
- package/dist/scanners/auth/middleware-gap.d.ts.map +0 -1
- package/dist/scanners/auth/middleware-gap.js +0 -203
- package/dist/scanners/auth/unprotected-api-route.d.ts +0 -12
- package/dist/scanners/auth/unprotected-api-route.d.ts.map +0 -1
- package/dist/scanners/auth/unprotected-api-route.js +0 -126
- package/dist/scanners/config/index.d.ts +0 -5
- package/dist/scanners/config/index.d.ts.map +0 -1
- package/dist/scanners/config/index.js +0 -10
- package/dist/scanners/config/insecure-defaults.d.ts +0 -12
- package/dist/scanners/config/insecure-defaults.d.ts.map +0 -1
- package/dist/scanners/config/insecure-defaults.js +0 -77
- package/dist/scanners/config/undocumented-env.d.ts +0 -24
- package/dist/scanners/config/undocumented-env.d.ts.map +0 -1
- package/dist/scanners/config/undocumented-env.js +0 -159
- package/dist/scanners/crypto/index.d.ts +0 -6
- package/dist/scanners/crypto/index.d.ts.map +0 -1
- package/dist/scanners/crypto/index.js +0 -11
- package/dist/scanners/crypto/jwt-decode-unverified.d.ts +0 -14
- package/dist/scanners/crypto/jwt-decode-unverified.d.ts.map +0 -1
- package/dist/scanners/crypto/jwt-decode-unverified.js +0 -87
- package/dist/scanners/crypto/math-random-tokens.d.ts +0 -13
- package/dist/scanners/crypto/math-random-tokens.d.ts.map +0 -1
- package/dist/scanners/crypto/math-random-tokens.js +0 -80
- package/dist/scanners/crypto/weak-hashing.d.ts +0 -11
- package/dist/scanners/crypto/weak-hashing.d.ts.map +0 -1
- package/dist/scanners/crypto/weak-hashing.js +0 -95
- package/dist/scanners/env-config.d.ts +0 -24
- package/dist/scanners/env-config.d.ts.map +0 -1
- package/dist/scanners/env-config.js +0 -164
- package/dist/scanners/hallucinations/index.d.ts +0 -4
- package/dist/scanners/hallucinations/index.d.ts.map +0 -1
- package/dist/scanners/hallucinations/index.js +0 -8
- package/dist/scanners/hallucinations/unused-security-imports.d.ts +0 -36
- package/dist/scanners/hallucinations/unused-security-imports.d.ts.map +0 -1
- package/dist/scanners/hallucinations/unused-security-imports.js +0 -309
- package/dist/scanners/helpers/ast-helpers.d.ts +0 -6
- package/dist/scanners/helpers/ast-helpers.d.ts.map +0 -1
- package/dist/scanners/helpers/ast-helpers.js +0 -945
- package/dist/scanners/helpers/context-builder.d.ts +0 -17
- package/dist/scanners/helpers/context-builder.d.ts.map +0 -1
- package/dist/scanners/helpers/context-builder.js +0 -148
- package/dist/scanners/helpers/index.d.ts +0 -3
- package/dist/scanners/helpers/index.d.ts.map +0 -1
- package/dist/scanners/helpers/index.js +0 -2
- package/dist/scanners/index.d.ts +0 -30
- package/dist/scanners/index.d.ts.map +0 -1
- package/dist/scanners/index.js +0 -102
- package/dist/scanners/middleware/index.d.ts +0 -4
- package/dist/scanners/middleware/index.d.ts.map +0 -1
- package/dist/scanners/middleware/index.js +0 -7
- package/dist/scanners/middleware/missing-rate-limit.d.ts +0 -13
- package/dist/scanners/middleware/missing-rate-limit.d.ts.map +0 -1
- package/dist/scanners/middleware/missing-rate-limit.js +0 -140
- package/dist/scanners/network/cors-misconfiguration.d.ts +0 -14
- package/dist/scanners/network/cors-misconfiguration.d.ts.map +0 -1
- package/dist/scanners/network/cors-misconfiguration.js +0 -89
- package/dist/scanners/network/index.d.ts +0 -7
- package/dist/scanners/network/index.d.ts.map +0 -1
- package/dist/scanners/network/index.js +0 -18
- package/dist/scanners/network/missing-timeout.d.ts +0 -15
- package/dist/scanners/network/missing-timeout.d.ts.map +0 -1
- package/dist/scanners/network/missing-timeout.js +0 -93
- package/dist/scanners/network/open-redirect.d.ts +0 -15
- package/dist/scanners/network/open-redirect.d.ts.map +0 -1
- package/dist/scanners/network/open-redirect.js +0 -88
- package/dist/scanners/network/ssrf-prone-fetch.d.ts +0 -12
- package/dist/scanners/network/ssrf-prone-fetch.d.ts.map +0 -1
- package/dist/scanners/network/ssrf-prone-fetch.js +0 -90
- package/dist/scanners/nextjs-middleware.d.ts +0 -26
- package/dist/scanners/nextjs-middleware.d.ts.map +0 -1
- package/dist/scanners/nextjs-middleware.js +0 -246
- package/dist/scanners/privacy/debug-flags.d.ts +0 -13
- package/dist/scanners/privacy/debug-flags.d.ts.map +0 -1
- package/dist/scanners/privacy/debug-flags.js +0 -124
- package/dist/scanners/privacy/index.d.ts +0 -6
- package/dist/scanners/privacy/index.d.ts.map +0 -1
- package/dist/scanners/privacy/index.js +0 -11
- package/dist/scanners/privacy/over-broad-response.d.ts +0 -15
- package/dist/scanners/privacy/over-broad-response.d.ts.map +0 -1
- package/dist/scanners/privacy/over-broad-response.js +0 -109
- package/dist/scanners/privacy/sensitive-logging.d.ts +0 -11
- package/dist/scanners/privacy/sensitive-logging.d.ts.map +0 -1
- package/dist/scanners/privacy/sensitive-logging.js +0 -78
- package/dist/scanners/types.d.ts +0 -456
- package/dist/scanners/types.d.ts.map +0 -1
- package/dist/scanners/types.js +0 -16
- package/dist/scanners/unused-security-imports.d.ts +0 -34
- package/dist/scanners/unused-security-imports.d.ts.map +0 -1
- package/dist/scanners/unused-security-imports.js +0 -206
- package/dist/scanners/uploads/index.d.ts +0 -5
- package/dist/scanners/uploads/index.d.ts.map +0 -1
- package/dist/scanners/uploads/index.js +0 -9
- package/dist/scanners/uploads/missing-constraints.d.ts +0 -15
- package/dist/scanners/uploads/missing-constraints.d.ts.map +0 -1
- package/dist/scanners/uploads/missing-constraints.js +0 -109
- package/dist/scanners/uploads/public-path.d.ts +0 -11
- package/dist/scanners/uploads/public-path.d.ts.map +0 -1
- package/dist/scanners/uploads/public-path.js +0 -87
- package/dist/scanners/validation/client-side-only.d.ts +0 -14
- package/dist/scanners/validation/client-side-only.d.ts.map +0 -1
- package/dist/scanners/validation/client-side-only.js +0 -140
- package/dist/scanners/validation/ignored-validation.d.ts +0 -12
- package/dist/scanners/validation/ignored-validation.d.ts.map +0 -1
- package/dist/scanners/validation/ignored-validation.js +0 -119
- package/dist/scanners/validation/index.d.ts +0 -5
- package/dist/scanners/validation/index.d.ts.map +0 -1
- package/dist/scanners/validation/index.js +0 -9
- package/dist/utils/exclude-patterns.d.ts +0 -35
- package/dist/utils/exclude-patterns.d.ts.map +0 -1
- package/dist/utils/exclude-patterns.js +0 -78
- package/dist/utils/file-utils.d.ts +0 -37
- package/dist/utils/file-utils.d.ts.map +0 -1
- package/dist/utils/file-utils.js +0 -77
- package/dist/utils/fingerprint.d.ts +0 -25
- package/dist/utils/fingerprint.d.ts.map +0 -1
- package/dist/utils/fingerprint.js +0 -28
- package/dist/utils/git-info.d.ts +0 -14
- package/dist/utils/git-info.d.ts.map +0 -1
- package/dist/utils/git-info.js +0 -55
- package/dist/utils/index.d.ts +0 -4
- package/dist/utils/index.d.ts.map +0 -1
- package/dist/utils/index.js +0 -3
- package/dist/utils/progress.d.ts +0 -42
- package/dist/utils/progress.d.ts.map +0 -1
- package/dist/utils/progress.js +0 -165
- package/dist/utils/sarif-formatter.d.ts +0 -92
- package/dist/utils/sarif-formatter.d.ts.map +0 -1
- package/dist/utils/sarif-formatter.js +0 -172
package/dist/commands/explain.js
DELETED
|
@@ -1,214 +0,0 @@
|
|
|
1
|
-
import { validateArtifact, } from "@vibecheck/schema";
|
|
2
|
-
import { readFileSync, resolvePath } from "../utils/file-utils.js";
|
|
3
|
-
/**
|
|
4
|
-
* Format severity for console output with color
|
|
5
|
-
*/
|
|
6
|
-
function formatSeverity(severity) {
|
|
7
|
-
const colors = {
|
|
8
|
-
critical: "\x1b[35m", // Magenta
|
|
9
|
-
high: "\x1b[31m", // Red
|
|
10
|
-
medium: "\x1b[33m", // Yellow
|
|
11
|
-
low: "\x1b[36m", // Cyan
|
|
12
|
-
info: "\x1b[90m", // Gray
|
|
13
|
-
};
|
|
14
|
-
const reset = "\x1b[0m";
|
|
15
|
-
return `${colors[severity]}${severity.toUpperCase().padEnd(8)}${reset}`;
|
|
16
|
-
}
|
|
17
|
-
/**
|
|
18
|
-
* Format category for display
|
|
19
|
-
*/
|
|
20
|
-
function formatCategory(category) {
|
|
21
|
-
return `\x1b[34m${category}\x1b[0m`;
|
|
22
|
-
}
|
|
23
|
-
/**
|
|
24
|
-
* Print a horizontal divider
|
|
25
|
-
*/
|
|
26
|
-
function divider(char = "-", length = 70) {
|
|
27
|
-
return char.repeat(length);
|
|
28
|
-
}
|
|
29
|
-
/**
|
|
30
|
-
* Print artifact summary
|
|
31
|
-
*/
|
|
32
|
-
function printSummary(artifact) {
|
|
33
|
-
const { summary, tool, repo, generatedAt, metrics } = artifact;
|
|
34
|
-
console.log("\n" + divider("="));
|
|
35
|
-
console.log("VIBECHECK SCAN REPORT");
|
|
36
|
-
console.log(divider("="));
|
|
37
|
-
console.log(`\nTool: ${tool.name} v${tool.version}`);
|
|
38
|
-
if (repo) {
|
|
39
|
-
console.log(`Repository: ${repo.name}`);
|
|
40
|
-
if (repo.git?.branch) {
|
|
41
|
-
console.log(`Branch: ${repo.git.branch}`);
|
|
42
|
-
}
|
|
43
|
-
if (repo.git?.commit) {
|
|
44
|
-
console.log(`Commit: ${repo.git.commit.slice(0, 8)}`);
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
console.log(`Generated: ${new Date(generatedAt).toLocaleString()}`);
|
|
48
|
-
if (metrics) {
|
|
49
|
-
console.log(`\nScan Metrics:`);
|
|
50
|
-
console.log(` Files scanned: ${metrics.filesScanned}`);
|
|
51
|
-
console.log(` Duration: ${metrics.scanDurationMs.toFixed(0)}ms`);
|
|
52
|
-
console.log(` Rules run: ${metrics.rulesExecuted}`);
|
|
53
|
-
}
|
|
54
|
-
console.log(`\n${divider()}`);
|
|
55
|
-
console.log("SUMMARY");
|
|
56
|
-
console.log(divider());
|
|
57
|
-
console.log(`\nTotal Findings: ${summary.totalFindings}`);
|
|
58
|
-
if (summary.totalFindings > 0) {
|
|
59
|
-
console.log("\nBy Severity:");
|
|
60
|
-
const severities = ["critical", "high", "medium", "low", "info"];
|
|
61
|
-
for (const sev of severities) {
|
|
62
|
-
const count = summary.bySeverity[sev];
|
|
63
|
-
if (count > 0) {
|
|
64
|
-
const bar = "\u2588".repeat(Math.min(count * 2, 40));
|
|
65
|
-
console.log(` ${formatSeverity(sev)} ${count.toString().padStart(3)} ${bar}`);
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
console.log("\nBy Category:");
|
|
69
|
-
const categories = Object.entries(summary.byCategory)
|
|
70
|
-
.filter(([, count]) => count > 0)
|
|
71
|
-
.sort(([, a], [, b]) => b - a);
|
|
72
|
-
for (const [cat, count] of categories) {
|
|
73
|
-
console.log(` ${formatCategory(cat.padEnd(12))} ${count}`);
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
/**
|
|
78
|
-
* Sort findings by severity (highest first)
|
|
79
|
-
*/
|
|
80
|
-
function sortBySeverity(findings) {
|
|
81
|
-
const order = {
|
|
82
|
-
critical: 4,
|
|
83
|
-
high: 3,
|
|
84
|
-
medium: 2,
|
|
85
|
-
low: 1,
|
|
86
|
-
info: 0,
|
|
87
|
-
};
|
|
88
|
-
return [...findings].sort((a, b) => order[b.severity] - order[a.severity]);
|
|
89
|
-
}
|
|
90
|
-
/**
|
|
91
|
-
* Print detailed finding information
|
|
92
|
-
*/
|
|
93
|
-
function printFinding(finding, index) {
|
|
94
|
-
console.log(`\n${divider()}`);
|
|
95
|
-
console.log(`FINDING #${index + 1}: ${finding.title}`);
|
|
96
|
-
console.log(divider());
|
|
97
|
-
console.log(`\nSeverity: ${formatSeverity(finding.severity)}`);
|
|
98
|
-
console.log(`Category: ${formatCategory(finding.category)}`);
|
|
99
|
-
console.log(`Rule: ${finding.ruleId}`);
|
|
100
|
-
console.log(`Confidence: ${(finding.confidence * 100).toFixed(0)}%`);
|
|
101
|
-
console.log(`ID: ${finding.id}`);
|
|
102
|
-
console.log(`\nDescription:`);
|
|
103
|
-
console.log(` ${finding.description}`);
|
|
104
|
-
console.log(`\nEvidence:`);
|
|
105
|
-
for (const ev of finding.evidence) {
|
|
106
|
-
console.log(` - ${ev.file}:${ev.startLine}-${ev.endLine}`);
|
|
107
|
-
console.log(` ${ev.label}`);
|
|
108
|
-
if (ev.snippet) {
|
|
109
|
-
console.log(` \x1b[90m${ev.snippet}\x1b[0m`);
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
if (finding.claim) {
|
|
113
|
-
console.log(`\nClaim:`);
|
|
114
|
-
console.log(` Type: ${finding.claim.type}`);
|
|
115
|
-
console.log(` Source: ${finding.claim.source}`);
|
|
116
|
-
console.log(` Strength: ${finding.claim.strength}`);
|
|
117
|
-
console.log(` Evidence: "${finding.claim.textEvidence}"`);
|
|
118
|
-
}
|
|
119
|
-
if (finding.proof) {
|
|
120
|
-
console.log(`\nProof Trace:`);
|
|
121
|
-
console.log(` ${finding.proof.summary}`);
|
|
122
|
-
for (const node of finding.proof.nodes) {
|
|
123
|
-
const loc = node.file ? ` (${node.file}:${node.line})` : "";
|
|
124
|
-
console.log(` [${node.kind}] ${node.label}${loc}`);
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
console.log(`\nRemediation:`);
|
|
128
|
-
console.log(` ${finding.remediation.recommendedFix}`);
|
|
129
|
-
if (finding.remediation.patch) {
|
|
130
|
-
console.log(`\n Suggested patch:`);
|
|
131
|
-
console.log(` \x1b[90m${finding.remediation.patch}\x1b[0m`);
|
|
132
|
-
}
|
|
133
|
-
if (finding.links) {
|
|
134
|
-
console.log(`\nReferences:`);
|
|
135
|
-
if (finding.links.owasp) {
|
|
136
|
-
console.log(` OWASP: ${finding.links.owasp}`);
|
|
137
|
-
}
|
|
138
|
-
if (finding.links.cwe) {
|
|
139
|
-
console.log(` CWE: ${finding.links.cwe}`);
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
/**
|
|
144
|
-
* Print top findings with details
|
|
145
|
-
*/
|
|
146
|
-
function printTopFindings(artifact, limit) {
|
|
147
|
-
const { findings } = artifact;
|
|
148
|
-
if (findings.length === 0) {
|
|
149
|
-
console.log("\n\x1b[32mNo findings to display.\x1b[0m");
|
|
150
|
-
return;
|
|
151
|
-
}
|
|
152
|
-
const sorted = sortBySeverity(findings);
|
|
153
|
-
const top = sorted.slice(0, limit);
|
|
154
|
-
console.log(`\n${divider("=")}`);
|
|
155
|
-
console.log(`TOP ${top.length} FINDINGS`);
|
|
156
|
-
console.log(divider("="));
|
|
157
|
-
for (let i = 0; i < top.length; i++) {
|
|
158
|
-
printFinding(top[i], i);
|
|
159
|
-
}
|
|
160
|
-
if (findings.length > limit) {
|
|
161
|
-
console.log(`\n${divider()}`);
|
|
162
|
-
console.log(`\x1b[90m... and ${findings.length - limit} more findings\x1b[0m`);
|
|
163
|
-
}
|
|
164
|
-
console.log("");
|
|
165
|
-
}
|
|
166
|
-
/**
|
|
167
|
-
* Execute the explain command
|
|
168
|
-
*/
|
|
169
|
-
export async function executeExplain(artifactPath, options) {
|
|
170
|
-
const absolutePath = resolvePath(artifactPath);
|
|
171
|
-
// Read artifact file
|
|
172
|
-
const content = readFileSync(absolutePath);
|
|
173
|
-
if (!content) {
|
|
174
|
-
console.error(`\x1b[31mError: Could not read file: ${absolutePath}\x1b[0m`);
|
|
175
|
-
return 1;
|
|
176
|
-
}
|
|
177
|
-
// Parse JSON
|
|
178
|
-
let json;
|
|
179
|
-
try {
|
|
180
|
-
json = JSON.parse(content);
|
|
181
|
-
}
|
|
182
|
-
catch {
|
|
183
|
-
console.error(`\x1b[31mError: Invalid JSON in file: ${absolutePath}\x1b[0m`);
|
|
184
|
-
return 1;
|
|
185
|
-
}
|
|
186
|
-
// Validate artifact
|
|
187
|
-
let artifact;
|
|
188
|
-
try {
|
|
189
|
-
artifact = validateArtifact(json);
|
|
190
|
-
}
|
|
191
|
-
catch (error) {
|
|
192
|
-
console.error(`\x1b[31mError: Invalid artifact format\x1b[0m`);
|
|
193
|
-
console.error(error);
|
|
194
|
-
return 1;
|
|
195
|
-
}
|
|
196
|
-
// Print report
|
|
197
|
-
printSummary(artifact);
|
|
198
|
-
printTopFindings(artifact, options.limit);
|
|
199
|
-
return 0;
|
|
200
|
-
}
|
|
201
|
-
/**
|
|
202
|
-
* Register explain command with commander
|
|
203
|
-
*/
|
|
204
|
-
export function registerExplainCommand(program) {
|
|
205
|
-
program
|
|
206
|
-
.command("explain <artifactPath>")
|
|
207
|
-
.description("Display a human-readable summary of a scan artifact")
|
|
208
|
-
.option("-l, --limit <number>", "Maximum findings to display", "5")
|
|
209
|
-
.action(async (artifactPath, options) => {
|
|
210
|
-
const limit = parseInt(options.limit, 10) || 5;
|
|
211
|
-
const exitCode = await executeExplain(artifactPath, { limit });
|
|
212
|
-
process.exit(exitCode);
|
|
213
|
-
});
|
|
214
|
-
}
|
package/dist/commands/index.d.ts
DELETED
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
export { registerScanCommand, executeScan, type ScanOptions } from "./scan.js";
|
|
2
|
-
export { registerExplainCommand, executeExplain } from "./explain.js";
|
|
3
|
-
export { registerDemoArtifactCommand, executeDemoArtifact } from "./demo-artifact.js";
|
|
4
|
-
export { registerIntentCommand, executeIntent, type IntentOptions } from "./intent.js";
|
|
5
|
-
export { registerEvaluateCommand, executeEvaluate, type EvaluateOptions } from "./evaluate.js";
|
|
6
|
-
export { registerWaiversCommand } from "./waivers.js";
|
|
7
|
-
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/commands/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,WAAW,EAAE,KAAK,WAAW,EAAE,MAAM,WAAW,CAAC;AAC/E,OAAO,EAAE,sBAAsB,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AACtE,OAAO,EAAE,2BAA2B,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACtF,OAAO,EAAE,qBAAqB,EAAE,aAAa,EAAE,KAAK,aAAa,EAAE,MAAM,aAAa,CAAC;AACvF,OAAO,EAAE,uBAAuB,EAAE,eAAe,EAAE,KAAK,eAAe,EAAE,MAAM,eAAe,CAAC;AAC/F,OAAO,EAAE,sBAAsB,EAAE,MAAM,cAAc,CAAC"}
|
package/dist/commands/index.js
DELETED
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
export { registerScanCommand, executeScan } from "./scan.js";
|
|
2
|
-
export { registerExplainCommand, executeExplain } from "./explain.js";
|
|
3
|
-
export { registerDemoArtifactCommand, executeDemoArtifact } from "./demo-artifact.js";
|
|
4
|
-
export { registerIntentCommand, executeIntent } from "./intent.js";
|
|
5
|
-
export { registerEvaluateCommand, executeEvaluate } from "./evaluate.js";
|
|
6
|
-
export { registerWaiversCommand } from "./waivers.js";
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Intent Command
|
|
3
|
-
*
|
|
4
|
-
* Generates a security intent map baseline for the codebase.
|
|
5
|
-
* Useful for tracking drift over time.
|
|
6
|
-
*/
|
|
7
|
-
import type { Command } from "commander";
|
|
8
|
-
export interface IntentOptions {
|
|
9
|
-
out: string;
|
|
10
|
-
format: string;
|
|
11
|
-
repoName?: string;
|
|
12
|
-
}
|
|
13
|
-
/**
|
|
14
|
-
* Execute the intent command
|
|
15
|
-
*/
|
|
16
|
-
export declare function executeIntent(targetDir: string, options: IntentOptions): Promise<number>;
|
|
17
|
-
/**
|
|
18
|
-
* Register intent command with commander
|
|
19
|
-
*/
|
|
20
|
-
export declare function registerIntentCommand(program: Command): void;
|
|
21
|
-
//# sourceMappingURL=intent.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"intent.d.ts","sourceRoot":"","sources":["../../src/commands/intent.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAqBzC,MAAM,WAAW,aAAa;IAC5B,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAuCD;;GAEG;AACH,wBAAsB,aAAa,CACjC,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,aAAa,GACrB,OAAO,CAAC,MAAM,CAAC,CA8DjB;AA+ID;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAgB5D"}
|
package/dist/commands/intent.js
DELETED
|
@@ -1,192 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Intent Command
|
|
3
|
-
*
|
|
4
|
-
* Generates a security intent map baseline for the codebase.
|
|
5
|
-
* Useful for tracking drift over time.
|
|
6
|
-
*/
|
|
7
|
-
import path from "node:path";
|
|
8
|
-
import { ARTIFACT_VERSION } from "@vibecheck/schema";
|
|
9
|
-
import { writeFileSync, resolvePath } from "../utils/file-utils.js";
|
|
10
|
-
import { hashPath } from "../utils/fingerprint.js";
|
|
11
|
-
import { getGitInfo, getRepoName } from "../utils/git-info.js";
|
|
12
|
-
import { buildScanContext } from "../scanners/index.js";
|
|
13
|
-
import { buildRouteMap, buildMiddlewareMap, buildAllProofTraces, calculateCoverage, mineAllIntentClaims, } from "../phase3/index.js";
|
|
14
|
-
/**
|
|
15
|
-
* Execute the intent command
|
|
16
|
-
*/
|
|
17
|
-
export async function executeIntent(targetDir, options) {
|
|
18
|
-
const absoluteTarget = resolvePath(targetDir);
|
|
19
|
-
console.log(`Mining intent map: ${absoluteTarget}`);
|
|
20
|
-
const startTime = Date.now();
|
|
21
|
-
// Build scan context
|
|
22
|
-
console.log("Building scan context...");
|
|
23
|
-
const context = await buildScanContext(absoluteTarget);
|
|
24
|
-
console.log(`Found ${context.fileIndex.allSourceFiles.length} source files`);
|
|
25
|
-
// Build Phase 3 maps
|
|
26
|
-
console.log("\nBuilding route map...");
|
|
27
|
-
const routeMap = buildRouteMap(context);
|
|
28
|
-
console.log(` Found ${routeMap.length} routes`);
|
|
29
|
-
console.log("Building middleware map...");
|
|
30
|
-
const middlewareMap = buildMiddlewareMap(context);
|
|
31
|
-
console.log(` Found ${middlewareMap.length} middleware configurations`);
|
|
32
|
-
console.log("Mining intent claims...");
|
|
33
|
-
const intentMap = mineAllIntentClaims(context, routeMap);
|
|
34
|
-
console.log(` Found ${intentMap.length} intent claims`);
|
|
35
|
-
console.log("Building proof traces...");
|
|
36
|
-
const proofTraces = buildAllProofTraces(context, routeMap);
|
|
37
|
-
console.log(` Built ${proofTraces.size} proof traces`);
|
|
38
|
-
console.log("Calculating coverage...");
|
|
39
|
-
const coverage = calculateCoverage(routeMap, proofTraces, middlewareMap);
|
|
40
|
-
const endTime = Date.now();
|
|
41
|
-
console.log(`\nCompleted in ${endTime - startTime}ms`);
|
|
42
|
-
// Create artifact
|
|
43
|
-
const artifact = createIntentArtifact(routeMap, middlewareMap, intentMap, proofTraces, coverage, absoluteTarget, options.repoName);
|
|
44
|
-
// Determine output path
|
|
45
|
-
let outputPath = options.out;
|
|
46
|
-
if (!path.isAbsolute(outputPath)) {
|
|
47
|
-
outputPath = resolvePath(absoluteTarget, outputPath);
|
|
48
|
-
}
|
|
49
|
-
// Write artifact
|
|
50
|
-
if (options.format === "json") {
|
|
51
|
-
writeFileSync(outputPath, JSON.stringify(artifact, null, 2));
|
|
52
|
-
console.log(`\nIntent map written to: ${outputPath}`);
|
|
53
|
-
}
|
|
54
|
-
// Print summary
|
|
55
|
-
printIntentSummary(artifact);
|
|
56
|
-
return 0;
|
|
57
|
-
}
|
|
58
|
-
/**
|
|
59
|
-
* Create intent map artifact
|
|
60
|
-
*/
|
|
61
|
-
function createIntentArtifact(routeMap, middlewareMap, intentMap, proofTraces, coverage, targetDir, repoName) {
|
|
62
|
-
const gitInfo = getGitInfo(targetDir);
|
|
63
|
-
const name = repoName ?? getRepoName(targetDir);
|
|
64
|
-
// Convert proofTraces Map to schema format
|
|
65
|
-
const proofTracesRecord = {};
|
|
66
|
-
for (const [key, value] of proofTraces) {
|
|
67
|
-
proofTracesRecord[key] = {
|
|
68
|
-
summary: value.authProven
|
|
69
|
-
? "Auth proven"
|
|
70
|
-
: value.middlewareCovered
|
|
71
|
-
? "Protected by middleware"
|
|
72
|
-
: "No protection proven",
|
|
73
|
-
nodes: value.steps.map((step) => ({
|
|
74
|
-
kind: "handler",
|
|
75
|
-
label: step.label,
|
|
76
|
-
file: step.file,
|
|
77
|
-
line: step.line,
|
|
78
|
-
})),
|
|
79
|
-
};
|
|
80
|
-
}
|
|
81
|
-
// Build middleware coverage
|
|
82
|
-
const allMatchers = middlewareMap.flatMap((m) => m.matchers);
|
|
83
|
-
const middlewareCoverage = routeMap.map((route) => {
|
|
84
|
-
const isRouteCovered = allMatchers.some((matcher) => {
|
|
85
|
-
const pattern = matcher.replace(/\*/g, ".*").replace(/\/:path\*/g, "/.*");
|
|
86
|
-
try {
|
|
87
|
-
return new RegExp(`^${pattern}`).test(route.path);
|
|
88
|
-
}
|
|
89
|
-
catch {
|
|
90
|
-
return route.path.startsWith(matcher.replace(/\/:path\*$/, ""));
|
|
91
|
-
}
|
|
92
|
-
});
|
|
93
|
-
return {
|
|
94
|
-
routeId: route.routeId,
|
|
95
|
-
covered: isRouteCovered,
|
|
96
|
-
};
|
|
97
|
-
});
|
|
98
|
-
// Calculate summary stats
|
|
99
|
-
const intentsByType = {};
|
|
100
|
-
const intentsBySource = {};
|
|
101
|
-
for (const intent of intentMap) {
|
|
102
|
-
intentsByType[intent.type] = (intentsByType[intent.type] || 0) + 1;
|
|
103
|
-
intentsBySource[intent.source] = (intentsBySource[intent.source] || 0) + 1;
|
|
104
|
-
}
|
|
105
|
-
return {
|
|
106
|
-
artifactVersion: ARTIFACT_VERSION,
|
|
107
|
-
generatedAt: new Date().toISOString(),
|
|
108
|
-
tool: {
|
|
109
|
-
name: "vibecheck",
|
|
110
|
-
version: "0.0.1",
|
|
111
|
-
},
|
|
112
|
-
repo: {
|
|
113
|
-
name,
|
|
114
|
-
rootPathHash: hashPath(targetDir),
|
|
115
|
-
git: gitInfo,
|
|
116
|
-
},
|
|
117
|
-
routeMap: { routes: routeMap },
|
|
118
|
-
middlewareMap: {
|
|
119
|
-
middlewareFile: middlewareMap[0]?.file,
|
|
120
|
-
matcher: allMatchers,
|
|
121
|
-
coverage: middlewareCoverage,
|
|
122
|
-
},
|
|
123
|
-
intentMap: { intents: intentMap },
|
|
124
|
-
proofTraces: proofTracesRecord,
|
|
125
|
-
coverage,
|
|
126
|
-
summary: {
|
|
127
|
-
totalRoutes: routeMap.length,
|
|
128
|
-
totalIntents: intentMap.length,
|
|
129
|
-
authCoveragePercent: Math.round(coverage.authCoverage * 100),
|
|
130
|
-
validationCoveragePercent: Math.round(coverage.validationCoverage * 100),
|
|
131
|
-
middlewareCoveragePercent: Math.round(coverage.middlewareCoverage * 100),
|
|
132
|
-
intentsByType,
|
|
133
|
-
intentsBySource,
|
|
134
|
-
},
|
|
135
|
-
};
|
|
136
|
-
}
|
|
137
|
-
/**
|
|
138
|
-
* Print intent map summary
|
|
139
|
-
*/
|
|
140
|
-
function printIntentSummary(artifact) {
|
|
141
|
-
const { summary, coverage } = artifact;
|
|
142
|
-
console.log("\n" + "=".repeat(60));
|
|
143
|
-
console.log("VibeCheck Intent Map Generated");
|
|
144
|
-
console.log("=".repeat(60));
|
|
145
|
-
console.log(`\nRoutes discovered: ${summary.totalRoutes}`);
|
|
146
|
-
console.log(`Intent claims found: ${summary.totalIntents}`);
|
|
147
|
-
console.log("\nCoverage metrics:");
|
|
148
|
-
console.log(` Auth coverage: ${formatPercent(coverage.authCoverage)}`);
|
|
149
|
-
console.log(` Validation coverage: ${formatPercent(coverage.validationCoverage)}`);
|
|
150
|
-
console.log(` Middleware coverage: ${formatPercent(coverage.middlewareCoverage)}`);
|
|
151
|
-
if (summary.totalIntents > 0) {
|
|
152
|
-
console.log("\nIntents by type:");
|
|
153
|
-
for (const [type, count] of Object.entries(summary.intentsByType)) {
|
|
154
|
-
console.log(` ${type}: ${count}`);
|
|
155
|
-
}
|
|
156
|
-
console.log("\nIntents by source:");
|
|
157
|
-
for (const [source, count] of Object.entries(summary.intentsBySource)) {
|
|
158
|
-
console.log(` ${source}: ${count}`);
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
console.log("");
|
|
162
|
-
}
|
|
163
|
-
/**
|
|
164
|
-
* Format percentage with color
|
|
165
|
-
*/
|
|
166
|
-
function formatPercent(value) {
|
|
167
|
-
const percent = Math.round(value * 100);
|
|
168
|
-
let color = "\x1b[32m"; // Green
|
|
169
|
-
if (percent < 50) {
|
|
170
|
-
color = "\x1b[31m"; // Red
|
|
171
|
-
}
|
|
172
|
-
else if (percent < 80) {
|
|
173
|
-
color = "\x1b[33m"; // Yellow
|
|
174
|
-
}
|
|
175
|
-
return `${color}${percent}%\x1b[0m`;
|
|
176
|
-
}
|
|
177
|
-
/**
|
|
178
|
-
* Register intent command with commander
|
|
179
|
-
*/
|
|
180
|
-
export function registerIntentCommand(program) {
|
|
181
|
-
program
|
|
182
|
-
.command("intent [target]")
|
|
183
|
-
.description("Generate security intent map baseline")
|
|
184
|
-
.option("-o, --out <path>", "Output file path", "vibecheck-artifacts/intent-map.json")
|
|
185
|
-
.option("-f, --format <format>", "Output format", "json")
|
|
186
|
-
.option("--repo-name <name>", "Override repository name")
|
|
187
|
-
.action(async (target, options) => {
|
|
188
|
-
const targetDir = target ?? process.cwd();
|
|
189
|
-
const exitCode = await executeIntent(targetDir, options);
|
|
190
|
-
process.exit(exitCode);
|
|
191
|
-
});
|
|
192
|
-
}
|
package/dist/commands/scan.d.ts
DELETED
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
import type { Command } from "commander";
|
|
2
|
-
import { type Severity } from "@vibecheck/schema";
|
|
3
|
-
/**
|
|
4
|
-
* Valid output formats
|
|
5
|
-
*/
|
|
6
|
-
export type OutputFormat = "json" | "sarif" | "both";
|
|
7
|
-
/**
|
|
8
|
-
* Valid fail-on thresholds
|
|
9
|
-
*/
|
|
10
|
-
export type FailThreshold = "off" | Severity;
|
|
11
|
-
/**
|
|
12
|
-
* Scan command options
|
|
13
|
-
*/
|
|
14
|
-
export interface ScanOptions {
|
|
15
|
-
/** Output file/directory path */
|
|
16
|
-
out: string;
|
|
17
|
-
/** Output format: json, sarif, or both */
|
|
18
|
-
format: OutputFormat;
|
|
19
|
-
/** Override repository name */
|
|
20
|
-
repoName?: string;
|
|
21
|
-
/** Fail threshold: off, info, low, medium, high, critical */
|
|
22
|
-
failOn: FailThreshold;
|
|
23
|
-
/** Only scan changed files (not implemented) */
|
|
24
|
-
changed: boolean;
|
|
25
|
-
/** Include route map in output (default: true) */
|
|
26
|
-
emitRouteMap: boolean;
|
|
27
|
-
/** Include intent claims in output (default: true) */
|
|
28
|
-
emitIntents: boolean;
|
|
29
|
-
/** Include proof traces in output (default: true) */
|
|
30
|
-
emitTraces: boolean;
|
|
31
|
-
/** Additional glob patterns to exclude */
|
|
32
|
-
exclude: string[];
|
|
33
|
-
/** Include test files in scan */
|
|
34
|
-
includeTests: boolean;
|
|
35
|
-
}
|
|
36
|
-
/**
|
|
37
|
-
* Execute the scan command
|
|
38
|
-
*/
|
|
39
|
-
export declare function executeScan(targetDir: string, options: ScanOptions): Promise<number>;
|
|
40
|
-
/**
|
|
41
|
-
* Register scan command with commander
|
|
42
|
-
*/
|
|
43
|
-
export declare function registerScanCommand(program: Command): void;
|
|
44
|
-
//# sourceMappingURL=scan.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"scan.d.ts","sourceRoot":"","sources":["../../src/commands/scan.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,EAML,KAAK,QAAQ,EACd,MAAM,mBAAmB,CAAC;AA0B3B;;GAEG;AACH,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,CAAC;AAErD;;GAEG;AACH,MAAM,MAAM,aAAa,GAAG,KAAK,GAAG,QAAQ,CAAC;AAE7C;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,iCAAiC;IACjC,GAAG,EAAE,MAAM,CAAC;IACZ,0CAA0C;IAC1C,MAAM,EAAE,YAAY,CAAC;IACrB,+BAA+B;IAC/B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,6DAA6D;IAC7D,MAAM,EAAE,aAAa,CAAC;IACtB,gDAAgD;IAChD,OAAO,EAAE,OAAO,CAAC;IACjB,kDAAkD;IAClD,YAAY,EAAE,OAAO,CAAC;IACtB,sDAAsD;IACtD,WAAW,EAAE,OAAO,CAAC;IACrB,qDAAqD;IACrD,UAAU,EAAE,OAAO,CAAC;IACpB,0CAA0C;IAC1C,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,iCAAiC;IACjC,YAAY,EAAE,OAAO,CAAC;CACvB;AA0VD;;GAEG;AACH,wBAAsB,WAAW,CAC/B,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,WAAW,GACnB,OAAO,CAAC,MAAM,CAAC,CAwMjB;AASD;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAkH1D"}
|