@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.
Files changed (208) hide show
  1. package/README.md +6 -6
  2. package/dist/index.d.ts +0 -2
  3. package/dist/index.js +7902 -8
  4. package/package.json +13 -7
  5. package/dist/__tests__/cli.test.d.ts +0 -2
  6. package/dist/__tests__/cli.test.d.ts.map +0 -1
  7. package/dist/__tests__/cli.test.js +0 -243
  8. package/dist/__tests__/fixtures/safe-app/app/api/users/route.js +0 -36
  9. package/dist/__tests__/fixtures/vulnerable-app/app/api/users/route.js +0 -28
  10. package/dist/__tests__/fixtures/vulnerable-app/lib/config.d.ts +0 -4
  11. package/dist/__tests__/fixtures/vulnerable-app/lib/config.d.ts.map +0 -1
  12. package/dist/__tests__/fixtures/vulnerable-app/lib/config.js +0 -6
  13. package/dist/__tests__/scanners/env-config.test.d.ts +0 -2
  14. package/dist/__tests__/scanners/env-config.test.d.ts.map +0 -1
  15. package/dist/__tests__/scanners/env-config.test.js +0 -142
  16. package/dist/__tests__/scanners/nextjs-middleware.test.d.ts +0 -2
  17. package/dist/__tests__/scanners/nextjs-middleware.test.d.ts.map +0 -1
  18. package/dist/__tests__/scanners/nextjs-middleware.test.js +0 -193
  19. package/dist/__tests__/scanners/scanner-packs.test.d.ts +0 -2
  20. package/dist/__tests__/scanners/scanner-packs.test.d.ts.map +0 -1
  21. package/dist/__tests__/scanners/scanner-packs.test.js +0 -126
  22. package/dist/__tests__/scanners/unused-security-imports.test.d.ts +0 -2
  23. package/dist/__tests__/scanners/unused-security-imports.test.d.ts.map +0 -1
  24. package/dist/__tests__/scanners/unused-security-imports.test.js +0 -145
  25. package/dist/commands/demo-artifact.d.ts +0 -7
  26. package/dist/commands/demo-artifact.d.ts.map +0 -1
  27. package/dist/commands/demo-artifact.js +0 -322
  28. package/dist/commands/evaluate.d.ts +0 -30
  29. package/dist/commands/evaluate.d.ts.map +0 -1
  30. package/dist/commands/evaluate.js +0 -258
  31. package/dist/commands/explain.d.ts +0 -12
  32. package/dist/commands/explain.d.ts.map +0 -1
  33. package/dist/commands/explain.js +0 -214
  34. package/dist/commands/index.d.ts +0 -7
  35. package/dist/commands/index.d.ts.map +0 -1
  36. package/dist/commands/index.js +0 -6
  37. package/dist/commands/intent.d.ts +0 -21
  38. package/dist/commands/intent.d.ts.map +0 -1
  39. package/dist/commands/intent.js +0 -192
  40. package/dist/commands/scan.d.ts +0 -44
  41. package/dist/commands/scan.d.ts.map +0 -1
  42. package/dist/commands/scan.js +0 -497
  43. package/dist/commands/waivers.d.ts +0 -30
  44. package/dist/commands/waivers.d.ts.map +0 -1
  45. package/dist/commands/waivers.js +0 -249
  46. package/dist/index.d.ts.map +0 -1
  47. package/dist/phase3/index.d.ts +0 -11
  48. package/dist/phase3/index.d.ts.map +0 -1
  49. package/dist/phase3/index.js +0 -12
  50. package/dist/phase3/intent-miner.d.ts +0 -32
  51. package/dist/phase3/intent-miner.d.ts.map +0 -1
  52. package/dist/phase3/intent-miner.js +0 -323
  53. package/dist/phase3/proof-trace-builder.d.ts +0 -42
  54. package/dist/phase3/proof-trace-builder.d.ts.map +0 -1
  55. package/dist/phase3/proof-trace-builder.js +0 -441
  56. package/dist/phase3/scanners/auth-by-ui-server-gap.d.ts +0 -15
  57. package/dist/phase3/scanners/auth-by-ui-server-gap.d.ts.map +0 -1
  58. package/dist/phase3/scanners/auth-by-ui-server-gap.js +0 -237
  59. package/dist/phase3/scanners/comment-claim-unproven.d.ts +0 -14
  60. package/dist/phase3/scanners/comment-claim-unproven.d.ts.map +0 -1
  61. package/dist/phase3/scanners/comment-claim-unproven.js +0 -161
  62. package/dist/phase3/scanners/index.d.ts +0 -31
  63. package/dist/phase3/scanners/index.d.ts.map +0 -1
  64. package/dist/phase3/scanners/index.js +0 -40
  65. package/dist/phase3/scanners/middleware-assumed-not-matching.d.ts +0 -14
  66. package/dist/phase3/scanners/middleware-assumed-not-matching.d.ts.map +0 -1
  67. package/dist/phase3/scanners/middleware-assumed-not-matching.js +0 -172
  68. package/dist/phase3/scanners/validation-claimed-missing.d.ts +0 -15
  69. package/dist/phase3/scanners/validation-claimed-missing.d.ts.map +0 -1
  70. package/dist/phase3/scanners/validation-claimed-missing.js +0 -204
  71. package/dist/scanners/abuse/compute-abuse.d.ts +0 -20
  72. package/dist/scanners/abuse/compute-abuse.d.ts.map +0 -1
  73. package/dist/scanners/abuse/compute-abuse.js +0 -509
  74. package/dist/scanners/abuse/index.d.ts +0 -12
  75. package/dist/scanners/abuse/index.d.ts.map +0 -1
  76. package/dist/scanners/abuse/index.js +0 -15
  77. package/dist/scanners/auth/index.d.ts +0 -5
  78. package/dist/scanners/auth/index.d.ts.map +0 -1
  79. package/dist/scanners/auth/index.js +0 -10
  80. package/dist/scanners/auth/middleware-gap.d.ts +0 -22
  81. package/dist/scanners/auth/middleware-gap.d.ts.map +0 -1
  82. package/dist/scanners/auth/middleware-gap.js +0 -203
  83. package/dist/scanners/auth/unprotected-api-route.d.ts +0 -12
  84. package/dist/scanners/auth/unprotected-api-route.d.ts.map +0 -1
  85. package/dist/scanners/auth/unprotected-api-route.js +0 -126
  86. package/dist/scanners/config/index.d.ts +0 -5
  87. package/dist/scanners/config/index.d.ts.map +0 -1
  88. package/dist/scanners/config/index.js +0 -10
  89. package/dist/scanners/config/insecure-defaults.d.ts +0 -12
  90. package/dist/scanners/config/insecure-defaults.d.ts.map +0 -1
  91. package/dist/scanners/config/insecure-defaults.js +0 -77
  92. package/dist/scanners/config/undocumented-env.d.ts +0 -24
  93. package/dist/scanners/config/undocumented-env.d.ts.map +0 -1
  94. package/dist/scanners/config/undocumented-env.js +0 -159
  95. package/dist/scanners/crypto/index.d.ts +0 -6
  96. package/dist/scanners/crypto/index.d.ts.map +0 -1
  97. package/dist/scanners/crypto/index.js +0 -11
  98. package/dist/scanners/crypto/jwt-decode-unverified.d.ts +0 -14
  99. package/dist/scanners/crypto/jwt-decode-unverified.d.ts.map +0 -1
  100. package/dist/scanners/crypto/jwt-decode-unverified.js +0 -87
  101. package/dist/scanners/crypto/math-random-tokens.d.ts +0 -13
  102. package/dist/scanners/crypto/math-random-tokens.d.ts.map +0 -1
  103. package/dist/scanners/crypto/math-random-tokens.js +0 -80
  104. package/dist/scanners/crypto/weak-hashing.d.ts +0 -11
  105. package/dist/scanners/crypto/weak-hashing.d.ts.map +0 -1
  106. package/dist/scanners/crypto/weak-hashing.js +0 -95
  107. package/dist/scanners/env-config.d.ts +0 -24
  108. package/dist/scanners/env-config.d.ts.map +0 -1
  109. package/dist/scanners/env-config.js +0 -164
  110. package/dist/scanners/hallucinations/index.d.ts +0 -4
  111. package/dist/scanners/hallucinations/index.d.ts.map +0 -1
  112. package/dist/scanners/hallucinations/index.js +0 -8
  113. package/dist/scanners/hallucinations/unused-security-imports.d.ts +0 -36
  114. package/dist/scanners/hallucinations/unused-security-imports.d.ts.map +0 -1
  115. package/dist/scanners/hallucinations/unused-security-imports.js +0 -309
  116. package/dist/scanners/helpers/ast-helpers.d.ts +0 -6
  117. package/dist/scanners/helpers/ast-helpers.d.ts.map +0 -1
  118. package/dist/scanners/helpers/ast-helpers.js +0 -945
  119. package/dist/scanners/helpers/context-builder.d.ts +0 -17
  120. package/dist/scanners/helpers/context-builder.d.ts.map +0 -1
  121. package/dist/scanners/helpers/context-builder.js +0 -148
  122. package/dist/scanners/helpers/index.d.ts +0 -3
  123. package/dist/scanners/helpers/index.d.ts.map +0 -1
  124. package/dist/scanners/helpers/index.js +0 -2
  125. package/dist/scanners/index.d.ts +0 -30
  126. package/dist/scanners/index.d.ts.map +0 -1
  127. package/dist/scanners/index.js +0 -102
  128. package/dist/scanners/middleware/index.d.ts +0 -4
  129. package/dist/scanners/middleware/index.d.ts.map +0 -1
  130. package/dist/scanners/middleware/index.js +0 -7
  131. package/dist/scanners/middleware/missing-rate-limit.d.ts +0 -13
  132. package/dist/scanners/middleware/missing-rate-limit.d.ts.map +0 -1
  133. package/dist/scanners/middleware/missing-rate-limit.js +0 -140
  134. package/dist/scanners/network/cors-misconfiguration.d.ts +0 -14
  135. package/dist/scanners/network/cors-misconfiguration.d.ts.map +0 -1
  136. package/dist/scanners/network/cors-misconfiguration.js +0 -89
  137. package/dist/scanners/network/index.d.ts +0 -7
  138. package/dist/scanners/network/index.d.ts.map +0 -1
  139. package/dist/scanners/network/index.js +0 -18
  140. package/dist/scanners/network/missing-timeout.d.ts +0 -15
  141. package/dist/scanners/network/missing-timeout.d.ts.map +0 -1
  142. package/dist/scanners/network/missing-timeout.js +0 -93
  143. package/dist/scanners/network/open-redirect.d.ts +0 -15
  144. package/dist/scanners/network/open-redirect.d.ts.map +0 -1
  145. package/dist/scanners/network/open-redirect.js +0 -88
  146. package/dist/scanners/network/ssrf-prone-fetch.d.ts +0 -12
  147. package/dist/scanners/network/ssrf-prone-fetch.d.ts.map +0 -1
  148. package/dist/scanners/network/ssrf-prone-fetch.js +0 -90
  149. package/dist/scanners/nextjs-middleware.d.ts +0 -26
  150. package/dist/scanners/nextjs-middleware.d.ts.map +0 -1
  151. package/dist/scanners/nextjs-middleware.js +0 -246
  152. package/dist/scanners/privacy/debug-flags.d.ts +0 -13
  153. package/dist/scanners/privacy/debug-flags.d.ts.map +0 -1
  154. package/dist/scanners/privacy/debug-flags.js +0 -124
  155. package/dist/scanners/privacy/index.d.ts +0 -6
  156. package/dist/scanners/privacy/index.d.ts.map +0 -1
  157. package/dist/scanners/privacy/index.js +0 -11
  158. package/dist/scanners/privacy/over-broad-response.d.ts +0 -15
  159. package/dist/scanners/privacy/over-broad-response.d.ts.map +0 -1
  160. package/dist/scanners/privacy/over-broad-response.js +0 -109
  161. package/dist/scanners/privacy/sensitive-logging.d.ts +0 -11
  162. package/dist/scanners/privacy/sensitive-logging.d.ts.map +0 -1
  163. package/dist/scanners/privacy/sensitive-logging.js +0 -78
  164. package/dist/scanners/types.d.ts +0 -456
  165. package/dist/scanners/types.d.ts.map +0 -1
  166. package/dist/scanners/types.js +0 -16
  167. package/dist/scanners/unused-security-imports.d.ts +0 -34
  168. package/dist/scanners/unused-security-imports.d.ts.map +0 -1
  169. package/dist/scanners/unused-security-imports.js +0 -206
  170. package/dist/scanners/uploads/index.d.ts +0 -5
  171. package/dist/scanners/uploads/index.d.ts.map +0 -1
  172. package/dist/scanners/uploads/index.js +0 -9
  173. package/dist/scanners/uploads/missing-constraints.d.ts +0 -15
  174. package/dist/scanners/uploads/missing-constraints.d.ts.map +0 -1
  175. package/dist/scanners/uploads/missing-constraints.js +0 -109
  176. package/dist/scanners/uploads/public-path.d.ts +0 -11
  177. package/dist/scanners/uploads/public-path.d.ts.map +0 -1
  178. package/dist/scanners/uploads/public-path.js +0 -87
  179. package/dist/scanners/validation/client-side-only.d.ts +0 -14
  180. package/dist/scanners/validation/client-side-only.d.ts.map +0 -1
  181. package/dist/scanners/validation/client-side-only.js +0 -140
  182. package/dist/scanners/validation/ignored-validation.d.ts +0 -12
  183. package/dist/scanners/validation/ignored-validation.d.ts.map +0 -1
  184. package/dist/scanners/validation/ignored-validation.js +0 -119
  185. package/dist/scanners/validation/index.d.ts +0 -5
  186. package/dist/scanners/validation/index.d.ts.map +0 -1
  187. package/dist/scanners/validation/index.js +0 -9
  188. package/dist/utils/exclude-patterns.d.ts +0 -35
  189. package/dist/utils/exclude-patterns.d.ts.map +0 -1
  190. package/dist/utils/exclude-patterns.js +0 -78
  191. package/dist/utils/file-utils.d.ts +0 -37
  192. package/dist/utils/file-utils.d.ts.map +0 -1
  193. package/dist/utils/file-utils.js +0 -77
  194. package/dist/utils/fingerprint.d.ts +0 -25
  195. package/dist/utils/fingerprint.d.ts.map +0 -1
  196. package/dist/utils/fingerprint.js +0 -28
  197. package/dist/utils/git-info.d.ts +0 -14
  198. package/dist/utils/git-info.d.ts.map +0 -1
  199. package/dist/utils/git-info.js +0 -55
  200. package/dist/utils/index.d.ts +0 -4
  201. package/dist/utils/index.d.ts.map +0 -1
  202. package/dist/utils/index.js +0 -3
  203. package/dist/utils/progress.d.ts +0 -42
  204. package/dist/utils/progress.d.ts.map +0 -1
  205. package/dist/utils/progress.js +0 -165
  206. package/dist/utils/sarif-formatter.d.ts +0 -92
  207. package/dist/utils/sarif-formatter.d.ts.map +0 -1
  208. 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"}