guardvibe 1.8.0 → 1.8.2

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/README.md CHANGED
@@ -1,5 +1,10 @@
1
1
  # GuardVibe
2
2
 
3
+ [![npm version](https://img.shields.io/npm/v/guardvibe)](https://www.npmjs.com/package/guardvibe)
4
+ [![License: Apache-2.0](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)
5
+ [![Node.js CI](https://github.com/goklab/guardvibe/actions/workflows/ci.yml/badge.svg)](https://github.com/goklab/guardvibe/actions/workflows/ci.yml)
6
+ [![npm provenance](https://img.shields.io/badge/provenance-verified-brightgreen)](https://www.npmjs.com/package/guardvibe)
7
+
3
8
  **The security MCP built for vibe coding.** 277 security rules covering the entire AI-generated code journey — from first line to production deployment.
4
9
 
5
10
  Works with **Claude Code, Cursor, Gemini CLI, Codex, Windsurf**, and any MCP-compatible coding agent.
@@ -430,7 +435,7 @@ GuardVibe takes supply chain security seriously:
430
435
  - **Minimal CI permissions** — GitHub Actions workflows use `permissions: contents: read` only
431
436
  - **Zero runtime dependencies** — only MCP SDK and Zod (both widely audited)
432
437
 
433
- To report a vulnerability, please email security@goklab.com or open a GitHub issue.
438
+ To report a vulnerability, please email info@goklab.com or open a GitHub issue.
434
439
 
435
440
  ## License
436
441
 
package/build/cli.js CHANGED
@@ -362,10 +362,23 @@ async function main() {
362
362
  console.log(pkg.version);
363
363
  process.exit(0);
364
364
  }
365
- if (args.length === 0 || args[0] === "--help" || args[0] === "-h") {
365
+ if (args[0] === "--help" || args[0] === "-h") {
366
366
  printUsage();
367
367
  process.exit(0);
368
368
  }
369
+ // No args: if stdin is a pipe, start MCP server; if TTY, show help
370
+ if (args.length === 0) {
371
+ if (process.stdin.isTTY) {
372
+ printUsage();
373
+ process.exit(0);
374
+ }
375
+ else {
376
+ // Started by MCP client (Claude Code, Cursor, etc.) — launch MCP server
377
+ const { startMcpServer } = await import("./index.js");
378
+ await startMcpServer();
379
+ return;
380
+ }
381
+ }
369
382
  const command = args[0];
370
383
  if (command === "init") {
371
384
  const platform = args[1]?.toLowerCase();
@@ -38,7 +38,7 @@ export const modernStackRules = [
38
38
  severity: "high",
39
39
  owasp: "A04:2023 Unrestricted Resource Consumption",
40
40
  description: "File upload handler does not validate file type (MIME type or extension). Attackers can upload executable files, scripts, or malicious content.",
41
- pattern: /(?:formData\.get|req\.file|upload|multer|busboy|formidable|Files?\s*\[)[\s\S]{0,500}?(?:writeFile|putObject|upload|save|createBucket|put\s*\()(?:(?!mime|type|extension|contentType|allowedTypes|accept|fileFilter|allowedMimeTypes)[\s\S]){0,200}/gi,
41
+ pattern: /(?:formData\.get\s*\(|req\.file\b|multer\s*\(|busboy|formidable\s*\(|Files?\s*\[)[\s\S]{0,500}?(?:writeFile|putObject|\.upload\s*\(|\.save\s*\(|createBucket|\.put\s*\()(?:(?!mime|type|extension|contentType|allowedTypes|accept|fileFilter|allowedMimeTypes)[\s\S]){0,200}/gi,
42
42
  languages: ["javascript", "typescript"],
43
43
  fix: "Always validate file types against an allowlist before storing. Check both MIME type and extension.",
44
44
  fixCode: '// Validate file type before upload\nconst ALLOWED_TYPES = ["image/jpeg", "image/png", "image/webp"];\nconst file = formData.get("file") as File;\nif (!ALLOWED_TYPES.includes(file.type)) {\n return new Response("Invalid file type", { status: 400 });\n}\nif (file.size > 5 * 1024 * 1024) {\n return new Response("File too large", { status: 400 });\n}',
@@ -50,7 +50,7 @@ export const modernStackRules = [
50
50
  severity: "medium",
51
51
  owasp: "A04:2023 Unrestricted Resource Consumption",
52
52
  description: "File upload handler does not enforce a file size limit. Attackers can upload extremely large files to exhaust storage or memory.",
53
- pattern: /(?:formData\.get|req\.file|upload)[\s\S]{0,300}?(?:writeFile|putObject|upload|save|put\s*\()(?:(?!size|limit|max|MB|GB|bytes|fileSizeLimit)[\s\S]){0,200}/gi,
53
+ pattern: /(?:formData\.get\s*\(|req\.file\b|multer\s*\()[\s\S]{0,300}?(?:writeFile|putObject|\.upload\s*\(|\.save\s*\(|\.put\s*\()(?:(?!size|limit|max|MB|GB|bytes|fileSizeLimit)[\s\S]){0,200}/gi,
54
54
  languages: ["javascript", "typescript"],
55
55
  fix: "Enforce a file size limit before processing uploads. Typical limits: 5MB for images, 50MB for documents.",
56
56
  fixCode: '// Check file size before upload\nconst MAX_SIZE = 5 * 1024 * 1024; // 5MB\nconst file = formData.get("file") as File;\nif (file.size > MAX_SIZE) {\n return new Response("File too large (max 5MB)", { status: 400 });\n}',
package/build/index.d.ts CHANGED
@@ -1,2 +1,2 @@
1
1
  #!/usr/bin/env node
2
- export {};
2
+ export declare function startMcpServer(): Promise<void>;
package/build/index.js CHANGED
@@ -288,6 +288,9 @@ server.tool("explain_remediation", "Deep explanation of a security finding: why
288
288
  const results = explainRemediation(rule_id, code, format, rules);
289
289
  return { content: [{ type: "text", text: results }] };
290
290
  });
291
+ export async function startMcpServer() {
292
+ return main();
293
+ }
291
294
  async function main() {
292
295
  // Load plugins
293
296
  const config = loadConfig(process.cwd());
@@ -319,7 +322,11 @@ async function main() {
319
322
  await server.connect(transport);
320
323
  console.error("GuardVibe Security MCP server running on stdio");
321
324
  }
322
- main().catch((error) => {
323
- console.error("Fatal error:", error);
324
- process.exit(1);
325
- });
325
+ // Only auto-start when run directly (not imported by cli.ts)
326
+ const isDirectRun = process.argv[1]?.replace(/\.js$/, "").endsWith("index");
327
+ if (isDirectRun) {
328
+ main().catch((error) => {
329
+ console.error("Fatal error:", error);
330
+ process.exit(1);
331
+ });
332
+ }
@@ -1,3 +1,4 @@
1
+ import { createRequire } from "module";
1
2
  import { readFileSync, statSync } from "fs";
2
3
  import { extname, basename, resolve } from "path";
3
4
  import { analyzeCode } from "./check-code.js";
@@ -5,6 +6,8 @@ import { owaspRules } from "../data/rules/index.js";
5
6
  import { loadConfig } from "../utils/config.js";
6
7
  import { EXTENSION_MAP, DEFAULT_EXCLUDES } from "../utils/constants.js";
7
8
  import { walkDirectory } from "../utils/walk-directory.js";
9
+ const _require = createRequire(import.meta.url);
10
+ const _pkg = _require("../../package.json");
8
11
  function severityToLevel(severity) {
9
12
  if (severity === "critical" || severity === "high")
10
13
  return "error";
@@ -72,7 +75,7 @@ export function exportSarif(path, rules) {
72
75
  tool: {
73
76
  driver: {
74
77
  name: "GuardVibe",
75
- version: "0.10.0",
78
+ version: _pkg.version,
76
79
  informationUri: "https://guardvibe.dev",
77
80
  rules: sarifRules,
78
81
  },
package/package.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "guardvibe",
3
- "version": "1.8.0",
3
+ "version": "1.8.2",
4
4
  "description": "Security MCP for vibe coding. 277 rules, 22 tools for Next.js, Supabase, Clerk, Stripe, Prisma, tRPC, Hono, GraphQL, Convex, Turso, Uploadthing, AI SDK, and the full AI-generated stack.",
5
5
  "type": "module",
6
6
  "bin": {
7
- "guardvibe": "build/index.js",
7
+ "guardvibe": "build/cli.js",
8
8
  "guardvibe-init": "build/cli.js",
9
9
  "guardvibe-scan": "build/cli.js"
10
10
  },
@@ -79,7 +79,7 @@
79
79
  ],
80
80
  "author": "GokLab",
81
81
  "license": "Apache-2.0",
82
- "homepage": "https://github.com/goklab/guardvibe",
82
+ "homepage": "https://guardvibe.dev",
83
83
  "repository": {
84
84
  "type": "git",
85
85
  "url": "https://github.com/goklab/guardvibe.git"