guardvibe 2.5.0 → 2.7.4
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/CHANGELOG.md +35 -0
- package/README.md +43 -14
- package/build/cli/args.d.ts +15 -0
- package/build/cli/args.js +78 -0
- package/build/cli/ci.d.ts +5 -0
- package/build/cli/ci.js +67 -0
- package/build/cli/doctor.d.ts +5 -0
- package/build/cli/doctor.js +35 -0
- package/build/cli/hook.d.ts +5 -0
- package/build/cli/hook.js +90 -0
- package/build/cli/init.d.ts +5 -0
- package/build/cli/init.js +214 -0
- package/build/cli/remediation.d.ts +14 -0
- package/build/cli/remediation.js +91 -0
- package/build/cli/scan.d.ts +11 -0
- package/build/cli/scan.js +227 -0
- package/build/cli.js +33 -639
- package/build/data/rules/ai-host-security.d.ts +2 -0
- package/build/data/rules/ai-host-security.js +128 -0
- package/build/data/rules/ai-tool-runtime.d.ts +2 -0
- package/build/data/rules/ai-tool-runtime.js +54 -0
- package/build/data/rules/index.js +4 -0
- package/build/index.js +36 -0
- package/build/server/register.d.ts +7 -0
- package/build/server/register.js +7 -0
- package/build/server/types.d.ts +40 -0
- package/build/server/types.js +138 -0
- package/build/tools/audit-mcp-config.d.ts +10 -0
- package/build/tools/audit-mcp-config.js +296 -0
- package/build/tools/check-code.js +3 -0
- package/build/tools/doctor.d.ts +14 -0
- package/build/tools/doctor.js +123 -0
- package/build/tools/scan-directory.js +2 -0
- package/build/tools/scan-host-config.d.ts +10 -0
- package/build/tools/scan-host-config.js +181 -0
- package/build/tools/scan-staged.js +2 -0
- package/build/utils/banner.d.ts +36 -0
- package/build/utils/banner.js +66 -0
- package/package.json +2 -3
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { execFileSync } from "child_process";
|
|
2
2
|
import { extname, basename } from "path";
|
|
3
3
|
import { analyzeCode, formatFindingsJson } from "./check-code.js";
|
|
4
|
+
import { securityBanner } from "../utils/banner.js";
|
|
4
5
|
const EXTENSION_MAP = {
|
|
5
6
|
".js": "javascript", ".jsx": "javascript", ".mjs": "javascript", ".cjs": "javascript",
|
|
6
7
|
".ts": "typescript", ".tsx": "typescript", ".mts": "typescript", ".cts": "typescript",
|
|
@@ -135,5 +136,6 @@ export function scanStaged(cwd = process.cwd(), format = "markdown", rules) {
|
|
|
135
136
|
if (skippedFiles.length > 0) {
|
|
136
137
|
lines.push("", `*Skipped ${skippedFiles.length} files with unsupported extensions.*`);
|
|
137
138
|
}
|
|
139
|
+
lines.push(securityBanner({ total: totalIssues, critical: totalCritical, high: totalHigh, medium: totalMedium, score, grade, filesScanned: scannedCount, context: "Pre-Commit" }));
|
|
138
140
|
return lines.join("\n");
|
|
139
141
|
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared security summary banner — appended to the end of every CLI command output.
|
|
3
|
+
* Gives users an instant, human-readable security status in one line.
|
|
4
|
+
*/
|
|
5
|
+
export interface BannerInput {
|
|
6
|
+
/** Total findings count */
|
|
7
|
+
total: number;
|
|
8
|
+
critical: number;
|
|
9
|
+
high: number;
|
|
10
|
+
medium: number;
|
|
11
|
+
low?: number;
|
|
12
|
+
/** Numeric score 0-100 (optional — will be computed if not provided) */
|
|
13
|
+
score?: number;
|
|
14
|
+
/** Grade A-F (optional — will be computed from score) */
|
|
15
|
+
grade?: string;
|
|
16
|
+
/** Number of files scanned */
|
|
17
|
+
filesScanned?: number;
|
|
18
|
+
/** Context label for the banner (e.g., "Host Security", "Pre-Commit") */
|
|
19
|
+
context?: string;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Generate the summary banner line for terminal output.
|
|
23
|
+
*
|
|
24
|
+
* Examples:
|
|
25
|
+
* 🛡️ GuardVibe: A (95/100) — 0 critical, 0 high, 2 medium | 42 files scanned
|
|
26
|
+
* 🛡️ GuardVibe: F (12/100) — 5 critical, 3 high, 8 medium | 42 files scanned
|
|
27
|
+
* 🛡️ GuardVibe: Clean — no issues found | 6 files scanned
|
|
28
|
+
*/
|
|
29
|
+
export declare function securityBanner(input: BannerInput): string;
|
|
30
|
+
/**
|
|
31
|
+
* Generate the JSON summary banner object — added to JSON output's summary.
|
|
32
|
+
*/
|
|
33
|
+
export declare function bannerFields(input: BannerInput): {
|
|
34
|
+
grade: string;
|
|
35
|
+
score: number;
|
|
36
|
+
};
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared security summary banner — appended to the end of every CLI command output.
|
|
3
|
+
* Gives users an instant, human-readable security status in one line.
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Compute grade from score.
|
|
7
|
+
*/
|
|
8
|
+
function gradeFromScore(score) {
|
|
9
|
+
if (score >= 90)
|
|
10
|
+
return "A";
|
|
11
|
+
if (score >= 75)
|
|
12
|
+
return "B";
|
|
13
|
+
if (score >= 60)
|
|
14
|
+
return "C";
|
|
15
|
+
if (score >= 40)
|
|
16
|
+
return "D";
|
|
17
|
+
return "F";
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Compute score from findings if not provided.
|
|
21
|
+
* Uses weighted density formula consistent with scan-directory.ts.
|
|
22
|
+
*/
|
|
23
|
+
function computeScore(input) {
|
|
24
|
+
if (input.score !== undefined)
|
|
25
|
+
return input.score;
|
|
26
|
+
const files = Math.max(input.filesScanned ?? 1, 1);
|
|
27
|
+
const weighted = input.critical * 15 + input.high * 5 + input.medium * 0.5;
|
|
28
|
+
const density = weighted / files;
|
|
29
|
+
return Math.max(0, Math.min(100, Math.round(100 - Math.min(density, 5) * 20)));
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Generate the summary banner line for terminal output.
|
|
33
|
+
*
|
|
34
|
+
* Examples:
|
|
35
|
+
* 🛡️ GuardVibe: A (95/100) — 0 critical, 0 high, 2 medium | 42 files scanned
|
|
36
|
+
* 🛡️ GuardVibe: F (12/100) — 5 critical, 3 high, 8 medium | 42 files scanned
|
|
37
|
+
* 🛡️ GuardVibe: Clean — no issues found | 6 files scanned
|
|
38
|
+
*/
|
|
39
|
+
export function securityBanner(input) {
|
|
40
|
+
const score = computeScore(input);
|
|
41
|
+
const grade = input.grade ?? gradeFromScore(score);
|
|
42
|
+
const ctx = input.context ? ` ${input.context}:` : ":";
|
|
43
|
+
const filesPart = input.filesScanned !== undefined ? ` | ${input.filesScanned} files scanned` : "";
|
|
44
|
+
if (input.total === 0) {
|
|
45
|
+
return `\n🛡️ GuardVibe${ctx} Clean — no issues found${filesPart}`;
|
|
46
|
+
}
|
|
47
|
+
const parts = [];
|
|
48
|
+
if (input.critical > 0)
|
|
49
|
+
parts.push(`${input.critical} critical`);
|
|
50
|
+
if (input.high > 0)
|
|
51
|
+
parts.push(`${input.high} high`);
|
|
52
|
+
if (input.medium > 0)
|
|
53
|
+
parts.push(`${input.medium} medium`);
|
|
54
|
+
if ((input.low ?? 0) > 0)
|
|
55
|
+
parts.push(`${input.low} low`);
|
|
56
|
+
const breakdown = parts.join(", ");
|
|
57
|
+
return `\n🛡️ GuardVibe${ctx} ${grade} (${score}/100) — ${breakdown}${filesPart}`;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Generate the JSON summary banner object — added to JSON output's summary.
|
|
61
|
+
*/
|
|
62
|
+
export function bannerFields(input) {
|
|
63
|
+
const score = computeScore(input);
|
|
64
|
+
const grade = input.grade ?? gradeFromScore(score);
|
|
65
|
+
return { grade, score };
|
|
66
|
+
}
|
package/package.json
CHANGED
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "guardvibe",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.7.4",
|
|
4
4
|
"mcpName": "io.github.goklab/guardvibe",
|
|
5
|
-
"description": "Security MCP for vibe coding.
|
|
5
|
+
"description": "Security MCP for vibe coding. 330 rules, 29 tools, CLI + doctor. Host security: CVE-2025-59536 hook injection, CVE-2026-21852 base URL hijack, MCP config audit, AI host hardening. Plus Next.js, Supabase, Clerk, Stripe, Prisma, tRPC, Hono, GraphQL, Convex, Turso, Uploadthing, AI SDK, and the full AI-generated stack.",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"bin": {
|
|
8
8
|
"guardvibe": "build/cli.js",
|
|
9
|
-
"guardvibe-init": "build/cli.js",
|
|
10
9
|
"guardvibe-scan": "build/cli.js"
|
|
11
10
|
},
|
|
12
11
|
"main": "./build/index.js",
|