@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
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@quantracode/vibecheck",
3
- "version": "0.0.1",
3
+ "version": "0.0.2",
4
4
  "description": "Security scanner for modern web applications",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -43,24 +43,30 @@
43
43
  "node": ">=18.0.0"
44
44
  },
45
45
  "scripts": {
46
- "build": "tsc -p tsconfig.build.json",
46
+ "build": "tsup",
47
+ "build:tsc": "tsc -p tsconfig.build.json",
47
48
  "typecheck": "tsc --noEmit",
48
- "dev": "tsc -p tsconfig.build.json --watch",
49
+ "dev": "tsup --watch",
49
50
  "test": "vitest run",
50
51
  "test:watch": "vitest",
51
52
  "vibecheck": "node ./dist/index.js",
52
53
  "smoke": "node scripts/smoke-test.mjs",
53
- "prepublishOnly": "pnpm run build"
54
+ "pack:check": "node scripts/pack-check.mjs",
55
+ "prepublishOnly": "pnpm run build && pnpm run pack:check"
54
56
  },
55
57
  "dependencies": {
56
- "@vibecheck/policy": "workspace:*",
57
- "@vibecheck/schema": "workspace:*",
58
58
  "commander": "^12.1.0",
59
59
  "fast-glob": "^3.3.2",
60
- "ts-morph": "^24.0.0"
60
+ "micromatch": "^4.0.8",
61
+ "ts-morph": "^24.0.0",
62
+ "zod": "^3.24.1"
61
63
  },
62
64
  "devDependencies": {
65
+ "@types/micromatch": "^4.0.9",
63
66
  "@types/node": "^22.10.2",
67
+ "@vibecheck/policy": "workspace:*",
68
+ "@vibecheck/schema": "workspace:*",
69
+ "tsup": "^8.5.1",
64
70
  "vitest": "^2.1.8"
65
71
  }
