guardvibe 3.9.0 → 3.10.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 CHANGED
@@ -5,6 +5,16 @@ 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.10.0] - 2026-06-07
9
+
10
+ ### Added — Season 3 S3-1: autonomous, prioritized threat intel (441 rules / 37 tools)
11
+ - **`npm run intel --scaffold`** now drafts a review-ready `cve-versions.ts` rule object **and** a version-range test stub for each uncovered advisory — turning "here's a gap" into "here's a rule + test to review." Drafts are printed only; nothing is auto-committed (the standing rule: never auto-commit untested rules).
12
+ - **CISA KEV prioritization:** the intel gap report cross-references the CISA Known-Exploited-Vulnerabilities catalog and surfaces actively-exploited CVEs first (🔥 marker), so what's being exploited in the wild — past your model's training cutoff — rises to the top. Degrades gracefully if the catalog is unreachable.
13
+ - New tested module `src/lib/cve-scaffold.ts`: `versionRangeRegex(introduced, fixed)` generalizes the hand-rolled 0-FP semver→regex work (single version / patch-range / minor-range / from-zero), and `scaffoldCveRule` emits the rule + test. Exact/`=` pins by default (a caret/tilde that resolves to the fix is left for the reviewer). The intel report (and `--json`) now also carries each gap's package + affected/fixed range + `kev` flag.
14
+ - No rule or tool changes (441 / 37) — this drafts rules; humans + the gate still decide.
15
+
16
+ Gate green (build / lint / test / self-audit PASS / A / 0).
17
+
8
18
  ## [3.9.0] - 2026-06-07
9
19
 
10
20
  ### Changed — diff-aware is now the default across every gating surface (441 rules / 37 tools)
