@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
|
@@ -1,322 +0,0 @@
|
|
|
1
|
-
import { writeFileSync } from "node:fs";
|
|
2
|
-
import { resolve } from "node:path";
|
|
3
|
-
import { ARTIFACT_VERSION, computeSummary, } from "@vibecheck/schema";
|
|
4
|
-
function generateDemoArtifact() {
|
|
5
|
-
const findings = [
|
|
6
|
-
{
|
|
7
|
-
id: "demo-finding-1",
|
|
8
|
-
ruleId: "VC-AUTH-001",
|
|
9
|
-
title: "Missing Authentication in API Route",
|
|
10
|
-
description: "The API route /api/users does not verify user authentication before returning sensitive data. An attacker could access user information without logging in.",
|
|
11
|
-
severity: "critical",
|
|
12
|
-
confidence: 0.95,
|
|
13
|
-
category: "auth",
|
|
14
|
-
evidence: [
|
|
15
|
-
{
|
|
16
|
-
file: "pages/api/users.ts",
|
|
17
|
-
startLine: 5,
|
|
18
|
-
endLine: 12,
|
|
19
|
-
snippet: `export default async function handler(req, res) {
|
|
20
|
-
// No authentication check!
|
|
21
|
-
const users = await db.query("SELECT * FROM users");
|
|
22
|
-
res.json(users);
|
|
23
|
-
}`,
|
|
24
|
-
label: "Unauthenticated API handler",
|
|
25
|
-
},
|
|
26
|
-
],
|
|
27
|
-
remediation: {
|
|
28
|
-
recommendedFix: "Add authentication middleware to verify the user session before processing the request.",
|
|
29
|
-
patch: `import { getServerSession } from "next-auth";
|
|
30
|
-
|
|
31
|
-
export default async function handler(req, res) {
|
|
32
|
-
const session = await getServerSession(req, res);
|
|
33
|
-
if (!session) {
|
|
34
|
-
return res.status(401).json({ error: "Unauthorized" });
|
|
35
|
-
}
|
|
36
|
-
const users = await db.query("SELECT * FROM users");
|
|
37
|
-
res.json(users);
|
|
38
|
-
}`,
|
|
39
|
-
},
|
|
40
|
-
links: {
|
|
41
|
-
owasp: "https://owasp.org/Top10/A01_2021-Broken_Access_Control/",
|
|
42
|
-
cwe: "https://cwe.mitre.org/data/definitions/306.html",
|
|
43
|
-
},
|
|
44
|
-
fingerprint: "demo-fp-001",
|
|
45
|
-
},
|
|
46
|
-
{
|
|
47
|
-
id: "demo-finding-2",
|
|
48
|
-
ruleId: "VC-INJECT-001",
|
|
49
|
-
title: "SQL Injection Vulnerability",
|
|
50
|
-
description: "User input is directly interpolated into SQL query without parameterization, allowing attackers to execute arbitrary SQL commands.",
|
|
51
|
-
severity: "critical",
|
|
52
|
-
confidence: 0.92,
|
|
53
|
-
category: "injection",
|
|
54
|
-
evidence: [
|
|
55
|
-
{
|
|
56
|
-
file: "lib/database.ts",
|
|
57
|
-
startLine: 23,
|
|
58
|
-
endLine: 25,
|
|
59
|
-
snippet: `async function getUser(id: string) {
|
|
60
|
-
return db.query(\`SELECT * FROM users WHERE id = '\${id}'\`);
|
|
61
|
-
}`,
|
|
62
|
-
label: "SQL string interpolation",
|
|
63
|
-
},
|
|
64
|
-
],
|
|
65
|
-
proof: {
|
|
66
|
-
summary: "User input flows from API parameter to SQL query without sanitization",
|
|
67
|
-
nodes: [
|
|
68
|
-
{
|
|
69
|
-
kind: "route",
|
|
70
|
-
label: "User ID received from request query parameter",
|
|
71
|
-
file: "pages/api/user/[id].ts",
|
|
72
|
-
line: 4,
|
|
73
|
-
},
|
|
74
|
-
{
|
|
75
|
-
kind: "function",
|
|
76
|
-
label: "ID passed to getUser() without validation",
|
|
77
|
-
file: "pages/api/user/[id].ts",
|
|
78
|
-
line: 8,
|
|
79
|
-
},
|
|
80
|
-
{
|
|
81
|
-
kind: "sink",
|
|
82
|
-
label: "ID interpolated directly into SQL query",
|
|
83
|
-
file: "lib/database.ts",
|
|
84
|
-
line: 24,
|
|
85
|
-
},
|
|
86
|
-
],
|
|
87
|
-
},
|
|
88
|
-
remediation: {
|
|
89
|
-
recommendedFix: "Use parameterized queries or prepared statements instead of string interpolation.",
|
|
90
|
-
patch: `async function getUser(id: string) {
|
|
91
|
-
return db.query("SELECT * FROM users WHERE id = $1", [id]);
|
|
92
|
-
}`,
|
|
93
|
-
},
|
|
94
|
-
links: {
|
|
95
|
-
owasp: "https://owasp.org/Top10/A03_2021-Injection/",
|
|
96
|
-
cwe: "https://cwe.mitre.org/data/definitions/89.html",
|
|
97
|
-
},
|
|
98
|
-
fingerprint: "demo-fp-002",
|
|
99
|
-
},
|
|
100
|
-
{
|
|
101
|
-
id: "demo-finding-3",
|
|
102
|
-
ruleId: "VC-XSS-001",
|
|
103
|
-
title: "Cross-Site Scripting (XSS) via dangerouslySetInnerHTML",
|
|
104
|
-
description: "User-generated content is rendered using dangerouslySetInnerHTML without sanitization, enabling XSS attacks.",
|
|
105
|
-
severity: "high",
|
|
106
|
-
confidence: 0.88,
|
|
107
|
-
category: "validation",
|
|
108
|
-
evidence: [
|
|
109
|
-
{
|
|
110
|
-
file: "components/Comment.tsx",
|
|
111
|
-
startLine: 15,
|
|
112
|
-
endLine: 17,
|
|
113
|
-
snippet: `function Comment({ content }: { content: string }) {
|
|
114
|
-
return <div dangerouslySetInnerHTML={{ __html: content }} />;
|
|
115
|
-
}`,
|
|
116
|
-
label: "Unsanitized HTML rendering",
|
|
117
|
-
},
|
|
118
|
-
],
|
|
119
|
-
remediation: {
|
|
120
|
-
recommendedFix: "Sanitize HTML content using a library like DOMPurify before rendering.",
|
|
121
|
-
patch: `import DOMPurify from "dompurify";
|
|
122
|
-
|
|
123
|
-
function Comment({ content }: { content: string }) {
|
|
124
|
-
const sanitized = DOMPurify.sanitize(content);
|
|
125
|
-
return <div dangerouslySetInnerHTML={{ __html: sanitized }} />;
|
|
126
|
-
}`,
|
|
127
|
-
},
|
|
128
|
-
links: {
|
|
129
|
-
owasp: "https://owasp.org/Top10/A03_2021-Injection/",
|
|
130
|
-
cwe: "https://cwe.mitre.org/data/definitions/79.html",
|
|
131
|
-
},
|
|
132
|
-
fingerprint: "demo-fp-003",
|
|
133
|
-
},
|
|
134
|
-
{
|
|
135
|
-
id: "demo-finding-4",
|
|
136
|
-
ruleId: "VC-SECRETS-001",
|
|
137
|
-
title: "Hardcoded API Key in Source Code",
|
|
138
|
-
description: "An API key is hardcoded in the source file. This could be exposed in version control or client bundles.",
|
|
139
|
-
severity: "high",
|
|
140
|
-
confidence: 0.85,
|
|
141
|
-
category: "secrets",
|
|
142
|
-
evidence: [
|
|
143
|
-
{
|
|
144
|
-
file: "lib/stripe.ts",
|
|
145
|
-
startLine: 3,
|
|
146
|
-
endLine: 3,
|
|
147
|
-
snippet: `const STRIPE_KEY = "sk_live_abc123xyz789";`,
|
|
148
|
-
label: "Hardcoded secret key",
|
|
149
|
-
},
|
|
150
|
-
],
|
|
151
|
-
remediation: {
|
|
152
|
-
recommendedFix: "Move secrets to environment variables and never commit them to version control.",
|
|
153
|
-
patch: `const STRIPE_KEY = process.env.STRIPE_SECRET_KEY;
|
|
154
|
-
|
|
155
|
-
if (!STRIPE_KEY) {
|
|
156
|
-
throw new Error("STRIPE_SECRET_KEY environment variable is required");
|
|
157
|
-
}`,
|
|
158
|
-
},
|
|
159
|
-
fingerprint: "demo-fp-004",
|
|
160
|
-
},
|
|
161
|
-
{
|
|
162
|
-
id: "demo-finding-5",
|
|
163
|
-
ruleId: "VC-HALL-001",
|
|
164
|
-
title: "Unused Security Import: helmet",
|
|
165
|
-
description: "The helmet security middleware is imported but never used, suggesting incomplete security implementation.",
|
|
166
|
-
severity: "medium",
|
|
167
|
-
confidence: 0.94,
|
|
168
|
-
category: "middleware",
|
|
169
|
-
evidence: [
|
|
170
|
-
{
|
|
171
|
-
file: "server.ts",
|
|
172
|
-
startLine: 2,
|
|
173
|
-
endLine: 2,
|
|
174
|
-
snippet: `import helmet from "helmet";`,
|
|
175
|
-
label: "Unused helmet import",
|
|
176
|
-
},
|
|
177
|
-
],
|
|
178
|
-
claim: {
|
|
179
|
-
type: "OTHER",
|
|
180
|
-
source: "import",
|
|
181
|
-
scope: "module",
|
|
182
|
-
strength: "weak",
|
|
183
|
-
textEvidence: 'import helmet from "helmet"',
|
|
184
|
-
location: {
|
|
185
|
-
file: "server.ts",
|
|
186
|
-
startLine: 2,
|
|
187
|
-
endLine: 2,
|
|
188
|
-
},
|
|
189
|
-
},
|
|
190
|
-
remediation: {
|
|
191
|
-
recommendedFix: "Apply the helmet middleware to add security headers, or remove the unused import.",
|
|
192
|
-
patch: `import helmet from "helmet";
|
|
193
|
-
|
|
194
|
-
app.use(helmet());`,
|
|
195
|
-
},
|
|
196
|
-
fingerprint: "demo-fp-005",
|
|
197
|
-
},
|
|
198
|
-
{
|
|
199
|
-
id: "demo-finding-6",
|
|
200
|
-
ruleId: "VC-PRIVACY-001",
|
|
201
|
-
title: "Sensitive Data in Console Logs",
|
|
202
|
-
description: "User passwords are being logged to the console, which could expose credentials in log files or monitoring systems.",
|
|
203
|
-
severity: "medium",
|
|
204
|
-
confidence: 0.91,
|
|
205
|
-
category: "privacy",
|
|
206
|
-
evidence: [
|
|
207
|
-
{
|
|
208
|
-
file: "lib/auth.ts",
|
|
209
|
-
startLine: 45,
|
|
210
|
-
endLine: 45,
|
|
211
|
-
snippet: `console.log("Login attempt:", { email, password });`,
|
|
212
|
-
label: "Password logged to console",
|
|
213
|
-
},
|
|
214
|
-
],
|
|
215
|
-
remediation: {
|
|
216
|
-
recommendedFix: "Remove sensitive data from log statements. Only log non-sensitive identifiers.",
|
|
217
|
-
patch: `console.log("Login attempt:", { email, timestamp: Date.now() });`,
|
|
218
|
-
},
|
|
219
|
-
fingerprint: "demo-fp-006",
|
|
220
|
-
},
|
|
221
|
-
{
|
|
222
|
-
id: "demo-finding-7",
|
|
223
|
-
ruleId: "VC-CONFIG-001",
|
|
224
|
-
title: "Insecure Cookie Configuration",
|
|
225
|
-
description: "Session cookies are configured without the Secure and HttpOnly flags, making them vulnerable to interception and XSS attacks.",
|
|
226
|
-
severity: "low",
|
|
227
|
-
confidence: 0.82,
|
|
228
|
-
category: "config",
|
|
229
|
-
evidence: [
|
|
230
|
-
{
|
|
231
|
-
file: "lib/session.ts",
|
|
232
|
-
startLine: 8,
|
|
233
|
-
endLine: 12,
|
|
234
|
-
snippet: `const sessionConfig = {
|
|
235
|
-
name: "session",
|
|
236
|
-
secret: process.env.SESSION_SECRET,
|
|
237
|
-
// Missing: secure, httpOnly, sameSite
|
|
238
|
-
};`,
|
|
239
|
-
label: "Insecure session config",
|
|
240
|
-
},
|
|
241
|
-
],
|
|
242
|
-
remediation: {
|
|
243
|
-
recommendedFix: "Add secure cookie options to protect against common attacks.",
|
|
244
|
-
patch: `const sessionConfig = {
|
|
245
|
-
name: "session",
|
|
246
|
-
secret: process.env.SESSION_SECRET,
|
|
247
|
-
cookie: {
|
|
248
|
-
secure: process.env.NODE_ENV === "production",
|
|
249
|
-
httpOnly: true,
|
|
250
|
-
sameSite: "strict",
|
|
251
|
-
maxAge: 60 * 60 * 24 * 7, // 1 week
|
|
252
|
-
},
|
|
253
|
-
};`,
|
|
254
|
-
},
|
|
255
|
-
fingerprint: "demo-fp-007",
|
|
256
|
-
},
|
|
257
|
-
];
|
|
258
|
-
const artifact = {
|
|
259
|
-
artifactVersion: ARTIFACT_VERSION,
|
|
260
|
-
generatedAt: new Date().toISOString(),
|
|
261
|
-
tool: {
|
|
262
|
-
name: "vibecheck",
|
|
263
|
-
version: "0.0.1",
|
|
264
|
-
},
|
|
265
|
-
repo: {
|
|
266
|
-
name: "demo-project",
|
|
267
|
-
rootPathHash: "demo-hash-12345",
|
|
268
|
-
git: {
|
|
269
|
-
branch: "main",
|
|
270
|
-
commit: "abc1234",
|
|
271
|
-
isDirty: false,
|
|
272
|
-
},
|
|
273
|
-
},
|
|
274
|
-
summary: computeSummary(findings),
|
|
275
|
-
findings,
|
|
276
|
-
metrics: {
|
|
277
|
-
filesScanned: 42,
|
|
278
|
-
linesOfCode: 3847,
|
|
279
|
-
scanDurationMs: 1250,
|
|
280
|
-
rulesExecuted: 12,
|
|
281
|
-
},
|
|
282
|
-
};
|
|
283
|
-
return artifact;
|
|
284
|
-
}
|
|
285
|
-
export function executeDemoArtifact(options) {
|
|
286
|
-
const artifact = generateDemoArtifact();
|
|
287
|
-
const json = JSON.stringify(artifact, null, 2);
|
|
288
|
-
if (options.out) {
|
|
289
|
-
const outPath = resolve(process.cwd(), options.out);
|
|
290
|
-
writeFileSync(outPath, json, "utf-8");
|
|
291
|
-
console.log(`Demo artifact written to: ${outPath}`);
|
|
292
|
-
}
|
|
293
|
-
else {
|
|
294
|
-
console.log(json);
|
|
295
|
-
}
|
|
296
|
-
console.log(`
|
|
297
|
-
============================================================
|
|
298
|
-
Demo Artifact Generated
|
|
299
|
-
============================================================
|
|
300
|
-
|
|
301
|
-
Findings: ${artifact.summary.totalFindings}
|
|
302
|
-
- Critical: ${artifact.summary.bySeverity.critical}
|
|
303
|
-
- High: ${artifact.summary.bySeverity.high}
|
|
304
|
-
- Medium: ${artifact.summary.bySeverity.medium}
|
|
305
|
-
- Low: ${artifact.summary.bySeverity.low}
|
|
306
|
-
- Info: ${artifact.summary.bySeverity.info}
|
|
307
|
-
|
|
308
|
-
Use this artifact to test the VibeCheck UI:
|
|
309
|
-
1. Run: pnpm dev:web
|
|
310
|
-
2. Open: http://localhost:3000
|
|
311
|
-
3. Import the generated JSON file
|
|
312
|
-
`);
|
|
313
|
-
}
|
|
314
|
-
export function registerDemoArtifactCommand(program) {
|
|
315
|
-
program
|
|
316
|
-
.command("demo-artifact")
|
|
317
|
-
.description("Generate a demo artifact for testing the UI")
|
|
318
|
-
.option("-o, --out <path>", "Output file path (prints to stdout if not specified)")
|
|
319
|
-
.action((options) => {
|
|
320
|
-
executeDemoArtifact(options);
|
|
321
|
-
});
|
|
322
|
-
}
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
import type { Command } from "commander";
|
|
2
|
-
import { type ProfileName } from "@vibecheck/policy";
|
|
3
|
-
/**
|
|
4
|
-
* Evaluate command options
|
|
5
|
-
*/
|
|
6
|
-
export interface EvaluateOptions {
|
|
7
|
-
/** Path to scan artifact (JSON) */
|
|
8
|
-
artifact: string;
|
|
9
|
-
/** Optional baseline artifact for regression detection */
|
|
10
|
-
baseline?: string;
|
|
11
|
-
/** Policy profile name */
|
|
12
|
-
profile: ProfileName;
|
|
13
|
-
/** Path to policy config file (JSON) */
|
|
14
|
-
config?: string;
|
|
15
|
-
/** Path to waivers file (JSON) */
|
|
16
|
-
waivers?: string;
|
|
17
|
-
/** Output report to file */
|
|
18
|
-
out?: string;
|
|
19
|
-
/** JSON output only (no console summary) */
|
|
20
|
-
quiet: boolean;
|
|
21
|
-
}
|
|
22
|
-
/**
|
|
23
|
-
* Execute the evaluate command
|
|
24
|
-
*/
|
|
25
|
-
export declare function executeEvaluate(options: EvaluateOptions): Promise<number>;
|
|
26
|
-
/**
|
|
27
|
-
* Register evaluate command with commander
|
|
28
|
-
*/
|
|
29
|
-
export declare function registerEvaluateCommand(program: Command): void;
|
|
30
|
-
//# sourceMappingURL=evaluate.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"evaluate.d.ts","sourceRoot":"","sources":["../../src/commands/evaluate.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEzC,OAAO,EAKL,KAAK,WAAW,EAOjB,MAAM,mBAAmB,CAAC;AAG3B;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,mCAAmC;IACnC,QAAQ,EAAE,MAAM,CAAC;IACjB,0DAA0D;IAC1D,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,0BAA0B;IAC1B,OAAO,EAAE,WAAW,CAAC;IACrB,wCAAwC;IACxC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,kCAAkC;IAClC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,4BAA4B;IAC5B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,4CAA4C;IAC5C,KAAK,EAAE,OAAO,CAAC;CAChB;AAkLD;;GAEG;AACH,wBAAsB,eAAe,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,MAAM,CAAC,CAqD/E;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CA0E9D"}
|
|
@@ -1,258 +0,0 @@
|
|
|
1
|
-
import path from "node:path";
|
|
2
|
-
import { readFileSync, fileExists, resolvePath, writeFileSync, ensureDir } from "../utils/file-utils.js";
|
|
3
|
-
import { evaluate, PROFILE_NAMES, PROFILE_DESCRIPTIONS, WaiversFileSchema, PolicyConfigSchema, } from "@vibecheck/policy";
|
|
4
|
-
import { validateArtifact } from "@vibecheck/schema";
|
|
5
|
-
/**
|
|
6
|
-
* Load and validate scan artifact from file
|
|
7
|
-
*/
|
|
8
|
-
function loadArtifact(filepath) {
|
|
9
|
-
const absolutePath = resolvePath(filepath);
|
|
10
|
-
if (!fileExists(absolutePath)) {
|
|
11
|
-
throw new Error(`Artifact file not found: ${filepath}`);
|
|
12
|
-
}
|
|
13
|
-
const content = readFileSync(absolutePath);
|
|
14
|
-
if (!content) {
|
|
15
|
-
throw new Error(`Failed to read artifact file: ${filepath}`);
|
|
16
|
-
}
|
|
17
|
-
const data = JSON.parse(content);
|
|
18
|
-
// Validate the artifact
|
|
19
|
-
return validateArtifact(data);
|
|
20
|
-
}
|
|
21
|
-
/**
|
|
22
|
-
* Load and validate waivers file
|
|
23
|
-
*/
|
|
24
|
-
function loadWaivers(filepath) {
|
|
25
|
-
const absolutePath = resolvePath(filepath);
|
|
26
|
-
if (!fileExists(absolutePath)) {
|
|
27
|
-
throw new Error(`Waivers file not found: ${filepath}`);
|
|
28
|
-
}
|
|
29
|
-
const content = readFileSync(absolutePath);
|
|
30
|
-
if (!content) {
|
|
31
|
-
throw new Error(`Failed to read waivers file: ${filepath}`);
|
|
32
|
-
}
|
|
33
|
-
const data = JSON.parse(content);
|
|
34
|
-
const result = WaiversFileSchema.safeParse(data);
|
|
35
|
-
if (!result.success) {
|
|
36
|
-
throw new Error(`Invalid waivers file: ${result.error.message}`);
|
|
37
|
-
}
|
|
38
|
-
return result.data.waivers;
|
|
39
|
-
}
|
|
40
|
-
/**
|
|
41
|
-
* Load and validate policy config file
|
|
42
|
-
*/
|
|
43
|
-
function loadConfig(filepath) {
|
|
44
|
-
const absolutePath = resolvePath(filepath);
|
|
45
|
-
if (!fileExists(absolutePath)) {
|
|
46
|
-
throw new Error(`Config file not found: ${filepath}`);
|
|
47
|
-
}
|
|
48
|
-
const content = readFileSync(absolutePath);
|
|
49
|
-
if (!content) {
|
|
50
|
-
throw new Error(`Failed to read config file: ${filepath}`);
|
|
51
|
-
}
|
|
52
|
-
const data = JSON.parse(content);
|
|
53
|
-
const result = PolicyConfigSchema.safeParse(data);
|
|
54
|
-
if (!result.success) {
|
|
55
|
-
throw new Error(`Invalid config file: ${result.error.message}`);
|
|
56
|
-
}
|
|
57
|
-
return result.data;
|
|
58
|
-
}
|
|
59
|
-
/**
|
|
60
|
-
* Format severity for console output with color
|
|
61
|
-
*/
|
|
62
|
-
function formatSeverity(severity) {
|
|
63
|
-
const colors = {
|
|
64
|
-
critical: "\x1b[35m", // Magenta
|
|
65
|
-
high: "\x1b[31m", // Red
|
|
66
|
-
medium: "\x1b[33m", // Yellow
|
|
67
|
-
low: "\x1b[36m", // Cyan
|
|
68
|
-
info: "\x1b[90m", // Gray
|
|
69
|
-
};
|
|
70
|
-
const reset = "\x1b[0m";
|
|
71
|
-
return `${colors[severity]}${severity.toUpperCase()}${reset}`;
|
|
72
|
-
}
|
|
73
|
-
/**
|
|
74
|
-
* Format status for console output with color
|
|
75
|
-
*/
|
|
76
|
-
function formatStatus(status) {
|
|
77
|
-
const colors = {
|
|
78
|
-
pass: "\x1b[32m", // Green
|
|
79
|
-
warn: "\x1b[33m", // Yellow
|
|
80
|
-
fail: "\x1b[31m", // Red
|
|
81
|
-
};
|
|
82
|
-
const reset = "\x1b[0m";
|
|
83
|
-
return `${colors[status]}${status.toUpperCase()}${reset}`;
|
|
84
|
-
}
|
|
85
|
-
/**
|
|
86
|
-
* Print evaluation summary to console
|
|
87
|
-
*/
|
|
88
|
-
function printSummary(report) {
|
|
89
|
-
console.log("\n" + "=".repeat(60));
|
|
90
|
-
console.log("VibeCheck Policy Evaluation");
|
|
91
|
-
console.log("=".repeat(60));
|
|
92
|
-
console.log(`\nProfile: ${report.profileName ?? "custom"}`);
|
|
93
|
-
console.log(`Status: ${formatStatus(report.status)}`);
|
|
94
|
-
console.log(`Exit Code: ${report.exitCode}`);
|
|
95
|
-
console.log("\nSummary:");
|
|
96
|
-
console.log(` Total active findings: ${report.summary.total}`);
|
|
97
|
-
console.log(` Waived findings: ${report.summary.waived}`);
|
|
98
|
-
console.log(` Ignored by override: ${report.summary.ignored}`);
|
|
99
|
-
if (report.summary.total > 0) {
|
|
100
|
-
console.log("\nBy severity:");
|
|
101
|
-
if (report.summary.bySeverity.critical > 0) {
|
|
102
|
-
console.log(` ${formatSeverity("critical")}: ${report.summary.bySeverity.critical}`);
|
|
103
|
-
}
|
|
104
|
-
if (report.summary.bySeverity.high > 0) {
|
|
105
|
-
console.log(` ${formatSeverity("high")}: ${report.summary.bySeverity.high}`);
|
|
106
|
-
}
|
|
107
|
-
if (report.summary.bySeverity.medium > 0) {
|
|
108
|
-
console.log(` ${formatSeverity("medium")}: ${report.summary.bySeverity.medium}`);
|
|
109
|
-
}
|
|
110
|
-
if (report.summary.bySeverity.low > 0) {
|
|
111
|
-
console.log(` ${formatSeverity("low")}: ${report.summary.bySeverity.low}`);
|
|
112
|
-
}
|
|
113
|
-
if (report.summary.bySeverity.info > 0) {
|
|
114
|
-
console.log(` ${formatSeverity("info")}: ${report.summary.bySeverity.info}`);
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
// Show thresholds
|
|
118
|
-
console.log("\nThresholds:");
|
|
119
|
-
console.log(` Fail on severity >= ${report.thresholds.failOnSeverity} (confidence >= ${report.thresholds.minConfidenceForFail})`);
|
|
120
|
-
console.log(` Warn on severity >= ${report.thresholds.warnOnSeverity} (confidence >= ${report.thresholds.minConfidenceForWarn})`);
|
|
121
|
-
if (report.thresholds.maxFindings > 0) {
|
|
122
|
-
console.log(` Max findings: ${report.thresholds.maxFindings}`);
|
|
123
|
-
}
|
|
124
|
-
// Show regression if present
|
|
125
|
-
if (report.regression) {
|
|
126
|
-
console.log("\nRegression:");
|
|
127
|
-
console.log(` New findings: ${report.regression.newFindings.length}`);
|
|
128
|
-
console.log(` Resolved findings: ${report.regression.resolvedFindings.length}`);
|
|
129
|
-
console.log(` Severity regressions: ${report.regression.severityRegressions.length}`);
|
|
130
|
-
console.log(` Net change: ${report.regression.netChange > 0 ? "+" : ""}${report.regression.netChange}`);
|
|
131
|
-
}
|
|
132
|
-
// Show reasons
|
|
133
|
-
if (report.reasons.length > 0) {
|
|
134
|
-
console.log("\nReasons:");
|
|
135
|
-
for (const reason of report.reasons) {
|
|
136
|
-
const statusIcon = reason.status === "fail" ? "\x1b[31m✗\x1b[0m"
|
|
137
|
-
: reason.status === "warn" ? "\x1b[33m!\x1b[0m"
|
|
138
|
-
: "\x1b[32m✓\x1b[0m";
|
|
139
|
-
console.log(` ${statusIcon} ${reason.message}`);
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
// Show waived findings if any
|
|
143
|
-
if (report.waivedFindings.length > 0) {
|
|
144
|
-
console.log("\nWaived findings:");
|
|
145
|
-
for (const wf of report.waivedFindings.slice(0, 5)) {
|
|
146
|
-
const expiredNote = wf.expired ? " (EXPIRED)" : "";
|
|
147
|
-
console.log(` - [${wf.finding.ruleId}] ${wf.finding.title}${expiredNote}`);
|
|
148
|
-
console.log(` Reason: ${wf.waiver.reason}`);
|
|
149
|
-
}
|
|
150
|
-
if (report.waivedFindings.length > 5) {
|
|
151
|
-
console.log(` ... and ${report.waivedFindings.length - 5} more`);
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
console.log("");
|
|
155
|
-
}
|
|
156
|
-
/**
|
|
157
|
-
* Execute the evaluate command
|
|
158
|
-
*/
|
|
159
|
-
export async function executeEvaluate(options) {
|
|
160
|
-
// Load artifact
|
|
161
|
-
const artifact = loadArtifact(options.artifact);
|
|
162
|
-
// Load baseline if provided
|
|
163
|
-
let baseline;
|
|
164
|
-
if (options.baseline) {
|
|
165
|
-
baseline = loadArtifact(options.baseline);
|
|
166
|
-
}
|
|
167
|
-
// Load config if provided, otherwise use profile
|
|
168
|
-
let config;
|
|
169
|
-
if (options.config) {
|
|
170
|
-
config = loadConfig(options.config);
|
|
171
|
-
}
|
|
172
|
-
// Load waivers if provided
|
|
173
|
-
let waivers = [];
|
|
174
|
-
if (options.waivers) {
|
|
175
|
-
waivers = loadWaivers(options.waivers);
|
|
176
|
-
}
|
|
177
|
-
// Run evaluation
|
|
178
|
-
const report = evaluate({
|
|
179
|
-
artifact,
|
|
180
|
-
baseline,
|
|
181
|
-
config,
|
|
182
|
-
profile: config ? undefined : options.profile,
|
|
183
|
-
waivers,
|
|
184
|
-
artifactPath: options.artifact,
|
|
185
|
-
});
|
|
186
|
-
// Output report
|
|
187
|
-
if (options.out) {
|
|
188
|
-
const outPath = resolvePath(options.out);
|
|
189
|
-
ensureDir(path.dirname(outPath));
|
|
190
|
-
writeFileSync(outPath, JSON.stringify(report, null, 2));
|
|
191
|
-
if (!options.quiet) {
|
|
192
|
-
console.log(`Policy report written to: ${outPath}`);
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
// Print summary unless quiet mode
|
|
196
|
-
if (!options.quiet) {
|
|
197
|
-
printSummary(report);
|
|
198
|
-
}
|
|
199
|
-
else {
|
|
200
|
-
// In quiet mode, just output JSON
|
|
201
|
-
if (!options.out) {
|
|
202
|
-
console.log(JSON.stringify(report, null, 2));
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
return report.exitCode;
|
|
206
|
-
}
|
|
207
|
-
/**
|
|
208
|
-
* Register evaluate command with commander
|
|
209
|
-
*/
|
|
210
|
-
export function registerEvaluateCommand(program) {
|
|
211
|
-
program
|
|
212
|
-
.command("evaluate")
|
|
213
|
-
.description("Evaluate a scan artifact against a policy")
|
|
214
|
-
.requiredOption("-a, --artifact <path>", "Path to scan artifact (JSON)")
|
|
215
|
-
.option("-b, --baseline <path>", "Path to baseline artifact for regression detection")
|
|
216
|
-
.option("-p, --profile <name>", `Policy profile (${PROFILE_NAMES.join(", ")})`, "startup")
|
|
217
|
-
.option("-c, --config <path>", "Path to policy config file (overrides profile)")
|
|
218
|
-
.option("-w, --waivers <path>", "Path to waivers file")
|
|
219
|
-
.option("-o, --out <path>", "Output report to file")
|
|
220
|
-
.option("-q, --quiet", "JSON output only (no console summary)")
|
|
221
|
-
.addHelpText("after", `
|
|
222
|
-
Profiles:
|
|
223
|
-
${PROFILE_NAMES.map((name) => ` ${name}: ${PROFILE_DESCRIPTIONS[name]}`).join("\n")}
|
|
224
|
-
|
|
225
|
-
Examples:
|
|
226
|
-
$ vibecheck evaluate -a ./vibecheck-scan.json
|
|
227
|
-
$ vibecheck evaluate -a ./scan.json -p strict
|
|
228
|
-
$ vibecheck evaluate -a ./scan.json -b ./baseline.json
|
|
229
|
-
$ vibecheck evaluate -a ./scan.json -w ./waivers.json
|
|
230
|
-
$ vibecheck evaluate -a ./scan.json -c ./policy.json
|
|
231
|
-
$ vibecheck evaluate -a ./scan.json -o ./report.json -q
|
|
232
|
-
`)
|
|
233
|
-
.action(async (cmdOptions) => {
|
|
234
|
-
// Validate profile
|
|
235
|
-
const profileStr = cmdOptions.profile;
|
|
236
|
-
if (!PROFILE_NAMES.includes(profileStr)) {
|
|
237
|
-
console.error(`\x1b[31mError: Invalid profile "${profileStr}". Valid options: ${PROFILE_NAMES.join(", ")}\x1b[0m`);
|
|
238
|
-
process.exit(1);
|
|
239
|
-
}
|
|
240
|
-
const options = {
|
|
241
|
-
artifact: cmdOptions.artifact,
|
|
242
|
-
baseline: cmdOptions.baseline,
|
|
243
|
-
profile: profileStr,
|
|
244
|
-
config: cmdOptions.config,
|
|
245
|
-
waivers: cmdOptions.waivers,
|
|
246
|
-
out: cmdOptions.out,
|
|
247
|
-
quiet: Boolean(cmdOptions.quiet),
|
|
248
|
-
};
|
|
249
|
-
try {
|
|
250
|
-
const exitCode = await executeEvaluate(options);
|
|
251
|
-
process.exit(exitCode);
|
|
252
|
-
}
|
|
253
|
-
catch (error) {
|
|
254
|
-
console.error(`\x1b[31mError: ${error instanceof Error ? error.message : String(error)}\x1b[0m`);
|
|
255
|
-
process.exit(1);
|
|
256
|
-
}
|
|
257
|
-
});
|
|
258
|
-
}
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import type { Command } from "commander";
|
|
2
|
-
/**
|
|
3
|
-
* Execute the explain command
|
|
4
|
-
*/
|
|
5
|
-
export declare function executeExplain(artifactPath: string, options: {
|
|
6
|
-
limit: number;
|
|
7
|
-
}): Promise<number>;
|
|
8
|
-
/**
|
|
9
|
-
* Register explain command with commander
|
|
10
|
-
*/
|
|
11
|
-
export declare function registerExplainCommand(program: Command): void;
|
|
12
|
-
//# sourceMappingURL=explain.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"explain.d.ts","sourceRoot":"","sources":["../../src/commands/explain.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA0MzC;;GAEG;AACH,wBAAsB,cAAc,CAClC,YAAY,EAAE,MAAM,EACpB,OAAO,EAAE;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,GACzB,OAAO,CAAC,MAAM,CAAC,CAkCjB;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAU7D"}
|