66
72
  }
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=cli.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"cli.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/cli.test.ts"],"names":[],"mappings":""}
@@ -1,243 +0,0 @@
1
- import { describe, it, expect } from "vitest";
2
- import { executeScan } from "../commands/scan.js";
3
- import { executeExplain } from "../commands/explain.js";
4
- import { ScanArtifactSchema } from "@vibecheck/schema";
5
- import path from "node:path";
6
- import fs from "node:fs";
7
- import os from "node:os";
8
- describe("scan command", () => {
9
- it("produces valid artifact", async () => {
10
- const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "vibecheck-test-"));
11
- const outputPath = path.join(tmpDir, "output", "scan.json");
12
- // Create a simple test file
13
- fs.writeFileSync(path.join(tmpDir, "app.ts"), `const url = process.env.DATABASE_URL;`);
14
- try {
15
- const options = {
16
- out: outputPath,
17
- format: "json",
18
- failOn: "critical", // Don't fail on high so we can test output
19
- changed: false,
20
- };
21
- // Capture console output
22
- const originalLog = console.log;
23
- const logs = [];
24
- console.log = (...args) => logs.push(args.join(" "));
25
- await executeScan(tmpDir, options);
26
- console.log = originalLog;
27
- // Read and validate output
28
- const content = fs.readFileSync(outputPath, "utf-8");
29
- const artifact = JSON.parse(content);
30
- const result = ScanArtifactSchema.safeParse(artifact);
31
- expect(result.success).toBe(true);
32
- if (result.success) {
33
- expect(result.data.artifactVersion).toBe("0.1");
34
- expect(result.data.tool.name).toBe("vibecheck");
35
- expect(result.data.findings.length).toBeGreaterThan(0);
36
- }
37
- }
38
- finally {
39
- fs.rmSync(tmpDir, { recursive: true });
40
- }
41
- });
42
- it("includes repo info when available", async () => {
43
- const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "vibecheck-test-"));
44
- const outputPath = path.join(tmpDir, "scan.json");
45
- fs.writeFileSync(path.join(tmpDir, "app.ts"), `const x = 1;`);
46
- try {
47
- const options = {
48
- out: outputPath,
49
- format: "json",
50
- repoName: "test-repo",
51
- failOn: "critical",
52
- changed: false,
53
- };
54
- const originalLog = console.log;
55
- console.log = () => { };
56
- await executeScan(tmpDir, options);
57
- console.log = originalLog;
58
- const artifact = JSON.parse(fs.readFileSync(outputPath, "utf-8"));
59
- expect(artifact.repo.name).toBe("test-repo");
60
- }
61
- finally {
62
- fs.rmSync(tmpDir, { recursive: true });
63
- }
64
- });
65
- it("includes metrics in output", async () => {
66
- const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "vibecheck-test-"));
67
- const outputPath = path.join(tmpDir, "scan.json");
68
- fs.writeFileSync(path.join(tmpDir, "app.ts"), `const x = 1;`);
69
- try {
70
- const options = {
71
- out: outputPath,
72
- format: "json",
73
- failOn: "critical",
74
- changed: false,
75
- };
76
- const originalLog = console.log;
77
- console.log = () => { };
78
- await executeScan(tmpDir, options);
79
- console.log = originalLog;
80
- const artifact = JSON.parse(fs.readFileSync(outputPath, "utf-8"));
81
- expect(artifact.metrics).toBeDefined();
82
- expect(artifact.metrics.filesScanned).toBe(1);
83
- expect(artifact.metrics.scanDurationMs).toBeGreaterThanOrEqual(0);
84
- }
85
- finally {
86
- fs.rmSync(tmpDir, { recursive: true });
87
- }
88
- });
89
- it("exits with non-zero when findings exceed threshold", async () => {
90
- const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "vibecheck-test-"));
91
- const outputPath = path.join(tmpDir, "scan.json");
92
- // Create file with high severity finding
93
- fs.writeFileSync(path.join(tmpDir, "app.ts"), `const key = process.env.API_SECRET_KEY;`);
94
- try {
95
- const options = {
96
- out: outputPath,
97
- format: "json",
98
- failOn: "high",
99
- changed: false,
100
- };
101
- const originalLog = console.log;
102
- console.log = () => { };
103
- const exitCode = await executeScan(tmpDir, options);
104
- console.log = originalLog;
105
- expect(exitCode).toBe(1);
106
- }
107
- finally {
108
- fs.rmSync(tmpDir, { recursive: true });
109
- }
110
- });
111
- });
112
- describe("explain command", () => {
113
- it("reads and displays artifact", async () => {
114
- const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "vibecheck-test-"));
115
- const artifactPath = path.join(tmpDir, "scan.json");
116
- const artifact = {
117
- artifactVersion: "0.1",
118
- generatedAt: new Date().toISOString(),
119
- tool: { name: "vibecheck", version: "0.0.1" },
120
- summary: {
121
- totalFindings: 1,
122
- bySeverity: { critical: 0, high: 1, medium: 0, low: 0, info: 0 },
123
- byCategory: {
124
- auth: 1,
125
- validation: 0,
126
- middleware: 0,
127
- secrets: 0,
128
- injection: 0,
129
- privacy: 0,
130
- config: 0,
131
- other: 0,
132
- },
133
- },
134
- findings: [
135
- {
136
- id: "test-001",
137
- severity: "high",
138
- confidence: 0.9,
139
- category: "auth",
140
- ruleId: "VC-AUTH-001",
141
- title: "Test finding",
142
- description: "Test description",
143
- evidence: [
144
- { file: "test.ts", startLine: 1, endLine: 1, label: "Test label" },
145
- ],
146
- remediation: { recommendedFix: "Fix it" },
147
- fingerprint: "abc123",
148
- },
149
- ],
150
- };
151
- fs.writeFileSync(artifactPath, JSON.stringify(artifact));
152
- try {
153
- const originalLog = console.log;
154
- const logs = [];
155
- console.log = (...args) => logs.push(args.join(" "));
156
- const exitCode = await executeExplain(artifactPath, { limit: 5 });
157
- console.log = originalLog;
158
- expect(exitCode).toBe(0);
159
- expect(logs.some((l) => l.includes("VIBECHECK SCAN REPORT"))).toBe(true);
160
- expect(logs.some((l) => l.includes("Test finding"))).toBe(true);
161
- }
162
- finally {
163
- fs.rmSync(tmpDir, { recursive: true });
164
- }
165
- });
166
- it("returns error for invalid artifact", async () => {
167
- const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "vibecheck-test-"));
168
- const artifactPath = path.join(tmpDir, "invalid.json");
169
- fs.writeFileSync(artifactPath, JSON.stringify({ invalid: true }));
170
- try {
171
- const originalLog = console.log;
172
- const originalError = console.error;
173
- console.log = () => { };
174
- console.error = () => { };
175
- const exitCode = await executeExplain(artifactPath, { limit: 5 });
176
- console.log = originalLog;
177
- console.error = originalError;
178
- expect(exitCode).toBe(1);
179
- }
180
- finally {
181
- fs.rmSync(tmpDir, { recursive: true });
182
- }
183
- });
184
- });
185
- describe("artifact output shape", () => {
186
- it("has correct structure", async () => {
187
- const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "vibecheck-test-"));
188
- const outputPath = path.join(tmpDir, "scan.json");
189
- fs.writeFileSync(path.join(tmpDir, "app.ts"), `import { z } from "zod";
190
- // unused
191
- `);
192
- try {
193
- const options = {
194
- out: outputPath,
195
- format: "json",
196
- failOn: "critical",
197
- changed: false,
198
- };
199
- const originalLog = console.log;
200
- console.log = () => { };
201
- await executeScan(tmpDir, options);
202
- console.log = originalLog;
203
- const artifact = JSON.parse(fs.readFileSync(outputPath, "utf-8"));
204
- // Check top-level structure
205
- expect(artifact).toHaveProperty("artifactVersion", "0.1");
206
- expect(artifact).toHaveProperty("generatedAt");
207
- expect(artifact).toHaveProperty("tool");
208
- expect(artifact).toHaveProperty("summary");
209
- expect(artifact).toHaveProperty("findings");
210
- // Check tool info
211
- expect(artifact.tool).toHaveProperty("name", "vibecheck");
212
- expect(artifact.tool).toHaveProperty("version");
213
- // Check summary structure
214
- expect(artifact.summary).toHaveProperty("totalFindings");
215
- expect(artifact.summary).toHaveProperty("bySeverity");
216
- expect(artifact.summary).toHaveProperty("byCategory");
217
- // Check finding structure (if any)
218
- if (artifact.findings.length > 0) {
219
- const finding = artifact.findings[0];
220
- expect(finding).toHaveProperty("id");
221
- expect(finding).toHaveProperty("severity");
222
- expect(finding).toHaveProperty("confidence");
223
- expect(finding).toHaveProperty("category");
224
- expect(finding).toHaveProperty("ruleId");
225
- expect(finding).toHaveProperty("title");
226
- expect(finding).toHaveProperty("description");
227
- expect(finding).toHaveProperty("evidence");
228
- expect(finding).toHaveProperty("remediation");
229
- expect(finding).toHaveProperty("fingerprint");
230
- // Check ruleId format
231
- expect(finding.ruleId).toMatch(/^VC-[A-Z]+-\d{3}$/);
232
- // Check evidence structure
233
- expect(finding.evidence[0]).toHaveProperty("file");
234
- expect(finding.evidence[0]).toHaveProperty("startLine");
235
- expect(finding.evidence[0]).toHaveProperty("endLine");
236
- expect(finding.evidence[0]).toHaveProperty("label");
237
- }
238
- }
239
- finally {
240
- fs.rmSync(tmpDir, { recursive: true });
241
- }
242
- });
243
- });
@@ -1,36 +0,0 @@
1
- import { prisma } from "@/lib/prisma";
2
- import { getServerSession } from "next-auth";
3
- import { z } from "zod";
4
- const userSchema = z.object({
5
- name: z.string(),
6
- email: z.string().email(),
7
- });
8
- // Safe: Has auth check
9
- export async function POST(request) {
10
- const session = await getServerSession();
11
- if (!session) {
12
- return Response.json({ error: "Unauthorized" }, { status: 401 });
13
- }
14
- const body = await request.json();
15
- // Safe: Validation result is used
16
- const validatedData = userSchema.parse(body);
17
- const user = await prisma.user.create({
18
- data: validatedData,
19
- });
20
- // Safe: Not logging sensitive data
21
- console.log("Created user:", { id: user.id, timestamp: Date.now() });
22
- return Response.json(user);
23
- }
24
- // Safe: Has auth check
25
- export async function DELETE(request) {
26
- const session = await getServerSession();
27
- if (!session) {
28
- return Response.json({ error: "Unauthorized" }, { status: 401 });
29
- }
30
- const { searchParams } = new URL(request.url);
31
- const id = searchParams.get("id");
32
- await prisma.user.delete({
33
- where: { id },
34
- });
35
- return Response.json({ success: true });
36
- }
@@ -1,28 +0,0 @@
1
- import { prisma } from "@/lib/prisma";
2
- import { z } from "zod";
3
- const userSchema = z.object({
4
- name: z.string(),
5
- email: z.string().email(),
6
- });
7
- // VC-AUTH-001: No auth check before database write
8
- export async function POST(request) {
9
- const body = await request.json();
10
- // VC-VAL-001: Validation called but result ignored
11
- userSchema.parse(body);
12
- // Using raw body instead of validated data
13
- const user = await prisma.user.create({
14
- data: body,
15
- });
16
- // VC-PRIV-001: Logging sensitive data
17
- console.log("Created user:", { email: body.email, password: body.password });
18
- return Response.json(user);
19
- }
20
- // VC-AUTH-001: Critical - delete without auth
21
- export async function DELETE(request) {
22
- const { searchParams } = new URL(request.url);
23
- const id = searchParams.get("id");
24
- await prisma.user.delete({
25
- where: { id },
26
- });
27
- return Response.json({ success: true });
28
- }
@@ -1,4 +0,0 @@
1
- export declare const JWT_SECRET: string;
2
- export declare const SESSION_SECRET: string;
3
- export declare const API_URL: string;
4
- //# sourceMappingURL=config.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../../../../src/__tests__/fixtures/vulnerable-app/lib/config.ts"],"names":[],"mappings":"AACA,eAAO,MAAM,UAAU,QAA6C,CAAC;AAGrE,eAAO,MAAM,cAAc,QAA8C,CAAC;AAG1E,eAAO,MAAM,OAAO,QAAiD,CAAC"}
@@ -1,6 +0,0 @@
1
- // VC-CONFIG-002: Insecure default for critical secret
2
- export const JWT_SECRET = process.env.JWT_SECRET || "dev-secret-123";
3
- // VC-CONFIG-002: Another insecure default
4
- export const SESSION_SECRET = process.env.SESSION_SECRET ?? "session-dev";
5
- // Safe - not a secret
6
- export const API_URL = process.env.API_URL || "http://localhost:3000";
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=env-config.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"env-config.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/scanners/env-config.test.ts"],"names":[],"mappings":""}
@@ -1,142 +0,0 @@
1
- import { describe, it, expect } from "vitest";
2
- import { parseEnvExample, findEnvUsages, scanEnvConfig, } from "../../scanners/env-config.js";
3
- import path from "node:path";
4
- import fs from "node:fs";
5
- import os from "node:os";
6
- describe("parseEnvExample", () => {
7
- it("parses simple env file", () => {
8
- const content = `
9
- DATABASE_URL=
10
- API_KEY=your-key-here
11
- SECRET_TOKEN=
12
- `;
13
- const vars = parseEnvExample(content);
14
- expect(vars.has("DATABASE_URL")).toBe(true);
15
- expect(vars.has("API_KEY")).toBe(true);
16
- expect(vars.has("SECRET_TOKEN")).toBe(true);
17
- });
18
- it("ignores comments", () => {
19
- const content = `
20
- # This is a comment
21
- DATABASE_URL=
22
- # API_KEY=should-be-ignored
23
- `;
24
- const vars = parseEnvExample(content);
25
- expect(vars.has("DATABASE_URL")).toBe(true);
26
- expect(vars.has("API_KEY")).toBe(false);
27
- });
28
- it("handles empty lines", () => {
29
- const content = `
30
-
31
- DATABASE_URL=
32
-
33
- API_KEY=
34
-
35
- `;
36
- const vars = parseEnvExample(content);
37
- expect(vars.size).toBe(2);
38
- });
39
- it("handles vars without values", () => {
40
- const content = `DATABASE_URL`;
41
- const vars = parseEnvExample(content);
42
- expect(vars.has("DATABASE_URL")).toBe(true);
43
- });
44
- });
45
- describe("findEnvUsages", () => {
46
- it("finds process.env.VAR usage", () => {
47
- const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "vibecheck-test-"));
48
- const filePath = path.join(tmpDir, "test.ts");
49
- fs.writeFileSync(filePath, `
50
- const url = process.env.DATABASE_URL;
51
- const key = process.env.API_KEY;
52
- `);
53
- try {
54
- const usages = findEnvUsages(["test.ts"], tmpDir);
55
- expect(usages).toHaveLength(2);
56
- expect(usages[0].name).toBe("DATABASE_URL");
57
- expect(usages[1].name).toBe("API_KEY");
58
- }
59
- finally {
60
- fs.rmSync(tmpDir, { recursive: true });
61
- }
62
- });
63
- it("finds bracket notation usage", () => {
64
- const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "vibecheck-test-"));
65
- const filePath = path.join(tmpDir, "test.ts");
66
- fs.writeFileSync(filePath, `const url = process.env["DATABASE_URL"];`);
67
- try {
68
- const usages = findEnvUsages(["test.ts"], tmpDir);
69
- expect(usages).toHaveLength(1);
70
- expect(usages[0].name).toBe("DATABASE_URL");
71
- }
72
- finally {
73
- fs.rmSync(tmpDir, { recursive: true });
74
- }
75
- });
76
- it("returns correct line numbers", () => {
77
- const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "vibecheck-test-"));
78
- const filePath = path.join(tmpDir, "test.ts");
79
- fs.writeFileSync(filePath, `// line 1
80
- // line 2
81
- const x = process.env.MY_VAR; // line 3
82
- `);
83
- try {
84
- const usages = findEnvUsages(["test.ts"], tmpDir);
85
- expect(usages[0].line).toBe(3);
86
- }
87
- finally {
88
- fs.rmSync(tmpDir, { recursive: true });
89
- }
90
- });
91
- });
92
- describe("scanEnvConfig", () => {
93
- it("creates findings for undocumented env vars", async () => {
94
- const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "vibecheck-test-"));
95
- const filePath = path.join(tmpDir, "app.ts");
96
- fs.writeFileSync(filePath, `const url = process.env.DATABASE_URL;`);
97
- try {
98
- const context = {
99
- targetDir: tmpDir,
100
- sourceFiles: ["app.ts"],
101
- };
102
- const findings = await scanEnvConfig(context);
103
- expect(findings).toHaveLength(1);
104
- expect(findings[0].ruleId).toBe("VC-CONFIG-001");
105
- expect(findings[0].title).toContain("DATABASE_URL");
106
- }
107
- finally {
108
- fs.rmSync(tmpDir, { recursive: true });
109
- }
110
- });
111
- it("does not create findings for documented vars", async () => {
112
- const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "vibecheck-test-"));
113
- fs.writeFileSync(path.join(tmpDir, "app.ts"), `const url = process.env.DATABASE_URL;`);
114
- fs.writeFileSync(path.join(tmpDir, ".env.example"), "DATABASE_URL=");
115
- try {
116
- const context = {
117
- targetDir: tmpDir,
118
- sourceFiles: ["app.ts"],
119
- };
120
- const findings = await scanEnvConfig(context);
121
- expect(findings).toHaveLength(0);
122
- }
123
- finally {
124
- fs.rmSync(tmpDir, { recursive: true });
125
- }
126
- });
127
- it("marks SECRET-like vars as high severity", async () => {
128
- const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "vibecheck-test-"));
129
- fs.writeFileSync(path.join(tmpDir, "app.ts"), `const key = process.env.API_SECRET_KEY;`);
130
- try {
131
- const context = {
132
- targetDir: tmpDir,
133
- sourceFiles: ["app.ts"],
134
- };
135
- const findings = await scanEnvConfig(context);
136
- expect(findings[0].severity).toBe("high");
137
- }
138
- finally {
139
- fs.rmSync(tmpDir, { recursive: true });
140
- }
141
- });
142
- });
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=nextjs-middleware.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"nextjs-middleware.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/scanners/nextjs-middleware.test.ts"],"names":[],"mappings":""}