guardvibe 3.1.42 → 3.2.0
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 +12 -0
- package/README.md +9 -3
- package/build/cli/secure-this.d.ts +1 -0
- package/build/cli/secure-this.js +96 -0
- package/build/cli.js +5 -0
- package/build/index.js +20 -0
- package/build/tools/secure-this.d.ts +47 -0
- package/build/tools/secure-this.js +0 -0
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,18 @@ 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
|
+
## [3.2.0] - 2026-06-07
|
|
9
|
+
|
|
10
|
+
### Added — `secure_this`: close the loop from "warns" to "guarantees the fix landed" (438 rules / 37 tools)
|
|
11
|
+
- **New tool `secure_this`** (MCP + CLI `guardvibe secure-this <file>`). It scans a file, applies only the auto-fixes that **verifiably land**, and re-verifies — converting GuardVibe from a tool that *reports* findings into one that *guarantees the fix landed*.
|
|
12
|
+
- **Verify-and-rollback loop:** every candidate edit from `fix_code` is applied to a copy and re-scanned; the edit is kept only if it (1) strictly reduces the finding set and (2) introduces no new finding. Any edit that fails either check is rolled back. The loop repeats until no further verified fix is available.
|
|
13
|
+
- **Definition-of-done gate:** the result carries `definitionOfDone.passed` — the agent must pass it before claiming a task complete. `status` is `clean` / `secured` / `partial` / `no_autofix`; `applied[]` lists verified fixes, `remaining[]` lists findings that need a manual fix (with guidance).
|
|
14
|
+
- **Deterministic:** same code in → same code out (fixes applied in a fixed line/rule order; verified by the deterministic `analyzeFileSecurity`).
|
|
15
|
+
- **CLI:** `secure-this <file>` is dry-run by default (shows what would land + remaining manual work); `--write` applies only the verified fixes to disk; `--format json` for agents. Exit code gates a pre-commit hook / CI step (1 while real findings remain).
|
|
16
|
+
- Tool count 36 → 37. No rule changes (438).
|
|
17
|
+
|
|
18
|
+
Gate green (build / lint / test / self-audit PASS / A / 0).
|
|
19
|
+
|
|
8
20
|
## [3.1.42] - 2026-06-07
|
|
9
21
|
|
|
10
22
|
### Fixed — MCP registry description length (no rule-count change, 438 / 36)
|
package/README.md
CHANGED
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
- **🗺️ Sees the whole repo.** Cross-file taint + auth-coverage across every route — catches the unprotected endpoint your agent's narrow context missed.
|
|
15
15
|
- **🔍 An independent second pair of eyes.** The thing that wrote the code can't review itself. GuardVibe is the outside checker on AI-written code — in the loop *while* your AI codes (real-time edit hook), not after.
|
|
16
16
|
|
|
17
|
-
**The security MCP built for vibe coding.** 438 security rules,
|
|
17
|
+
**The security MCP built for vibe coding.** 438 security rules, 37 tools covering the entire AI-generated code journey — from first line to production deployment.
|
|
18
18
|
|
|
19
19
|
Works with **Claude Code, Cursor, Gemini CLI, Codex, VS Code (Copilot), Windsurf**, and any MCP-compatible coding agent.
|
|
20
20
|
|
|
@@ -26,7 +26,7 @@ Works with **Claude Code, Cursor, Gemini CLI, Codex, VS Code (Copilot), Windsurf
|
|
|
26
26
|
|
|
27
27
|
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.
|
|
28
28
|
|
|
29
|
-
- **438 security rules,
|
|
29
|
+
- **438 security rules, 37 tools** purpose-built for the stacks AI agents generate
|
|
30
30
|
- **Zero setup friction** — `npx guardvibe` and you're scanning
|
|
31
31
|
- **No account required** — runs 100% locally, no API keys, no cloud
|
|
32
32
|
- **Understands your stack** — not generic SAST, but rules that know Next.js, Supabase, Stripe, Clerk, and the tools you actually use
|
|
@@ -211,7 +211,7 @@ Maps security findings to SOC2, PCI-DSS, HIPAA, GDPR, ISO27001, and EU AI Act (E
|
|
|
211
211
|
### Supply Chain
|
|
212
212
|
Malicious postinstall scripts, unpinned GitHub Actions, CI `npm` provenance / `--ignore-scripts` hardening (VG1070), typosquat detection, `node-ipc` protestware versions (VG1069), Miasma `@redhat-cloud-services` namespace compromise IOC (VG1074, RHSB-2026-006), Session messenger exfil endpoint IOC (VG1075, `filev2.getsession.org`), `@tanstack/*` Mini Shai-Hulud mass-malware versions (May 2026), `@wdio/browserstack-service` command injection via git branch names (CVE-2026-25244), lockfile poisoning patterns
|
|
213
213
|
|
|
214
|
-
## Tools (
|
|
214
|
+
## Tools (37 MCP tools)
|
|
215
215
|
|
|
216
216
|
| Tool | What it does |
|
|
217
217
|
|------|-------------|
|
|
@@ -227,6 +227,7 @@ Malicious postinstall scripts, unpinned GitHub Actions, CI `npm` provenance / `-
|
|
|
227
227
|
| `export_sarif` | SARIF v2.1.0 export for CI/CD integration |
|
|
228
228
|
| `get_security_docs` | Security best practices and guides |
|
|
229
229
|
| `fix_code` | **Auto-fix suggestions** with concrete patches for AI agents |
|
|
230
|
+
| `secure_this` | **Close the loop** — scan, apply only the fixes that verifiably land (each re-scanned, rolled back on regression), return the verified code + a definition-of-done gate |
|
|
230
231
|
| `audit_config` | Audit project configuration files for cross-file security misconfigurations |
|
|
231
232
|
| `generate_policy` | Detect project stack and generate tailored security policies (CSP, CORS, RLS) |
|
|
232
233
|
| `review_pr` | Review PR diff for security issues with severity gating |
|
|
@@ -293,6 +294,11 @@ npx guardvibe scan . --format json # JSON output for automation
|
|
|
293
294
|
npx guardvibe check <file> # Scan a single file
|
|
294
295
|
npx guardvibe diff [base] # Scan only changed files since git ref
|
|
295
296
|
|
|
297
|
+
# Close the loop — scan, apply verified fixes, re-verify
|
|
298
|
+
npx guardvibe secure-this <file> # Dry run: show the fixes that would land + remaining manual work
|
|
299
|
+
npx guardvibe secure-this <file> --write # Apply only the fixes that re-verify clean (rolled back on regression)
|
|
300
|
+
npx guardvibe secure-this <file> --format json
|
|
301
|
+
|
|
296
302
|
# Full security audit
|
|
297
303
|
npx guardvibe audit [path] # Full audit with PASS/FAIL verdict + hash
|
|
298
304
|
npx guardvibe audit . --format json # JSON output for CI pipelines
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function runSecureThis(args: string[]): Promise<void>;
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI: guardvibe secure-this <file> [--write] [--format json]
|
|
3
|
+
*
|
|
4
|
+
* Closes the loop: scans the file, applies only the fixes that verifiably land
|
|
5
|
+
* (each re-scanned, rolled back on regression), and reports a definition-of-done
|
|
6
|
+
* gate. Dry-run by default; `--write` applies the verified fixes to disk.
|
|
7
|
+
*
|
|
8
|
+
* Exit code: 0 when the file is (or was made) clean; 1 while real findings remain
|
|
9
|
+
* — so it can gate a pre-commit hook or CI step.
|
|
10
|
+
*/
|
|
11
|
+
import { readFileSync, writeFileSync, existsSync } from "fs";
|
|
12
|
+
import { resolve, extname, basename } from "path";
|
|
13
|
+
import { parseArgs } from "./args.js";
|
|
14
|
+
import { secureThis } from "../tools/secure-this.js";
|
|
15
|
+
import { EXTENSION_MAP, CONFIG_FILE_MAP } from "../utils/constants.js";
|
|
16
|
+
function detectLanguage(resolvedPath) {
|
|
17
|
+
const ext = extname(resolvedPath).toLowerCase();
|
|
18
|
+
let language = EXTENSION_MAP[ext];
|
|
19
|
+
if (!language && basename(resolvedPath).startsWith("Dockerfile"))
|
|
20
|
+
language = "dockerfile";
|
|
21
|
+
if (!language)
|
|
22
|
+
language = CONFIG_FILE_MAP[basename(resolvedPath)];
|
|
23
|
+
return language;
|
|
24
|
+
}
|
|
25
|
+
function renderMarkdown(r, file, wrote) {
|
|
26
|
+
const badge = {
|
|
27
|
+
clean: "CLEAN ✅", secured: "SECURED ✅", partial: "PARTIAL ⚠️", no_autofix: "NO AUTO-FIX ❌",
|
|
28
|
+
};
|
|
29
|
+
const lines = [
|
|
30
|
+
`# GuardVibe secure_this — ${file}`,
|
|
31
|
+
"",
|
|
32
|
+
`**Status:** ${badge[r.status] ?? r.status}`,
|
|
33
|
+
`**Findings:** ${r.initialFindings} → ${r.finalFindings}`,
|
|
34
|
+
"",
|
|
35
|
+
];
|
|
36
|
+
if (r.applied.length) {
|
|
37
|
+
lines.push(`## Applied & verified (${r.applied.length})`, "");
|
|
38
|
+
for (const a of r.applied) {
|
|
39
|
+
lines.push(`- **${a.ruleId}** (${a.severity}) line ${a.line}: ${a.ruleName}`);
|
|
40
|
+
}
|
|
41
|
+
lines.push("");
|
|
42
|
+
}
|
|
43
|
+
if (r.remaining.length) {
|
|
44
|
+
lines.push(`## Remaining — manual fix required (${r.remaining.length})`, "");
|
|
45
|
+
for (const f of r.remaining) {
|
|
46
|
+
lines.push(`- **${f.ruleId}** (${f.severity}) line ${f.line}: ${f.name}`);
|
|
47
|
+
if (f.fix)
|
|
48
|
+
lines.push(` - Fix: ${f.fix}`);
|
|
49
|
+
}
|
|
50
|
+
lines.push("");
|
|
51
|
+
}
|
|
52
|
+
if (r.changed && !wrote) {
|
|
53
|
+
lines.push("> Dry run — re-run with `--write` to apply the verified fixes above.", "");
|
|
54
|
+
}
|
|
55
|
+
else if (wrote && r.changed) {
|
|
56
|
+
lines.push(`> Wrote ${r.applied.length} verified fix(es) to ${file}.`, "");
|
|
57
|
+
}
|
|
58
|
+
lines.push(`**Definition of done:** ${r.definitionOfDone.passed ? "PASSED ✅" : "FAILED ❌"} — ${r.definitionOfDone.message}`);
|
|
59
|
+
return lines.join("\n");
|
|
60
|
+
}
|
|
61
|
+
export async function runSecureThis(args) {
|
|
62
|
+
const { flags, positional } = parseArgs(args);
|
|
63
|
+
const filePath = positional[0];
|
|
64
|
+
if (!filePath) {
|
|
65
|
+
console.error(" [ERR] Please specify a file: npx guardvibe secure-this src/app/api/route.ts [--write]");
|
|
66
|
+
process.exit(1);
|
|
67
|
+
}
|
|
68
|
+
const resolved = resolve(filePath);
|
|
69
|
+
if (!existsSync(resolved)) {
|
|
70
|
+
console.error(` [ERR] File not found: ${resolved}`);
|
|
71
|
+
process.exit(1);
|
|
72
|
+
}
|
|
73
|
+
const language = detectLanguage(resolved);
|
|
74
|
+
if (!language) {
|
|
75
|
+
console.error(` [ERR] Unsupported file type: ${extname(resolved) || basename(resolved)}`);
|
|
76
|
+
process.exit(1);
|
|
77
|
+
}
|
|
78
|
+
const content = readFileSync(resolved, "utf-8");
|
|
79
|
+
const result = secureThis(content, language, { filePath: resolved });
|
|
80
|
+
const write = flags.write === true || flags.apply === true;
|
|
81
|
+
if (write && result.changed) {
|
|
82
|
+
writeFileSync(resolved, result.fixedCode, "utf-8");
|
|
83
|
+
}
|
|
84
|
+
const format = flags.format === "json" ? "json" : "markdown";
|
|
85
|
+
if (format === "json") {
|
|
86
|
+
console.log(JSON.stringify({ ...result, file: resolved, wrote: write && result.changed }));
|
|
87
|
+
}
|
|
88
|
+
else {
|
|
89
|
+
console.log(renderMarkdown(result, resolved, write && result.changed));
|
|
90
|
+
}
|
|
91
|
+
// Exit code gates a pre-commit hook / CI step.
|
|
92
|
+
// --write: pass iff the file ended clean. Dry-run: pass only if nothing to fix.
|
|
93
|
+
const ok = write ? result.definitionOfDone.passed : result.status === "clean";
|
|
94
|
+
if (!ok)
|
|
95
|
+
process.exit(1);
|
|
96
|
+
}
|
package/build/cli.js
CHANGED
|
@@ -29,6 +29,7 @@ function printUsage() {
|
|
|
29
29
|
npx guardvibe audit [path] Full security audit with PASS/FAIL verdict
|
|
30
30
|
npx guardvibe explain <ruleId> Get detailed remediation guidance for a rule
|
|
31
31
|
npx guardvibe fix <file> Get security fix suggestions for a file
|
|
32
|
+
npx guardvibe secure-this <file> Scan, apply verified fixes, re-verify (--write to apply)
|
|
32
33
|
npx guardvibe check-cmd "<cmd>" Check if a shell command is safe to execute
|
|
33
34
|
npx guardvibe auth-coverage [path] Auth coverage analysis (Next.js routes)
|
|
34
35
|
npx guardvibe compliance [path] Compliance report (--framework SOC2|GDPR|...)
|
|
@@ -145,6 +146,10 @@ async function main() {
|
|
|
145
146
|
const { runFix } = await import("./cli/fix.js");
|
|
146
147
|
await runFix(subArgs);
|
|
147
148
|
}
|
|
149
|
+
else if (command === "secure-this" || command === "secure_this") {
|
|
150
|
+
const { runSecureThis } = await import("./cli/secure-this.js");
|
|
151
|
+
await runSecureThis(subArgs);
|
|
152
|
+
}
|
|
148
153
|
else if (command === "check-cmd") {
|
|
149
154
|
const { runCheckCmd } = await import("./cli/check-cmd.js");
|
|
150
155
|
await runCheckCmd(subArgs);
|
package/build/index.js
CHANGED
|
@@ -41,6 +41,7 @@ import { doctor } from "./tools/doctor.js";
|
|
|
41
41
|
import { formatHostFindings, redactSecrets } from "./server/types.js";
|
|
42
42
|
import { verifyFix } from "./tools/verify-fix.js";
|
|
43
43
|
import { fixCode as fixCodeTool } from "./tools/fix-code.js";
|
|
44
|
+
import { secureThis } from "./tools/secure-this.js";
|
|
44
45
|
import { analyzeAuthCoverage, formatAuthCoverage } from "./tools/auth-coverage.js";
|
|
45
46
|
import { buildDeepScanPrompt, parseDeepScanResult, formatDeepScanFindings, callLLM } from "./tools/deep-scan.js";
|
|
46
47
|
import { runFullAudit, formatAuditResult } from "./tools/full-audit.js";
|
|
@@ -315,6 +316,25 @@ server.tool("fix_code", "Pass vulnerable code as a string and get fix suggestion
|
|
|
315
316
|
content: [{ type: "text", text: results }],
|
|
316
317
|
};
|
|
317
318
|
});
|
|
319
|
+
// Tool 37: secure_this — close the loop (scan → apply verified fix → re-verify)
|
|
320
|
+
server.tool("secure_this", "Close the loop on vulnerabilities in code: scan, apply only the fixes that VERIFIABLY land (each candidate edit is re-scanned and rolled back if it fails to resolve the issue or introduces a new one), and return the verified code plus a definition-of-done gate. Prefer this over fix_code+verify_fix when you want a guarantee the fix landed — not just a suggestion. Returns { status: clean|secured|partial|no_autofix, fixedCode, applied[], remaining[], definitionOfDone:{passed,message} }. Write fixedCode to disk, then require definitionOfDone.passed before claiming the task complete; anything in remaining[] needs a manual fix. Example: secure_this({code: '...', language: 'typescript'})", {
|
|
321
|
+
code: z.string().describe("The code to scan and secure"),
|
|
322
|
+
language: z
|
|
323
|
+
.enum(["javascript", "typescript", "python", "go", "dockerfile", "html", "sql", "shell", "yaml", "terraform", "firestore"])
|
|
324
|
+
.describe("Programming language of the code"),
|
|
325
|
+
framework: z.string().optional().describe("Framework context (e.g. express, nextjs, react)"),
|
|
326
|
+
filePath: z.string().optional().describe("File path for context-aware analysis (the file is NOT written; apply fixedCode yourself)"),
|
|
327
|
+
}, async ({ code, language, framework, filePath }) => {
|
|
328
|
+
const rules = getRules();
|
|
329
|
+
const result = secureThis(code, language, { framework, filePath, rules });
|
|
330
|
+
if (result.applied.length > 0) {
|
|
331
|
+
try {
|
|
332
|
+
recordFix(process.cwd(), result.applied.length);
|
|
333
|
+
}
|
|
334
|
+
catch { /* stats best-effort */ }
|
|
335
|
+
}
|
|
336
|
+
return { content: [{ type: "text", text: JSON.stringify(result) }] };
|
|
337
|
+
});
|
|
318
338
|
// Tool 13: Cross-file configuration security audit
|
|
319
339
|
server.tool("audit_config", "Audit application config files (next.config, middleware, .env, vercel.json) for cross-file security gaps: missing headers, unprotected routes, exposed secrets. NOT the same as guardvibe_doctor which checks AI host security (MCP configs, hooks). Example: audit_config({path: '.'})", {
|
|
320
340
|
path: z.string().describe("Project root directory to audit"),
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type { SecurityRule } from "../data/rules/types.js";
|
|
2
|
+
export interface AppliedFix {
|
|
3
|
+
ruleId: string;
|
|
4
|
+
ruleName: string;
|
|
5
|
+
severity: string;
|
|
6
|
+
line: number;
|
|
7
|
+
before: string;
|
|
8
|
+
after: string;
|
|
9
|
+
}
|
|
10
|
+
export interface RemainingFinding {
|
|
11
|
+
ruleId: string;
|
|
12
|
+
name: string;
|
|
13
|
+
severity: string;
|
|
14
|
+
line: number;
|
|
15
|
+
reason: "no_autofix" | "fix_rejected";
|
|
16
|
+
fix: string;
|
|
17
|
+
fixCode?: string;
|
|
18
|
+
}
|
|
19
|
+
export type SecureThisStatus = "clean" | "secured" | "partial" | "no_autofix";
|
|
20
|
+
export interface SecureThisResult {
|
|
21
|
+
status: SecureThisStatus;
|
|
22
|
+
changed: boolean;
|
|
23
|
+
initialFindings: number;
|
|
24
|
+
finalFindings: number;
|
|
25
|
+
resolved: string[];
|
|
26
|
+
applied: AppliedFix[];
|
|
27
|
+
remaining: RemainingFinding[];
|
|
28
|
+
passes: number;
|
|
29
|
+
fixedCode: string;
|
|
30
|
+
definitionOfDone: {
|
|
31
|
+
passed: boolean;
|
|
32
|
+
message: string;
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
export interface SecureThisOptions {
|
|
36
|
+
framework?: string;
|
|
37
|
+
filePath?: string;
|
|
38
|
+
configDir?: string;
|
|
39
|
+
rules?: SecurityRule[];
|
|
40
|
+
/** Hard backstop on apply passes (each accepted edit removes >=1 finding). */
|
|
41
|
+
maxPasses?: number;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Scan a file, apply only the fixes that verifiably land, and report a
|
|
45
|
+
* definition-of-done gate.
|
|
46
|
+
*/
|
|
47
|
+
export declare function secureThis(code: string, language: string, opts?: SecureThisOptions): SecureThisResult;
|
|
Binary file
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "guardvibe",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.2.0",
|
|
4
4
|
"mcpName": "io.github.goklab/guardvibe",
|
|
5
|
-
"description": "Security infrastructure your AI can't be — deterministic, current past your model's training cutoff, whole-repo-aware, author-independent. Security MCP for vibe coding. 438 rules,
|
|
5
|
+
"description": "Security infrastructure your AI can't be — deterministic, current past your model's training cutoff, whole-repo-aware, author-independent. Security MCP for vibe coding. 438 rules, 37 tools, CLI + doctor. Host security, auth coverage mapping, LLM-powered deep scan (IDOR/business logic), taint analysis. 67 CVE rules refreshed daily from GHSA/OSV/CISA KEV — Miasma @redhat-cloud-services compromise, Next.js May 2026 13-advisory cluster, Drizzle/MikroORM/Kysely SQL injection, Axios proxy-auth redirect leak, Hono setCookie attribute injection, Clerk SSRF, tRPC prototype pollution, @tanstack supply-chain, node-ipc protestware, OpenClaude sandbox bypass, plus the full AI-generated stack (Supabase, Stripe, Prisma, Hono, GraphQL, Convex, Turso, Uploadthing, AI SDK). 68 AI-native rules including OWASP MCP Top 10 tool-description prompt injection (VG1068), model-controlled sandbox-disable flag detection (VG1063), Session messenger exfil endpoint IOC (VG1075), and CI/CD supply-chain hardening (VG1070 npm --expect-provenance / --ignore-scripts enforcement).",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"bin": {
|
|
8
8
|
"guardvibe": "build/cli.js",
|