guardvibe 2.4.5 → 2.7.3
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 +42 -0
- package/README.md +44 -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 +222 -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 +57 -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 +130 -0
- package/build/tools/audit-mcp-config.d.ts +10 -0
- package/build/tools/audit-mcp-config.js +296 -0
- package/build/tools/cross-file-taint.d.ts +81 -0
- package/build/tools/cross-file-taint.js +554 -0
- package/build/tools/doctor.d.ts +14 -0
- package/build/tools/doctor.js +123 -0
- package/build/tools/scan-host-config.d.ts +10 -0
- package/build/tools/scan-host-config.js +181 -0
- package/package.json +3 -4
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,48 @@ All notable changes to GuardVibe are documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [2.7.1] - 2026-04-04
|
|
9
|
+
|
|
10
|
+
### Fixed
|
|
11
|
+
- `--output` flag without value no longer creates a file named "true" — now errors with clear message
|
|
12
|
+
- `--fail-on` default standardized to "critical" across all CLI commands (was inconsistently "high" in `guardvibe-scan`)
|
|
13
|
+
- `--format` with invalid value (e.g., "yaml") now errors explicitly instead of silently falling back to markdown
|
|
14
|
+
- `--output` with nested path (e.g., `--output reports/deep/out.json`) now auto-creates parent directories
|
|
15
|
+
- CLI error messages now consistently use `[ERR]` prefix across all commands
|
|
16
|
+
|
|
17
|
+
### Changed
|
|
18
|
+
- Secret redaction expanded from 3 to 13 patterns — now covers AWS keys, GitHub tokens, Stripe keys, Google API keys, Slack tokens, SendGrid keys, private key headers, and DATABASE_URL
|
|
19
|
+
- `guardvibe-init` binary entry removed as part of early CLI surface cleanup. Use `guardvibe init` going forward. This simplifies the public CLI before wider adoption.
|
|
20
|
+
|
|
21
|
+
### Added
|
|
22
|
+
- 21 new stabilization tests covering all v2.7.1 fixes
|
|
23
|
+
|
|
24
|
+
## [2.7.0] - 2026-04-04
|
|
25
|
+
|
|
26
|
+
### Added
|
|
27
|
+
- `npx guardvibe doctor` CLI command with `--scope`, `--format`, `--output`, `--fail-on` flags
|
|
28
|
+
- CLI modular decomposition: `src/cli/` with args, init, hook, ci, scan, doctor, remediation modules
|
|
29
|
+
- Host-specific remediation: findings now include platform-tailored fix steps for Claude, Cursor, VS Code, Gemini, Windsurf, Shell, and .env files
|
|
30
|
+
- 13 new doctor CLI tests
|
|
31
|
+
|
|
32
|
+
## [2.6.0] - 2026-04-04
|
|
33
|
+
|
|
34
|
+
### Added
|
|
35
|
+
- Host security: `guardvibe_doctor` unified host hardening scanner
|
|
36
|
+
- `audit_mcp_config` — MCP configuration scanner (CVE-2025-59536 hook injection)
|
|
37
|
+
- `scan_host_config` — environment scanner (CVE-2026-21852 base URL hijack)
|
|
38
|
+
- Four-axis finding model: severity, trustState, verdict, confidence
|
|
39
|
+
- 14 new AI host security rules (VG880-VG895)
|
|
40
|
+
- Secret redaction in all output paths
|
|
41
|
+
- `.guardviberc` allowlist support for trusted servers, base URLs, registries
|
|
42
|
+
|
|
43
|
+
## [2.5.0] - 2026-04-04
|
|
44
|
+
|
|
45
|
+
### Added
|
|
46
|
+
- Cross-file taint analysis — tracks tainted data flowing across module boundaries (`analyze_cross_file_dataflow` tool)
|
|
47
|
+
- Import/export resolution, module graph building, and cross-file taint propagation
|
|
48
|
+
- Detects SQL injection, XSS, open redirect, code injection, and path traversal across files
|
|
49
|
+
|
|
8
50
|
## [2.4.5] - 2026-04-04
|
|
9
51
|
|
|
10
52
|
### Added
|
package/README.md
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
[](https://www.npmjs.com/package/guardvibe)
|
|
7
7
|
[](https://codecov.io/gh/goklab/guardvibe)
|
|
8
8
|
|
|
9
|
-
**The security MCP built for vibe coding.**
|
|
9
|
+
**The security MCP built for vibe coding.** 330 security rules, 29 tools covering the entire AI-generated code journey — from first line to production deployment.
|
|
10
10
|
|
|
11
11
|
Works with **Claude Code, Cursor, Gemini CLI, Codex, VS Code (Copilot), Windsurf**, and any MCP-compatible coding agent.
|
|
12
12
|
|
|
@@ -14,7 +14,7 @@ Works with **Claude Code, Cursor, Gemini CLI, Codex, VS Code (Copilot), Windsurf
|
|
|
14
14
|
|
|
15
15
|
Most security tools are built for enterprise security teams. GuardVibe is built for **you** — the developer using AI to build and ship web apps fast.
|
|
16
16
|
|
|
17
|
-
- **
|
|
17
|
+
- **330 security rules, 29 tools** purpose-built for the stacks AI agents generate
|
|
18
18
|
- **Zero setup friction** — `npx guardvibe` and you're scanning
|
|
19
19
|
- **No account required** — runs 100% locally, no API keys, no cloud
|
|
20
20
|
- **Understands your stack** — not generic SAST, but rules that know Next.js, Supabase, Stripe, Clerk, and the tools you actually use
|
|
@@ -35,12 +35,13 @@ GuardVibe is purpose-built for the AI coding workflow. Traditional tools are exc
|
|
|
35
35
|
| Runs inside AI agents (MCP) | Native | Not supported | Not supported |
|
|
36
36
|
| Zero config setup | `npx guardvibe` | Account + config required | Built-in (limited) |
|
|
37
37
|
| Vibecoding stack rules (Next.js, Supabase, Clerk, tRPC, Hono) | 100+ dedicated | Generic patterns | Not applicable |
|
|
38
|
-
| AI/LLM security (prompt injection, MCP, tool abuse) |
|
|
38
|
+
| AI/LLM security (prompt injection, MCP, tool abuse) | 30 rules | Experimental/None | None |
|
|
39
|
+
| AI host security (CVE-2025-59536, CVE-2026-21852) | `guardvibe doctor` | Not supported | Not supported |
|
|
39
40
|
| Auto-fix suggestions for AI agents | `fix_code` tool | CLI autofix | Not supported |
|
|
40
41
|
| CVE version detection | 21 packages | Extensive | Extensive |
|
|
41
42
|
| Compliance mapping (SOC2, PCI-DSS, HIPAA) | Built-in | Paid tier | None |
|
|
42
43
|
| SARIF CI/CD export | Yes | Yes | Limited |
|
|
43
|
-
| Rule count |
|
|
44
|
+
| Rule count | 330 (focused) | 5000+ (broad) | N/A |
|
|
44
45
|
|
|
45
46
|
**When to use GuardVibe:** You're building with AI agents and want security scanning integrated into your coding workflow — no dashboard, no account, no CI setup.
|
|
46
47
|
|
|
@@ -149,6 +150,9 @@ Resend (email HTML injection), Upstash Redis, Pinecone, PostHog, Google Analytic
|
|
|
149
150
|
### AI / LLM Security
|
|
150
151
|
Prompt injection detection, LLM output sinks, system prompt leaks, MCP server SSRF/path traversal/command injection, `dangerouslyAllowBrowser`, missing `maxTokens`, AI API key client exposure, indirect prompt injection via external data
|
|
151
152
|
|
|
153
|
+
### AI Host Security (NEW in v2.6.0+)
|
|
154
|
+
`guardvibe doctor` — unified host hardening scanner detecting CVE-2025-59536 (hook injection via `.claude/settings.json`), CVE-2026-21852 (API key exfiltration via `ANTHROPIC_BASE_URL` override), MCP config audit, environment scanner, permission analysis. Supports Claude, Cursor, VS Code, Gemini, Windsurf. Host-specific remediation with platform-tailored fix steps.
|
|
155
|
+
|
|
152
156
|
### OWASP API Security
|
|
153
157
|
BOLA/IDOR (Broken Object Level Authorization), mass assignment (spread request body, Object.assign), missing pagination, rate limiting, admin endpoint authorization, verbose error leaks
|
|
154
158
|
|
|
@@ -179,7 +183,7 @@ SOC2, PCI-DSS, HIPAA control mapping with compliance reports
|
|
|
179
183
|
### Supply Chain
|
|
180
184
|
Malicious postinstall scripts, unpinned GitHub Actions, typosquat detection
|
|
181
185
|
|
|
182
|
-
## Tools (
|
|
186
|
+
## Tools (29 MCP tools)
|
|
183
187
|
|
|
184
188
|
| Tool | What it does |
|
|
185
189
|
|------|-------------|
|
|
@@ -201,6 +205,7 @@ Malicious postinstall scripts, unpinned GitHub Actions, typosquat detection
|
|
|
201
205
|
| `scan_secrets_history` | Scan git history for leaked secrets (active and removed) |
|
|
202
206
|
| `policy_check` | Check project against compliance policies defined in .guardviberc |
|
|
203
207
|
| `analyze_dataflow` | Track tainted data flows from user input to dangerous sinks |
|
|
208
|
+
| `analyze_cross_file_dataflow` | **Cross-file taint analysis** — track tainted data across module boundaries |
|
|
204
209
|
| `check_command` | Analyze shell commands for security risks before execution |
|
|
205
210
|
| `scan_config_change` | Compare config file versions to detect security downgrades |
|
|
206
211
|
| `repo_security_posture` | Assess overall repository security posture and map sensitive areas |
|
|
@@ -208,26 +213,31 @@ Malicious postinstall scripts, unpinned GitHub Actions, typosquat detection
|
|
|
208
213
|
| `scan_file` | Real-time single-file scan — designed for post-edit hooks |
|
|
209
214
|
| `scan_changed_files` | Scan only git-changed files — for PRs and incremental CI |
|
|
210
215
|
| `security_stats` | Cumulative security dashboard — scans, fixes, grade trend over time |
|
|
216
|
+
| `guardvibe_doctor` | **Host security audit** — CVE-2025-59536, CVE-2026-21852, MCP config, env scanner |
|
|
217
|
+
| `audit_mcp_config` | Audit MCP server configurations for hook injection, file:// abuse, sensitive paths |
|
|
218
|
+
| `scan_host_config` | Scan shell profiles, .env files for base URL hijack and credential sniffing |
|
|
211
219
|
|
|
212
220
|
All scanning tools support `format: "json"` for machine-readable output.
|
|
213
221
|
|
|
214
|
-
## Security Rules (
|
|
222
|
+
## Security Rules (330 rules across 25 modules)
|
|
215
223
|
|
|
216
224
|
| Category | Rules | Coverage |
|
|
217
225
|
|----------|-------|----------|
|
|
218
226
|
| Core OWASP | 38 | SQL injection, XSS, CSRF, command injection, CORS, SSRF, hardcoded secrets |
|
|
219
227
|
| Next.js App Router | 17 | Server Actions, secret exposure, auth bypass, CSP, redirects |
|
|
220
228
|
| Auth (Clerk / Auth.js / Supabase Auth) | 16 | Middleware, secret keys, session storage, role checks, SSR cookies |
|
|
221
|
-
| Database (Supabase / Prisma / Drizzle) |
|
|
229
|
+
| Database (Supabase / Prisma / Drizzle) | 11 | Raw queries, client exposure, service role leaks, NoSQL injection |
|
|
222
230
|
| OWASP API Security | 10 | BOLA/IDOR, mass assignment, pagination, rate limiting, error leaks |
|
|
223
|
-
| Modern Stack |
|
|
224
|
-
| Deployment Config |
|
|
231
|
+
| Modern Stack | 37 | Zod, tRPC, Hono, GraphQL, Uploadthing, Turso, Convex, OAuth, CSP, webhooks, AI SDK |
|
|
232
|
+
| Deployment Config | 21 | Vercel, Next.js config, Docker Compose, Fly, Render, Netlify, Cloudflare, K8s secrets |
|
|
225
233
|
| Payments (Stripe / Polar / Lemon) | 9 | Webhook signatures, key exposure, price manipulation |
|
|
226
234
|
| Services (Resend / Upstash / Pinecone / PostHog) | 11 | API key leaks, PII tracking, email injection |
|
|
227
235
|
| Web Security | 15 | Webhooks, CSP, .env safety, AI key exposure, cookie handling |
|
|
228
236
|
| React Native / Expo | 10 | AsyncStorage secrets, deep links, ATS, hardcoded URLs |
|
|
229
237
|
| Firebase | 7 | Firestore rules, admin SDK, storage, custom tokens |
|
|
230
238
|
| AI / LLM Security | 16 | Prompt injection, MCP SSRF, excessive agency, indirect injection |
|
|
239
|
+
| **AI Host Security** | **10** | **CVE-2025-59536 hook injection, CVE-2026-21852 base URL hijack, MCP config audit** |
|
|
240
|
+
| **AI Tool Runtime** | **4** | **MCP tool output sanitization, obfuscated descriptions, safety bypass** |
|
|
231
241
|
| CVE Version Intelligence | 21 | Known vulnerable versions in package.json (21 CVEs) |
|
|
232
242
|
| Shell / Bash | 5 | Pipe to bash, chmod 777, rm -rf, sudo password |
|
|
233
243
|
| SQL | 4 | DROP/DELETE without WHERE, stacked queries, GRANT ALL |
|
|
@@ -242,12 +252,32 @@ All scanning tools support `format: "json"` for machine-readable output.
|
|
|
242
252
|
## CLI Commands
|
|
243
253
|
|
|
244
254
|
```bash
|
|
245
|
-
|
|
246
|
-
npx guardvibe
|
|
247
|
-
npx guardvibe
|
|
248
|
-
npx guardvibe
|
|
249
|
-
npx guardvibe
|
|
255
|
+
# Scanning
|
|
256
|
+
npx guardvibe scan [path] # Scan a directory for security issues
|
|
257
|
+
npx guardvibe scan . --format json # JSON output for automation
|
|
258
|
+
npx guardvibe check <file> # Scan a single file
|
|
259
|
+
npx guardvibe diff [base] # Scan only changed files since git ref
|
|
260
|
+
|
|
261
|
+
# Host security audit
|
|
262
|
+
npx guardvibe doctor # Host hardening audit (project scope)
|
|
263
|
+
npx guardvibe doctor --scope host # + shell profiles, global MCP configs
|
|
264
|
+
npx guardvibe doctor --scope full # + home dir configs
|
|
265
|
+
npx guardvibe doctor --format json # JSON output
|
|
266
|
+
|
|
267
|
+
# Setup
|
|
268
|
+
npx guardvibe init <platform> # Setup MCP server (claude, cursor, gemini, all)
|
|
269
|
+
npx guardvibe hook install # Install pre-commit hook
|
|
270
|
+
npx guardvibe hook uninstall # Remove pre-commit hook
|
|
271
|
+
npx guardvibe ci github # Generate GitHub Actions workflow
|
|
272
|
+
|
|
273
|
+
# Pre-commit / CI
|
|
274
|
+
npx guardvibe-scan # Scan staged files (for pre-commit)
|
|
250
275
|
npx guardvibe-scan --format sarif --output results.sarif # CI mode
|
|
276
|
+
|
|
277
|
+
# Options (all scan commands)
|
|
278
|
+
# --format markdown|json|sarif|buddy
|
|
279
|
+
# --output <file> Write results to file
|
|
280
|
+
# --fail-on <level> Exit 1 on findings: critical|high|medium|low|none
|
|
251
281
|
```
|
|
252
282
|
|
|
253
283
|
## Plugin System
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI argument parsing utilities
|
|
3
|
+
*/
|
|
4
|
+
export declare function getStringFlag(flags: Record<string, string | true>, key: string): string | null;
|
|
5
|
+
export declare function validateFormat(flags: Record<string, string | true>): string;
|
|
6
|
+
export declare function getOutputPath(flags: Record<string, string | true>): string | null;
|
|
7
|
+
export declare function parseArgs(args: string[]): {
|
|
8
|
+
flags: Record<string, string | true>;
|
|
9
|
+
positional: string[];
|
|
10
|
+
};
|
|
11
|
+
/**
|
|
12
|
+
* Check if scan results should cause a non-zero exit based on --fail-on flag.
|
|
13
|
+
* Default: "critical" — only exit 1 on critical findings.
|
|
14
|
+
*/
|
|
15
|
+
export declare function shouldFail(result: string, failOn: string): boolean;
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI argument parsing utilities
|
|
3
|
+
*/
|
|
4
|
+
const VALID_FORMATS = new Set(["markdown", "json", "sarif", "buddy"]);
|
|
5
|
+
export function getStringFlag(flags, key) {
|
|
6
|
+
const val = flags[key];
|
|
7
|
+
if (val === undefined || val === true)
|
|
8
|
+
return null;
|
|
9
|
+
return val;
|
|
10
|
+
}
|
|
11
|
+
export function validateFormat(flags) {
|
|
12
|
+
const format = getStringFlag(flags, "format") ?? "markdown";
|
|
13
|
+
if (!VALID_FORMATS.has(format)) {
|
|
14
|
+
console.error(` [ERR] Invalid format "${format}". Use: markdown, json, sarif, or buddy`);
|
|
15
|
+
process.exit(1);
|
|
16
|
+
}
|
|
17
|
+
return format;
|
|
18
|
+
}
|
|
19
|
+
export function getOutputPath(flags) {
|
|
20
|
+
const val = flags.output;
|
|
21
|
+
if (val === undefined)
|
|
22
|
+
return null;
|
|
23
|
+
if (val === true) {
|
|
24
|
+
console.error(" [ERR] --output requires a file path. Usage: --output results.json");
|
|
25
|
+
process.exit(1);
|
|
26
|
+
}
|
|
27
|
+
return val;
|
|
28
|
+
}
|
|
29
|
+
export function parseArgs(args) {
|
|
30
|
+
const flags = {};
|
|
31
|
+
const positional = [];
|
|
32
|
+
for (let i = 0; i < args.length; i++) {
|
|
33
|
+
if (args[i].startsWith("--")) {
|
|
34
|
+
const key = args[i].slice(2);
|
|
35
|
+
const next = args[i + 1];
|
|
36
|
+
if (next && !next.startsWith("--")) {
|
|
37
|
+
flags[key] = next;
|
|
38
|
+
i++;
|
|
39
|
+
}
|
|
40
|
+
else {
|
|
41
|
+
flags[key] = true;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
positional.push(args[i]);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
return { flags, positional };
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Check if scan results should cause a non-zero exit based on --fail-on flag.
|
|
52
|
+
* Default: "critical" — only exit 1 on critical findings.
|
|
53
|
+
*/
|
|
54
|
+
export function shouldFail(result, failOn) {
|
|
55
|
+
if (failOn === "none")
|
|
56
|
+
return false;
|
|
57
|
+
const levels = {
|
|
58
|
+
low: ["critical", "high", "medium", "low"],
|
|
59
|
+
medium: ["critical", "high", "medium"],
|
|
60
|
+
high: ["critical", "high"],
|
|
61
|
+
critical: ["critical"],
|
|
62
|
+
};
|
|
63
|
+
const failLevels = levels[failOn] || levels.critical;
|
|
64
|
+
// Try JSON format first
|
|
65
|
+
try {
|
|
66
|
+
const parsed = JSON.parse(result);
|
|
67
|
+
if (parsed.summary) {
|
|
68
|
+
return failLevels.some(level => (parsed.summary[level] ?? 0) > 0);
|
|
69
|
+
}
|
|
70
|
+
if (parsed.findings) {
|
|
71
|
+
return parsed.findings.some((f) => failLevels.includes(f.severity));
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
catch { /* not JSON, try markdown tags */ }
|
|
75
|
+
// Markdown format: check for [SEVERITY] tags
|
|
76
|
+
const tags = failLevels.map(l => `[${l.toUpperCase()}]`);
|
|
77
|
+
return tags.some(tag => result.includes(tag));
|
|
78
|
+
}
|
package/build/cli/ci.js
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI: guardvibe ci <provider>
|
|
3
|
+
* Generates CI/CD workflow configurations.
|
|
4
|
+
*/
|
|
5
|
+
import { writeFileSync, mkdirSync, existsSync } from "fs";
|
|
6
|
+
import { join } from "path";
|
|
7
|
+
const GITHUB_ACTIONS_WORKFLOW = `name: GuardVibe Security Scan
|
|
8
|
+
|
|
9
|
+
on:
|
|
10
|
+
pull_request:
|
|
11
|
+
branches: [main, master]
|
|
12
|
+
push:
|
|
13
|
+
branches: [main, master]
|
|
14
|
+
|
|
15
|
+
permissions:
|
|
16
|
+
contents: read
|
|
17
|
+
security-events: write
|
|
18
|
+
|
|
19
|
+
jobs:
|
|
20
|
+
security-scan:
|
|
21
|
+
name: Security Scan
|
|
22
|
+
runs-on: ubuntu-latest
|
|
23
|
+
steps:
|
|
24
|
+
- uses: actions/checkout@v4
|
|
25
|
+
with:
|
|
26
|
+
persist-credentials: false
|
|
27
|
+
|
|
28
|
+
- uses: actions/setup-node@v4
|
|
29
|
+
with:
|
|
30
|
+
node-version: "22"
|
|
31
|
+
|
|
32
|
+
- name: Run GuardVibe security scan
|
|
33
|
+
run: npx -y guardvibe-scan --format sarif --output guardvibe-results.sarif
|
|
34
|
+
|
|
35
|
+
- name: Upload SARIF to GitHub Security
|
|
36
|
+
if: always()
|
|
37
|
+
uses: github/codeql-action/upload-sarif@v3
|
|
38
|
+
with:
|
|
39
|
+
sarif_file: guardvibe-results.sarif
|
|
40
|
+
category: guardvibe
|
|
41
|
+
`;
|
|
42
|
+
function generateGitHubActions() {
|
|
43
|
+
const workflowDir = join(process.cwd(), ".github", "workflows");
|
|
44
|
+
if (!existsSync(workflowDir)) {
|
|
45
|
+
mkdirSync(workflowDir, { recursive: true });
|
|
46
|
+
}
|
|
47
|
+
const workflowPath = join(workflowDir, "guardvibe.yml");
|
|
48
|
+
if (existsSync(workflowPath)) {
|
|
49
|
+
console.log(" [OK] .github/workflows/guardvibe.yml already exists.");
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
writeFileSync(workflowPath, GITHUB_ACTIONS_WORKFLOW, "utf-8");
|
|
53
|
+
console.log(" [OK] Created .github/workflows/guardvibe.yml");
|
|
54
|
+
console.log(" [OK] SARIF results will appear in GitHub Security tab.");
|
|
55
|
+
}
|
|
56
|
+
export function runCi(args) {
|
|
57
|
+
const provider = args[0]?.toLowerCase();
|
|
58
|
+
console.log(`\n GuardVibe CI/CD Setup\n`);
|
|
59
|
+
if (provider === "github") {
|
|
60
|
+
generateGitHubActions();
|
|
61
|
+
}
|
|
62
|
+
else {
|
|
63
|
+
console.error(" [ERR] Unknown CI provider. Usage: npx guardvibe ci github");
|
|
64
|
+
process.exit(1);
|
|
65
|
+
}
|
|
66
|
+
console.log();
|
|
67
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI: guardvibe doctor
|
|
3
|
+
* Host hardening audit from terminal with host-specific remediation.
|
|
4
|
+
*/
|
|
5
|
+
import { writeFileSync, existsSync, mkdirSync } from "fs";
|
|
6
|
+
import { resolve, dirname } from "path";
|
|
7
|
+
import { parseArgs, shouldFail, validateFormat, getOutputPath, getStringFlag } from "./args.js";
|
|
8
|
+
import { doctor } from "../tools/doctor.js";
|
|
9
|
+
export async function runDoctor(args) {
|
|
10
|
+
const { flags, positional } = parseArgs(args);
|
|
11
|
+
const targetPath = resolve(positional[0] ?? ".");
|
|
12
|
+
const scope = (getStringFlag(flags, "scope") ?? "project");
|
|
13
|
+
const format = validateFormat(flags);
|
|
14
|
+
const outputFile = getOutputPath(flags);
|
|
15
|
+
if (!["project", "host", "full"].includes(scope)) {
|
|
16
|
+
console.error(` [ERR] Invalid scope "${scope}". Use: project, host, or full`);
|
|
17
|
+
process.exit(1);
|
|
18
|
+
}
|
|
19
|
+
const formatArg = format === "json" ? "json" : "markdown";
|
|
20
|
+
const result = doctor(targetPath, scope, formatArg);
|
|
21
|
+
if (outputFile) {
|
|
22
|
+
const dir = dirname(outputFile);
|
|
23
|
+
if (!existsSync(dir)) {
|
|
24
|
+
mkdirSync(dir, { recursive: true });
|
|
25
|
+
}
|
|
26
|
+
writeFileSync(outputFile, result, "utf-8");
|
|
27
|
+
console.log(` [OK] Results written to ${outputFile}`);
|
|
28
|
+
}
|
|
29
|
+
else {
|
|
30
|
+
console.log(result);
|
|
31
|
+
}
|
|
32
|
+
const failOn = getStringFlag(flags, "fail-on") ?? "high";
|
|
33
|
+
if (shouldFail(result, failOn))
|
|
34
|
+
process.exit(1);
|
|
35
|
+
}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI: guardvibe hook install|uninstall
|
|
3
|
+
* Manages pre-commit security hooks.
|
|
4
|
+
*/
|
|
5
|
+
import { readFileSync, writeFileSync, mkdirSync, existsSync, chmodSync, unlinkSync } from "fs";
|
|
6
|
+
import { join } from "path";
|
|
7
|
+
const HOOK_SCRIPT = `#!/bin/sh
|
|
8
|
+
# GuardVibe pre-commit security hook
|
|
9
|
+
# Installed by: npx guardvibe hook install
|
|
10
|
+
|
|
11
|
+
echo "🔒 GuardVibe: scanning staged files..."
|
|
12
|
+
|
|
13
|
+
# Run guardvibe scan on staged files
|
|
14
|
+
RESULT=$(npx -y guardvibe-scan 2>&1)
|
|
15
|
+
EXIT_CODE=$?
|
|
16
|
+
|
|
17
|
+
if [ $EXIT_CODE -ne 0 ]; then
|
|
18
|
+
echo ""
|
|
19
|
+
echo "$RESULT"
|
|
20
|
+
echo ""
|
|
21
|
+
echo "❌ GuardVibe: security issues found. Fix them or commit with --no-verify to skip."
|
|
22
|
+
exit 1
|
|
23
|
+
fi
|
|
24
|
+
|
|
25
|
+
echo "✅ GuardVibe: all checks passed."
|
|
26
|
+
`;
|
|
27
|
+
function installHook() {
|
|
28
|
+
const gitDir = join(process.cwd(), ".git");
|
|
29
|
+
if (!existsSync(gitDir)) {
|
|
30
|
+
console.error(" [ERR] Not a git repository. Run this from your project root.");
|
|
31
|
+
process.exit(1);
|
|
32
|
+
}
|
|
33
|
+
const hooksDir = join(gitDir, "hooks");
|
|
34
|
+
if (!existsSync(hooksDir)) {
|
|
35
|
+
mkdirSync(hooksDir, { recursive: true });
|
|
36
|
+
}
|
|
37
|
+
const hookPath = join(hooksDir, "pre-commit");
|
|
38
|
+
if (existsSync(hookPath)) {
|
|
39
|
+
const existing = readFileSync(hookPath, "utf-8");
|
|
40
|
+
if (existing.includes("GuardVibe")) {
|
|
41
|
+
console.log(" [OK] GuardVibe pre-commit hook already installed.");
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
writeFileSync(hookPath, existing + "\n" + HOOK_SCRIPT, "utf-8");
|
|
45
|
+
console.log(" [OK] GuardVibe added to existing pre-commit hook.");
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
writeFileSync(hookPath, HOOK_SCRIPT, "utf-8");
|
|
49
|
+
chmodSync(hookPath, 0o755);
|
|
50
|
+
console.log(" [OK] Pre-commit hook installed at .git/hooks/pre-commit");
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
function uninstallHook() {
|
|
54
|
+
const hookPath = join(process.cwd(), ".git", "hooks", "pre-commit");
|
|
55
|
+
if (!existsSync(hookPath)) {
|
|
56
|
+
console.log(" [OK] No pre-commit hook found.");
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
const content = readFileSync(hookPath, "utf-8");
|
|
60
|
+
if (!content.includes("GuardVibe")) {
|
|
61
|
+
console.log(" [OK] Pre-commit hook exists but doesn't contain GuardVibe.");
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
const cleaned = content
|
|
65
|
+
.replace(/\n?# GuardVibe pre-commit security hook[\s\S]*?GuardVibe: all checks passed[."]*\n?/g, "")
|
|
66
|
+
.trim();
|
|
67
|
+
if (!cleaned || cleaned === "#!/bin/sh") {
|
|
68
|
+
unlinkSync(hookPath);
|
|
69
|
+
console.log(" [OK] Pre-commit hook removed.");
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
writeFileSync(hookPath, cleaned + "\n", "utf-8");
|
|
73
|
+
console.log(" [OK] GuardVibe removed from pre-commit hook (other hooks preserved).");
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
export function runHook(args) {
|
|
77
|
+
const action = args[0]?.toLowerCase();
|
|
78
|
+
console.log(`\n GuardVibe Pre-Commit Hook\n`);
|
|
79
|
+
if (action === "install") {
|
|
80
|
+
installHook();
|
|
81
|
+
}
|
|
82
|
+
else if (action === "uninstall") {
|
|
83
|
+
uninstallHook();
|
|
84
|
+
}
|
|
85
|
+
else {
|
|
86
|
+
console.error(" [ERR] Unknown action. Usage: npx guardvibe hook install|uninstall");
|
|
87
|
+
process.exit(1);
|
|
88
|
+
}
|
|
89
|
+
console.log();
|
|
90
|
+
}
|