guardvibe 3.10.0 → 3.12.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 +18 -0
- package/build/cli/secure-this.js +10 -0
- package/build/index.js +1 -1
- package/build/tools/full-audit.d.ts +9 -0
- package/build/tools/full-audit.js +15 -0
- package/build/tools/secure-this.d.ts +6 -0
- package/build/tools/secure-this.js +0 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,24 @@ 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.12.0] - 2026-06-07
|
|
9
|
+
|
|
10
|
+
### Added — Season 3 S3-2: proof-carrying fixes (441 rules / 37 tools)
|
|
11
|
+
- **`secure_this` now returns a `proofTest`** when it applies fixes — a runnable regression test that proves the resolved findings stay fixed, using GuardVibe's deterministic scan as the oracle: it **fails on the vulnerable code and passes on the fixed code**. It's an honest scan-based proof (not an exploit test), and a real CI regression guard: drop it in the suite and the build breaks if the vuln is reintroduced.
|
|
12
|
+
- **CLI:** `guardvibe secure-this <file>` shows the proof test in markdown; `--emit-proof [path]` writes it (default `<file>.guardvibe.test.ts`). **MCP:** the `secure_this` result carries `proofTest` so agents can drop it into the project.
|
|
13
|
+
- Generated only when fixes were applied (nothing to prove for already-clean or non-auto-fixable code). New `node:test`-based template; 4 new tests. No rule or tool changes (441 / 37).
|
|
14
|
+
|
|
15
|
+
Gate green (build / lint / test / self-audit PASS / A / 0).
|
|
16
|
+
|
|
17
|
+
## [3.11.0] - 2026-06-07
|
|
18
|
+
|
|
19
|
+
### Changed — S3-1 (cont.): reachability-weighted dependency prioritization (441 rules / 37 tools)
|
|
20
|
+
- The audit's dependency section now **prioritizes** findings: severity first, then **imported (reachable) packages ahead of unused ones** within the same tier — so the agent fixes what its code actually calls into first. Severity is never altered (an unreachable dep can still be exploitable), so no false negatives are introduced.
|
|
21
|
+
- Each dependency `SectionFinding` now carries a structured `reachable` field (agent-consumable), in addition to the existing in-description annotation and the section's "N of M directly imported" count.
|
|
22
|
+
- New exported pure helper `sortDepFindings` (severity-rank + reachable-first), unit-tested. No rule or tool changes (441 / 37). Completes S3-1.
|
|
23
|
+
|
|
24
|
+
Gate green (build / lint / test / self-audit PASS / A / 0).
|
|
25
|
+
|
|
8
26
|
## [3.10.0] - 2026-06-07
|
|
9
27
|
|
|
10
28
|
### Added — Season 3 S3-1: autonomous, prioritized threat intel (441 rules / 37 tools)
|
package/build/cli/secure-this.js
CHANGED
|
@@ -56,6 +56,9 @@ function renderMarkdown(r, file, wrote) {
|
|
|
56
56
|
lines.push(`> Wrote ${r.applied.length} verified fix(es) to ${file}.`, "");
|
|
57
57
|
}
|
|
58
58
|
lines.push(`**Definition of done:** ${r.definitionOfDone.passed ? "PASSED ✅" : "FAILED ❌"} — ${r.definitionOfDone.message}`);
|
|
59
|
+
if (r.proofTest) {
|
|
60
|
+
lines.push("", "## Regression proof test", "Run on the fixed file to prove it stays fixed (`--emit-proof <path>` to save it):", "", "```ts", r.proofTest.trimEnd(), "```");
|
|
61
|
+
}
|
|
59
62
|
return lines.join("\n");
|
|
60
63
|
}
|
|
61
64
|
export async function runSecureThis(args) {
|
|
@@ -81,6 +84,13 @@ export async function runSecureThis(args) {
|
|
|
81
84
|
if (write && result.changed) {
|
|
82
85
|
writeFileSync(resolved, result.fixedCode, "utf-8");
|
|
83
86
|
}
|
|
87
|
+
// --emit-proof [path]: write the regression proof test (default: <file>.guardvibe.test.ts).
|
|
88
|
+
const emitProof = flags["emit-proof"];
|
|
89
|
+
if (emitProof && result.proofTest) {
|
|
90
|
+
const proofPath = typeof emitProof === "string" ? resolve(emitProof) : `${resolved}.guardvibe.test.ts`;
|
|
91
|
+
writeFileSync(proofPath, result.proofTest, "utf-8");
|
|
92
|
+
console.log(` [OK] Proof test written to ${proofPath}`);
|
|
93
|
+
}
|
|
84
94
|
const format = flags.format === "json" ? "json" : "markdown";
|
|
85
95
|
if (format === "json") {
|
|
86
96
|
console.log(JSON.stringify({ ...result, file: resolved, wrote: write && result.changed }));
|
package/build/index.js
CHANGED
|
@@ -319,7 +319,7 @@ server.tool("fix_code", "Pass vulnerable code as a string and get fix suggestion
|
|
|
319
319
|
};
|
|
320
320
|
});
|
|
321
321
|
// Tool 37: secure_this — close the loop (scan → apply verified fix → re-verify)
|
|
322
|
-
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'})", {
|
|
322
|
+
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}, proofTest }. Write fixedCode to disk, then require definitionOfDone.passed before claiming the task complete; anything in remaining[] needs a manual fix. When fixes were applied, proofTest is a runnable regression test (GuardVibe-as-oracle) you can drop into the project to guard against regressions. Example: secure_this({code: '...', language: 'typescript'})", {
|
|
323
323
|
code: z.string().describe("The code to scan and secure"),
|
|
324
324
|
language: z
|
|
325
325
|
.enum(["javascript", "typescript", "python", "go", "dockerfile", "html", "sql", "shell", "yaml", "terraform", "firestore"])
|
|
@@ -29,7 +29,16 @@ export interface SectionFinding {
|
|
|
29
29
|
name?: string;
|
|
30
30
|
description?: string;
|
|
31
31
|
fix?: string;
|
|
32
|
+
/** Dependency findings: is the vulnerable package actually imported in source? */
|
|
33
|
+
reachable?: boolean;
|
|
32
34
|
}
|
|
35
|
+
/**
|
|
36
|
+
* Order dependency findings by severity first, then surface reachable (imported)
|
|
37
|
+
* packages ahead of unreachable ones within the same tier — so the agent fixes
|
|
38
|
+
* what its code actually calls into first. Severity is never altered (an
|
|
39
|
+
* unreachable dep can still be exploitable), so this introduces no false negatives.
|
|
40
|
+
*/
|
|
41
|
+
export declare function sortDepFindings(findings: SectionFinding[]): SectionFinding[];
|
|
33
42
|
export interface AuditSection {
|
|
34
43
|
name: string;
|
|
35
44
|
status: "ok" | "error" | "skipped";
|
|
@@ -21,6 +21,17 @@ import { loadConfig } from "../utils/config.js";
|
|
|
21
21
|
import { isExcludedFilename } from "../utils/constants.js";
|
|
22
22
|
const _require = createRequire(import.meta.url);
|
|
23
23
|
const _pkg = _require("../../package.json");
|
|
24
|
+
const DEP_SEV_RANK = { critical: 0, high: 1, medium: 2, low: 3, info: 4 };
|
|
25
|
+
/**
|
|
26
|
+
* Order dependency findings by severity first, then surface reachable (imported)
|
|
27
|
+
* packages ahead of unreachable ones within the same tier — so the agent fixes
|
|
28
|
+
* what its code actually calls into first. Severity is never altered (an
|
|
29
|
+
* unreachable dep can still be exploitable), so this introduces no false negatives.
|
|
30
|
+
*/
|
|
31
|
+
export function sortDepFindings(findings) {
|
|
32
|
+
return [...findings].sort((a, b) => (DEP_SEV_RANK[a.severity] ?? 9) - (DEP_SEV_RANK[b.severity] ?? 9) ||
|
|
33
|
+
(Number(b.reachable === true) - Number(a.reachable === true)));
|
|
34
|
+
}
|
|
24
35
|
// --- Core Logic ---
|
|
25
36
|
/**
|
|
26
37
|
* Compute verdict: PASS (0 critical + 0 high), WARN (high > 0), FAIL (critical > 0)
|
|
@@ -285,10 +296,14 @@ export async function runFullAudit(path, options) {
|
|
|
285
296
|
name: `${pkgRec.name ?? "unknown"}: ${(vuln2.id ?? "CVE")}`,
|
|
286
297
|
description: `${(vuln2.summary ?? vuln2.details ?? "")}${reachNote}`,
|
|
287
298
|
fix: `Run: npm update ${pkgRec.name ?? ""}`,
|
|
299
|
+
reachable,
|
|
288
300
|
});
|
|
289
301
|
allFindings.push({ ruleId: `DEP:${vuln2.id ?? "CVE"}`, severity: sev, file: "package.json", line: 0 });
|
|
290
302
|
}
|
|
291
303
|
}
|
|
304
|
+
// Prioritize: severity first, then imported-and-vulnerable ahead of unused.
|
|
305
|
+
depFindings.sort((a, b) => (DEP_SEV_RANK[a.severity] ?? 9) - (DEP_SEV_RANK[b.severity] ?? 9) ||
|
|
306
|
+
(Number(b.reachable === true) - Number(a.reachable === true)));
|
|
292
307
|
const counts = { findings: depFindings.length, critical: depCritical, high: depHigh, medium: depMedium };
|
|
293
308
|
const reachText = typeof reachableVulnerable === "number" && vulnPackages > 0
|
|
294
309
|
? ` (${reachableVulnerable} of ${vulnPackages} directly imported in source)`
|
|
@@ -31,6 +31,12 @@ export interface SecureThisResult {
|
|
|
31
31
|
passed: boolean;
|
|
32
32
|
message: string;
|
|
33
33
|
};
|
|
34
|
+
/**
|
|
35
|
+
* A runnable regression test that proves the resolved findings stay fixed.
|
|
36
|
+
* Deterministic scan-based proof (GuardVibe is the oracle): run on the vulnerable
|
|
37
|
+
* code it fails, on the fixed code it passes. Present only when fixes were applied.
|
|
38
|
+
*/
|
|
39
|
+
proofTest?: string;
|
|
34
40
|
}
|
|
35
41
|
export interface SecureThisOptions {
|
|
36
42
|
framework?: string;
|
|
Binary file
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "guardvibe",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.12.0",
|
|
4
4
|
"mcpName": "io.github.goklab/guardvibe",
|
|
5
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. 441 rules, 37 tools, CLI + doctor. Host security, auth coverage mapping, LLM-powered deep scan (IDOR/business logic), taint analysis. 70 CVE rules refreshed daily from GHSA/OSV/CISA KEV — React Router 7 cluster, DOMPurify XSS, Better Auth bypass, 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",
|