@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,124 +0,0 @@
|
|
|
1
|
-
import { resolvePath, readFileSync } from "../../utils/file-utils.js";
|
|
2
|
-
import { generateFingerprint, generateFindingId } from "../../utils/fingerprint.js";
|
|
3
|
-
const RULE_ID = "VC-PRIV-003";
|
|
4
|
-
/**
|
|
5
|
-
* VC-PRIV-003: Debug flags enabled in production-ish config
|
|
6
|
-
*
|
|
7
|
-
* Detect:
|
|
8
|
-
* - next.config.* or server config with `dev: true`, `debug: true`, or logging level "debug"
|
|
9
|
-
*
|
|
10
|
-
* Precision:
|
|
11
|
-
* - Only if NODE_ENV is checked or project appears production-ready
|
|
12
|
-
*/
|
|
13
|
-
export async function scanDebugFlags(context) {
|
|
14
|
-
const { repoRoot, fileIndex } = context;
|
|
15
|
-
const findings = [];
|
|
16
|
-
// Check if project appears production-ready
|
|
17
|
-
const hasVercelConfig = fileIndex.configFiles.some((f) => f.includes("vercel.json"));
|
|
18
|
-
const pkgPath = resolvePath(repoRoot, "package.json");
|
|
19
|
-
const pkgContent = readFileSync(pkgPath);
|
|
20
|
-
const hasBuildScript = pkgContent && /"build"\s*:/.test(pkgContent);
|
|
21
|
-
const isProdReady = hasVercelConfig || hasBuildScript;
|
|
22
|
-
if (!isProdReady) {
|
|
23
|
-
return findings;
|
|
24
|
-
}
|
|
25
|
-
// Check config files for debug flags
|
|
26
|
-
const configPatterns = [
|
|
27
|
-
"next.config.js",
|
|
28
|
-
"next.config.mjs",
|
|
29
|
-
"next.config.ts",
|
|
30
|
-
"server.config.js",
|
|
31
|
-
"server.config.ts",
|
|
32
|
-
"app.config.js",
|
|
33
|
-
"app.config.ts",
|
|
34
|
-
];
|
|
35
|
-
for (const configFile of configPatterns) {
|
|
36
|
-
const relPath = fileIndex.configFiles.find((f) => f.endsWith(configFile));
|
|
37
|
-
if (!relPath)
|
|
38
|
-
continue;
|
|
39
|
-
const absPath = resolvePath(repoRoot, relPath);
|
|
40
|
-
const content = readFileSync(absPath);
|
|
41
|
-
if (!content)
|
|
42
|
-
continue;
|
|
43
|
-
// Check for debug flags
|
|
44
|
-
const debugPatterns = [
|
|
45
|
-
{ pattern: /\bdev\s*:\s*true\b/, flag: "dev: true" },
|
|
46
|
-
{ pattern: /\bdebug\s*:\s*true\b/, flag: "debug: true" },
|
|
47
|
-
{ pattern: /logLevel\s*:\s*['"]debug['"]/, flag: 'logLevel: "debug"' },
|
|
48
|
-
{ pattern: /LOG_LEVEL\s*=\s*['"]debug['"]/, flag: 'LOG_LEVEL="debug"' },
|
|
49
|
-
{ pattern: /reactStrictMode\s*:\s*false\b/, flag: "reactStrictMode: false" },
|
|
50
|
-
];
|
|
51
|
-
for (const { pattern, flag } of debugPatterns) {
|
|
52
|
-
const match = content.match(pattern);
|
|
53
|
-
if (!match)
|
|
54
|
-
continue;
|
|
55
|
-
// Check if it's conditional on NODE_ENV (which is acceptable)
|
|
56
|
-
const lineIndex = content.substring(0, match.index).split("\n").length;
|
|
57
|
-
const lines = content.split("\n");
|
|
58
|
-
const contextStart = Math.max(0, lineIndex - 5);
|
|
59
|
-
const contextEnd = Math.min(lines.length, lineIndex + 3);
|
|
60
|
-
const contextLines = lines.slice(contextStart, contextEnd).join("\n");
|
|
61
|
-
// Skip if guarded by NODE_ENV check
|
|
62
|
-
if (/process\.env\.NODE_ENV\s*[!=]==?\s*['"]development['"]/i.test(contextLines)) {
|
|
63
|
-
continue;
|
|
64
|
-
}
|
|
65
|
-
const evidence = [
|
|
66
|
-
{
|
|
67
|
-
file: relPath,
|
|
68
|
-
startLine: lineIndex,
|
|
69
|
-
endLine: lineIndex,
|
|
70
|
-
snippet: lines[lineIndex - 1]?.trim() ?? flag,
|
|
71
|
-
label: `Debug flag: ${flag}`,
|
|
72
|
-
},
|
|
73
|
-
];
|
|
74
|
-
if (hasVercelConfig) {
|
|
75
|
-
evidence.push({
|
|
76
|
-
file: "vercel.json",
|
|
77
|
-
startLine: 1,
|
|
78
|
-
endLine: 1,
|
|
79
|
-
snippet: "Project has Vercel deployment config",
|
|
80
|
-
label: "Production deployment detected",
|
|
81
|
-
});
|
|
82
|
-
}
|
|
83
|
-
const fingerprint = generateFingerprint({
|
|
84
|
-
ruleId: RULE_ID,
|
|
85
|
-
file: relPath,
|
|
86
|
-
symbol: flag,
|
|
87
|
-
startLine: lineIndex,
|
|
88
|
-
});
|
|
89
|
-
findings.push({
|
|
90
|
-
id: generateFindingId({
|
|
91
|
-
ruleId: RULE_ID,
|
|
92
|
-
file: relPath,
|
|
93
|
-
symbol: flag,
|
|
94
|
-
}),
|
|
95
|
-
ruleId: RULE_ID,
|
|
96
|
-
title: `Debug flag "${flag}" may be enabled in production`,
|
|
97
|
-
description: `The configuration file contains ${flag} which may be active in production. Debug modes often expose sensitive information, enable verbose error messages, or disable security features. This configuration is not guarded by a NODE_ENV check.`,
|
|
98
|
-
severity: "medium",
|
|
99
|
-
confidence: 0.75,
|
|
100
|
-
category: "config",
|
|
101
|
-
evidence,
|
|
102
|
-
remediation: {
|
|
103
|
-
recommendedFix: `Ensure debug flags are only enabled in development. Use environment variables or NODE_ENV checks.`,
|
|
104
|
-
patch: `// Guard debug flags with environment check:
|
|
105
|
-
const isDev = process.env.NODE_ENV === 'development';
|
|
106
|
-
|
|
107
|
-
module.exports = {
|
|
108
|
-
// Only enable in development
|
|
109
|
-
...(isDev && { debug: true }),
|
|
110
|
-
|
|
111
|
-
// Or use environment variable:
|
|
112
|
-
debug: process.env.DEBUG === 'true',
|
|
113
|
-
};`,
|
|
114
|
-
},
|
|
115
|
-
links: {
|
|
116
|
-
cwe: "https://cwe.mitre.org/data/definitions/489.html",
|
|
117
|
-
owasp: "https://owasp.org/Top10/A05_2021-Security_Misconfiguration/",
|
|
118
|
-
},
|
|
119
|
-
fingerprint,
|
|
120
|
-
});
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
return findings;
|
|
124
|
-
}
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
import type { ScannerPack } from "../types.js";
|
|
2
|
-
export declare const privacyPack: ScannerPack;
|
|
3
|
-
export { scanSensitiveLogging } from "./sensitive-logging.js";
|
|
4
|
-
export { scanOverBroadResponse } from "./over-broad-response.js";
|
|
5
|
-
export { scanDebugFlags } from "./debug-flags.js";
|
|
6
|
-
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/scanners/privacy/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAK/C,eAAO,MAAM,WAAW,EAAE,WAIzB,CAAC;AAEF,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,EAAE,qBAAqB,EAAE,MAAM,0BAA0B,CAAC;AACjE,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC"}
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import { scanSensitiveLogging } from "./sensitive-logging.js";
|
|
2
|
-
import { scanOverBroadResponse } from "./over-broad-response.js";
|
|
3
|
-
import { scanDebugFlags } from "./debug-flags.js";
|
|
4
|
-
export const privacyPack = {
|
|
5
|
-
id: "privacy",
|
|
6
|
-
name: "Privacy & Data Protection",
|
|
7
|
-
scanners: [scanSensitiveLogging, scanOverBroadResponse, scanDebugFlags],
|
|
8
|
-
};
|
|
9
|
-
export { scanSensitiveLogging } from "./sensitive-logging.js";
|
|
10
|
-
export { scanOverBroadResponse } from "./over-broad-response.js";
|
|
11
|
-
export { scanDebugFlags } from "./debug-flags.js";
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import type { Finding } from "@vibecheck/schema";
|
|
2
|
-
import type { ScanContext } from "../types.js";
|
|
3
|
-
/**
|
|
4
|
-
* VC-PRIV-002: Over-broad API response (returns whole ORM model)
|
|
5
|
-
*
|
|
6
|
-
* Detect in route handlers returning:
|
|
7
|
-
* - prisma.<model>.findMany({}) without select/include restrictions AND direct return
|
|
8
|
-
* - prisma.<model>.findUnique({ where }) without select AND direct return
|
|
9
|
-
*
|
|
10
|
-
* Precision:
|
|
11
|
-
* - Only flag if the model name suggests sensitive entity (user, account, etc.)
|
|
12
|
-
* - OR fields: password, hash, token are present in schema.prisma
|
|
13
|
-
*/
|
|
14
|
-
export declare function scanOverBroadResponse(context: ScanContext): Promise<Finding[]>;
|
|
15
|
-
//# sourceMappingURL=over-broad-response.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"over-broad-response.d.ts","sourceRoot":"","sources":["../../../src/scanners/privacy/over-broad-response.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAA0B,MAAM,mBAAmB,CAAC;AACzE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAM/C;;;;;;;;;;GAUG;AACH,wBAAsB,qBAAqB,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC,CAwGpF"}
|
|
@@ -1,109 +0,0 @@
|
|
|
1
|
-
import { resolvePath } from "../../utils/file-utils.js";
|
|
2
|
-
import { generateFingerprint, generateFindingId } from "../../utils/fingerprint.js";
|
|
3
|
-
const RULE_ID = "VC-PRIV-002";
|
|
4
|
-
/**
|
|
5
|
-
* VC-PRIV-002: Over-broad API response (returns whole ORM model)
|
|
6
|
-
*
|
|
7
|
-
* Detect in route handlers returning:
|
|
8
|
-
* - prisma.<model>.findMany({}) without select/include restrictions AND direct return
|
|
9
|
-
* - prisma.<model>.findUnique({ where }) without select AND direct return
|
|
10
|
-
*
|
|
11
|
-
* Precision:
|
|
12
|
-
* - Only flag if the model name suggests sensitive entity (user, account, etc.)
|
|
13
|
-
* - OR fields: password, hash, token are present in schema.prisma
|
|
14
|
-
*/
|
|
15
|
-
export async function scanOverBroadResponse(context) {
|
|
16
|
-
const { repoRoot, fileIndex, helpers, prismaSchemaInfo } = context;
|
|
17
|
-
const findings = [];
|
|
18
|
-
// Scan API route files
|
|
19
|
-
for (const relPath of fileIndex.apiRouteFiles) {
|
|
20
|
-
const absPath = resolvePath(repoRoot, relPath);
|
|
21
|
-
const sourceFile = helpers.parseFile(absPath);
|
|
22
|
-
if (!sourceFile)
|
|
23
|
-
continue;
|
|
24
|
-
const handlers = helpers.findRouteHandlers(sourceFile);
|
|
25
|
-
for (const handler of handlers) {
|
|
26
|
-
const prismaQueries = helpers.findPrismaQueries(handler.functionNode);
|
|
27
|
-
for (const query of prismaQueries) {
|
|
28
|
-
// Skip if has select (data is restricted)
|
|
29
|
-
if (query.hasSelect)
|
|
30
|
-
continue;
|
|
31
|
-
// Check if model has sensitive fields from prisma schema
|
|
32
|
-
let hasSensitiveFields = false;
|
|
33
|
-
if (prismaSchemaInfo) {
|
|
34
|
-
const modelInfo = prismaSchemaInfo.models.get(query.model.toLowerCase());
|
|
35
|
-
if (modelInfo) {
|
|
36
|
-
hasSensitiveFields = modelInfo.hasSensitiveFields;
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
// Determine severity based on sensitive fields
|
|
40
|
-
const severity = hasSensitiveFields ? "high" : "medium";
|
|
41
|
-
const evidence = [
|
|
42
|
-
{
|
|
43
|
-
file: relPath,
|
|
44
|
-
startLine: query.line,
|
|
45
|
-
endLine: query.line,
|
|
46
|
-
snippet: query.snippet,
|
|
47
|
-
label: `Returns full ${query.model} model without select restriction`,
|
|
48
|
-
},
|
|
49
|
-
];
|
|
50
|
-
// Add prisma schema evidence if available
|
|
51
|
-
if (hasSensitiveFields && prismaSchemaInfo) {
|
|
52
|
-
const modelInfo = prismaSchemaInfo.models.get(query.model.toLowerCase());
|
|
53
|
-
if (modelInfo) {
|
|
54
|
-
evidence.push({
|
|
55
|
-
file: "prisma/schema.prisma",
|
|
56
|
-
startLine: 1,
|
|
57
|
-
endLine: 1,
|
|
58
|
-
snippet: `Model ${modelInfo.name} has sensitive fields: ${modelInfo.fields.filter(f => /password|hash|token|secret/i.test(f)).join(", ")}`,
|
|
59
|
-
label: "Sensitive fields in model",
|
|
60
|
-
});
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
const fingerprint = generateFingerprint({
|
|
64
|
-
ruleId: RULE_ID,
|
|
65
|
-
file: relPath,
|
|
66
|
-
symbol: `${query.model}.${query.operation}`,
|
|
67
|
-
startLine: query.line,
|
|
68
|
-
});
|
|
69
|
-
findings.push({
|
|
70
|
-
id: generateFindingId({
|
|
71
|
-
ruleId: RULE_ID,
|
|
72
|
-
file: relPath,
|
|
73
|
-
symbol: `${query.model}.${query.operation}`,
|
|
74
|
-
startLine: query.line,
|
|
75
|
-
}),
|
|
76
|
-
ruleId: RULE_ID,
|
|
77
|
-
title: `Over-broad ${query.model} response exposes all fields`,
|
|
78
|
-
description: `The ${query.operation} query on the ${query.model} model returns all fields without using a \`select\` clause. This may inadvertently expose sensitive fields like passwords, tokens, or internal IDs to API consumers.${hasSensitiveFields ? " The Prisma schema indicates this model contains sensitive fields." : ""}`,
|
|
79
|
-
severity,
|
|
80
|
-
confidence: hasSensitiveFields ? 0.9 : 0.75,
|
|
81
|
-
category: "privacy",
|
|
82
|
-
evidence,
|
|
83
|
-
remediation: {
|
|
84
|
-
recommendedFix: `Use Prisma's \`select\` clause to explicitly choose which fields to return. Never expose password hashes, tokens, or other sensitive data in API responses.`,
|
|
85
|
-
patch: `// Instead of:
|
|
86
|
-
const users = await prisma.${query.model.toLowerCase()}.${query.operation}();
|
|
87
|
-
|
|
88
|
-
// Use select to return only needed fields:
|
|
89
|
-
const users = await prisma.${query.model.toLowerCase()}.${query.operation}({
|
|
90
|
-
select: {
|
|
91
|
-
id: true,
|
|
92
|
-
name: true,
|
|
93
|
-
email: true,
|
|
94
|
-
createdAt: true,
|
|
95
|
-
// Explicitly omit: password, passwordHash, tokens, etc.
|
|
96
|
-
},
|
|
97
|
-
});`,
|
|
98
|
-
},
|
|
99
|
-
links: {
|
|
100
|
-
cwe: "https://cwe.mitre.org/data/definitions/359.html",
|
|
101
|
-
owasp: "https://owasp.org/API-Security/editions/2023/en/0xa3-broken-object-property-level-authorization/",
|
|
102
|
-
},
|
|
103
|
-
fingerprint,
|
|
104
|
-
});
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
return findings;
|
|
109
|
-
}
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import type { Finding } from "@vibecheck/schema";
|
|
2
|
-
import type { ScanContext } from "../types.js";
|
|
3
|
-
/**
|
|
4
|
-
* VC-PRIV-001: Sensitive data logged
|
|
5
|
-
*
|
|
6
|
-
* Detects console.log/info/error or logger calls that include:
|
|
7
|
-
* - tokens, authorization headers, passwords, secrets
|
|
8
|
-
* - Variables named: password, token, auth, authorization, cookie, session, secret, apiKey
|
|
9
|
-
*/
|
|
10
|
-
export declare function scanSensitiveLogging(context: ScanContext): Promise<Finding[]>;
|
|
11
|
-
//# sourceMappingURL=sensitive-logging.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"sensitive-logging.d.ts","sourceRoot":"","sources":["../../../src/scanners/privacy/sensitive-logging.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAgB,MAAM,mBAAmB,CAAC;AAC/D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAM/C;;;;;;GAMG;AACH,wBAAsB,oBAAoB,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC,CA2EnF"}
|
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
import { resolvePath } from "../../utils/file-utils.js";
|
|
2
|
-
import { generateFingerprint, generateFindingId } from "../../utils/fingerprint.js";
|
|
3
|
-
const RULE_ID = "VC-PRIV-001";
|
|
4
|
-
/**
|
|
5
|
-
* VC-PRIV-001: Sensitive data logged
|
|
6
|
-
*
|
|
7
|
-
* Detects console.log/info/error or logger calls that include:
|
|
8
|
-
* - tokens, authorization headers, passwords, secrets
|
|
9
|
-
* - Variables named: password, token, auth, authorization, cookie, session, secret, apiKey
|
|
10
|
-
*/
|
|
11
|
-
export async function scanSensitiveLogging(context) {
|
|
12
|
-
const { repoRoot, fileIndex, helpers } = context;
|
|
13
|
-
const findings = [];
|
|
14
|
-
// Scan all source files
|
|
15
|
-
for (const relPath of fileIndex.allSourceFiles) {
|
|
16
|
-
const absPath = resolvePath(repoRoot, relPath);
|
|
17
|
-
const sourceFile = helpers.parseFile(absPath);
|
|
18
|
-
if (!sourceFile)
|
|
19
|
-
continue;
|
|
20
|
-
// Find all functions in the file
|
|
21
|
-
const functions = sourceFile.getFunctions();
|
|
22
|
-
const arrowFunctions = sourceFile.getDescendantsOfKind(
|
|
23
|
-
// @ts-expect-error - ts-morph types
|
|
24
|
-
sourceFile.getProject().getTypeChecker().compilerObject.SyntaxKind?.ArrowFunction ?? 213);
|
|
25
|
-
// Check module-level code as well
|
|
26
|
-
const sensitiveLogCalls = helpers.findSensitiveLogCalls({
|
|
27
|
-
// Create a pseudo-function node that covers the whole file
|
|
28
|
-
getDescendantsOfKind: (kind) => sourceFile.getDescendantsOfKind(kind),
|
|
29
|
-
getText: () => sourceFile.getText(),
|
|
30
|
-
});
|
|
31
|
-
for (const logCall of sensitiveLogCalls) {
|
|
32
|
-
const evidence = [
|
|
33
|
-
{
|
|
34
|
-
file: relPath,
|
|
35
|
-
startLine: logCall.line,
|
|
36
|
-
endLine: logCall.line,
|
|
37
|
-
snippet: logCall.snippet,
|
|
38
|
-
label: `Sensitive data logged: ${logCall.sensitiveVars.join(", ")}`,
|
|
39
|
-
},
|
|
40
|
-
];
|
|
41
|
-
const fingerprint = generateFingerprint({
|
|
42
|
-
ruleId: RULE_ID,
|
|
43
|
-
file: relPath,
|
|
44
|
-
symbol: logCall.sensitiveVars[0],
|
|
45
|
-
startLine: logCall.line,
|
|
46
|
-
});
|
|
47
|
-
findings.push({
|
|
48
|
-
id: generateFindingId({
|
|
49
|
-
ruleId: RULE_ID,
|
|
50
|
-
file: relPath,
|
|
51
|
-
symbol: logCall.sensitiveVars[0],
|
|
52
|
-
startLine: logCall.line,
|
|
53
|
-
}),
|
|
54
|
-
ruleId: RULE_ID,
|
|
55
|
-
title: `Sensitive data in logs: ${logCall.sensitiveVars.join(", ")}`,
|
|
56
|
-
description: `The ${logCall.logMethod} call includes sensitive data (${logCall.sensitiveVars.join(", ")}). This could expose credentials, tokens, or other sensitive information in log files, monitoring systems, or console output.`,
|
|
57
|
-
severity: logCall.severity,
|
|
58
|
-
confidence: 0.88,
|
|
59
|
-
category: "privacy",
|
|
60
|
-
evidence,
|
|
61
|
-
remediation: {
|
|
62
|
-
recommendedFix: `Remove sensitive data from log statements. Only log non-sensitive identifiers like user IDs, timestamps, or action types.`,
|
|
63
|
-
patch: `// Instead of:
|
|
64
|
-
console.log("Login:", { email, password });
|
|
65
|
-
|
|
66
|
-
// Do:
|
|
67
|
-
console.log("Login attempt:", { email, timestamp: Date.now() });`,
|
|
68
|
-
},
|
|
69
|
-
links: {
|
|
70
|
-
cwe: "https://cwe.mitre.org/data/definitions/532.html",
|
|
71
|
-
owasp: "https://owasp.org/Top10/A09_2021-Security_Logging_and_Monitoring_Failures/",
|
|
72
|
-
},
|
|
73
|
-
fingerprint,
|
|
74
|
-
});
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
return findings;
|
|
78
|
-
}
|