@@ -0,0 +1,38 @@
1
+ /**
2
+ * CVE rule scaffolding (Season 3, S3-1).
3
+ *
4
+ * Turns a "package X is vulnerable in [introduced, fixed)" advisory into a
5
+ * review-ready `cve-versions.ts` rule object + a version-range test stub, so the
6
+ * daily intel pipeline drafts rules instead of just reporting gaps. The output is
7
+ * a DRAFT for human review + the normal gate/corpus validation — never
8
+ * auto-committed (the hard-won "never auto-commit untested rules" rule stands).
9
+ *
10
+ * 0-FP-leaning by default: the generated pin matcher only accepts exact / `=`
11
+ * pins (a `^`/`~` range usually resolves to the fixed patch and is left for the
12
+ * reviewer to add where the range spans minors). Pure + deterministic.
13
+ */
14
+ /**
15
+ * Regex fragment matching a semver version string in [introduced, fixed).
16
+ * Handles the shapes CVE advisories use: single version, a patch range within a
17
+ * minor, a minor range within a major, and from-zero. Multi-major ranges get a
18
+ * best-effort pattern (flagged for review by the scaffold).
19
+ */
20
+ export declare function versionRangeRegex(introduced: string, fixed: string): string;
21
+ export interface AdvisoryInput {
22
+ ruleId: string;
23
+ pkg: string;
24
+ introduced: string;
25
+ fixed: string;
26
+ cve?: string;
27
+ ghsa?: string;
28
+ severity: string;
29
+ summary: string;
30
+ }
31
+ /**
32
+ * Build a review-ready cve-versions.ts rule object + a matching test stub for an
33
+ * advisory. Returns source strings to paste (after review) — NOT auto-applied.
34
+ */
35
+ export declare function scaffoldCveRule(a: AdvisoryInput): {
36
+ rule: string;
37
+ test: string;
38
+ };
@@ -0,0 +1,110 @@
1
+ // guardvibe-ignore — builds CVE-rule regex *strings* from semver ranges; the
2
+ // `["']`/`\s*` fragments here are detector-pattern templates, not vulnerable code.
3
+ /**
4
+ * CVE rule scaffolding (Season 3, S3-1).
5
+ *
6
+ * Turns a "package X is vulnerable in [introduced, fixed)" advisory into a
7
+ * review-ready `cve-versions.ts` rule object + a version-range test stub, so the
8
+ * daily intel pipeline drafts rules instead of just reporting gaps. The output is
9
+ * a DRAFT for human review + the normal gate/corpus validation — never
10
+ * auto-committed (the hard-won "never auto-commit untested rules" rule stands).
11
+ *
12
+ * 0-FP-leaning by default: the generated pin matcher only accepts exact / `=`
13
+ * pins (a `^`/`~` range usually resolves to the fixed patch and is left for the
14
+ * reviewer to add where the range spans minors). Pure + deterministic.
15
+ */
16
+ function parseVer(v) {
17
+ if (!v || v === "0")
18
+ return [0, 0, 0];
19
+ const m = v.match(/^(\d+)(?:\.(\d+))?(?:\.(\d+))?/);
20
+ if (!m)
21
+ return [0, 0, 0];
22
+ return [Number(m[1] || 0), Number(m[2] || 0), Number(m[3] || 0)];
23
+ }
24
+ /** Regex fragment matching integers in [min, max] (enumerated for the small ranges CVEs use). */
25
+ function numRange(min, max) {
26
+ if (max < min)
27
+ return "(?!)"; // never matches (empty range)
28
+ if (min === max)
29
+ return String(min);
30
+ if (max - min <= 40) {
31
+ const alts = [];
32
+ for (let n = min; n <= max; n++)
33
+ alts.push(String(n));
34
+ return "(?:" + alts.join("|") + ")";
35
+ }
36
+ return "\\d+"; // unexpected for a CVE range — fall back to any
37
+ }
38
+ /**
39
+ * Regex fragment matching a semver version string in [introduced, fixed).
40
+ * Handles the shapes CVE advisories use: single version, a patch range within a
41
+ * minor, a minor range within a major, and from-zero. Multi-major ranges get a
42
+ * best-effort pattern (flagged for review by the scaffold).
43
+ */
44
+ export function versionRangeRegex(introduced, fixed) {
45
+ const [iM, im, ip] = parseVer(introduced);
46
+ const [fM, fm, fp] = parseVer(fixed);
47
+ const alts = [];
48
+ if (iM === fM) {
49
+ if (im === fm) {
50
+ // Same minor: patches ip .. fp-1
51
+ alts.push(`${iM}\\.${im}\\.${numRange(ip, fp - 1)}`);
52
+ }
53
+ else {
54
+ if (ip === 0) {
55
+ // Introduced minor starts at .0 → folds into the full-minor sweep im..fm-1
56
+ alts.push(`${iM}\\.${numRange(im, fm - 1)}\\.\\d+`);
57
+ }
58
+ else {
59
+ // ip > 0: approximate the introduced minor as full (reviewer tightens)
60
+ alts.push(`${iM}\\.${im}\\.\\d+`);
61
+ if (fm - 1 >= im + 1)
62
+ alts.push(`${iM}\\.${numRange(im + 1, fm - 1)}\\.\\d+`);
63
+ }
64
+ if (fp > 0)
65
+ alts.push(`${iM}\\.${fm}\\.${numRange(0, fp - 1)}`);
66
+ }
67
+ }
68
+ else {
69
+ // Multi-major (rare): majors iM..fM-1 in full, then the start of the fixed major.
70
+ alts.push(`${numRange(iM, fM - 1)}\\.\\d+\\.\\d+`);
71
+ if (fm > 0)
72
+ alts.push(`${fM}\\.${numRange(0, fm - 1)}\\.\\d+`);
73
+ if (fp > 0)
74
+ alts.push(`${fM}\\.${fm}\\.${numRange(0, fp - 1)}`);
75
+ }
76
+ const parts = alts.filter(Boolean);
77
+ return parts.length === 1 ? parts[0] : "(?:" + parts.join("|") + ")";
78
+ }
79
+ /** Escape a package name for use inside a regex literal. */
80
+ function escapePkg(pkg) {
81
+ return pkg.replace(/[.*+?^${}()|[\]\\/]/g, "\\$&");
82
+ }
83
+ /**
84
+ * Build a review-ready cve-versions.ts rule object + a matching test stub for an
85
+ * advisory. Returns source strings to paste (after review) — NOT auto-applied.
86
+ */
87
+ export function scaffoldCveRule(a) {
88
+ const frag = versionRangeRegex(a.introduced, a.fixed);
89
+ const ids = [a.cve, a.ghsa].filter(Boolean).join(" / ");
90
+ const pattern = `/["']${escapePkg(a.pkg)}["']\\s*:\\s*["']=?${frag}["']/g`;
91
+ const safeSummary = a.summary.replace(/"/g, "'").replace(/\s+/g, " ").trim();
92
+ const rule = ` {
93
+ id: "${a.ruleId}",
94
+ name: "${a.pkg} vulnerability${ids ? ` (${ids})` : ""}",
95
+ severity: "${a.severity}",
96
+ owasp: "A06:2025 Vulnerable and Outdated Components",
97
+ description:
98
+ "${safeSummary} Affected: ${a.pkg} ${a.introduced}–<${a.fixed}; fixed in ${a.fixed}. REVIEW: confirm the affected range, and add ~/^ prefixes only where they don't resolve to the fix, before merging.",
99
+ pattern:
100
+ ${pattern},
101
+ languages: ["json"],
102
+ fix: "Upgrade ${a.pkg} to ${a.fixed}+: npm install ${a.pkg}@latest.",
103
+ compliance: ["SOC2:CC7.1"],
104
+ },`;
105
+ const test = ` describe("${a.ruleId} - ${a.pkg} (${ids})", () => {
106
+ it("detects affected ${a.pkg}", () => testRule("${a.ruleId}", '"${a.pkg}": "${a.introduced}"', true));
107
+ it("ignores fixed ${a.pkg}", () => testRule("${a.ruleId}", '"${a.pkg}": "${a.fixed}"', false));
108
+ });`;
109
+ return { rule, test };
110
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "guardvibe",
3
- "version": "3.9.0",
3
+ "version": "3.10.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",