guardvibe 3.0.28 → 3.0.30
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/build/cli/hook.js +1 -1
- package/build/cli/init.js +2 -2
- package/build/data/rules/core.js +1 -1
- package/build/tools/check-code.js +21 -0
- package/package.json +1 -1
package/build/cli/hook.js
CHANGED
|
@@ -11,7 +11,7 @@ const HOOK_SCRIPT = `#!/bin/sh
|
|
|
11
11
|
echo "🔒 GuardVibe: scanning staged files..."
|
|
12
12
|
|
|
13
13
|
# Run guardvibe scan on staged files
|
|
14
|
-
RESULT=$(npx -y guardvibe scan --staged 2>&1)
|
|
14
|
+
RESULT=$(npx -y guardvibe@latest scan --staged 2>&1)
|
|
15
15
|
EXIT_CODE=$?
|
|
16
16
|
|
|
17
17
|
if [ $EXIT_CODE -ne 0 ]; then
|
package/build/cli/init.js
CHANGED
|
@@ -7,7 +7,7 @@ import { join, dirname } from "path";
|
|
|
7
7
|
import { homedir } from "os";
|
|
8
8
|
const GUARDVIBE_MCP_CONFIG = {
|
|
9
9
|
command: "npx",
|
|
10
|
-
args: ["-y", "guardvibe"],
|
|
10
|
+
args: ["-y", "guardvibe@latest"],
|
|
11
11
|
};
|
|
12
12
|
const platforms = {
|
|
13
13
|
claude: {
|
|
@@ -98,7 +98,7 @@ function setupClaudeGuide() {
|
|
|
98
98
|
matcher: "Edit|Write",
|
|
99
99
|
hooks: [{
|
|
100
100
|
type: "command",
|
|
101
|
-
command: "jq -r '.tool_input.file_path' | xargs npx -y guardvibe check --format buddy 2>/dev/null || true"
|
|
101
|
+
command: "jq -r '.tool_input.file_path' | xargs npx -y guardvibe@latest check --format buddy 2>/dev/null || true"
|
|
102
102
|
}]
|
|
103
103
|
}
|
|
104
104
|
];
|
package/build/data/rules/core.js
CHANGED
|
@@ -31,7 +31,7 @@ export const coreRules = [
|
|
|
31
31
|
severity: "high",
|
|
32
32
|
owasp: "A01:2025 Broken Access Control",
|
|
33
33
|
description: "API route handler without authentication middleware or auth check.",
|
|
34
|
-
pattern: /(?:app|router)\.(get|post|put|delete|patch)\s*\(\s*['"](?!(?:\/(?:api\/)?)?(?:health|status|ping|ready|live|metrics|public|favicon|robots|sitemap)\b)[^'"]*['"]\s*,\s*(?:async\s+)?\(
|
|
34
|
+
pattern: /(?:app|router)\.(get|post|put|delete|patch)\s*\(\s*['"](?!(?:\/(?:api\/)?)?(?:health|status|ping|ready|live|metrics|public|favicon|robots|sitemap)\b)[^'"]*['"]\s*,\s*(?:async\s+)?\(?\b(?:req|request)\b/gi,
|
|
35
35
|
languages: ["javascript", "typescript"],
|
|
36
36
|
fix: "Add authentication middleware before route handlers: app.get('/api/data', authMiddleware, handler). Use frameworks like Passport.js, Clerk, or Auth0.",
|
|
37
37
|
fixCode: "// Add auth middleware before handler\napp.get('/api/data', authMiddleware, async (req, res) => {\n // handler code\n});",
|
|
@@ -162,6 +162,16 @@ function hasAuthGuardPattern(code) {
|
|
|
162
162
|
if (/await\s+(?:\w+\.)*\w*(?:auth|Auth|session|Session|permission|Permission|guard|Guard|verify|Verify|protect|Protect|check|Check|ensure|Ensure|require|Require|assert|Assert|authorize|Authorize)\w*\s*\(/i.test(code)) {
|
|
163
163
|
return true;
|
|
164
164
|
}
|
|
165
|
+
// Pattern 4: Express-style middleware function with auth-related name (sync, takes req/res/next).
|
|
166
|
+
// e.g. `function requireAuth(req, res, next)` or `const authMiddleware = (req, res, next) => {`
|
|
167
|
+
if (/(?:function\s+(?:require|auth|protect|verify|guard|ensure|check|assert|authorize)\w*\s*\(\s*req\b|(?:const|let)\s+(?:require|auth|protect|verify|guard|ensure|check|assert|authorize)\w*\s*=\s*(?:async\s+)?\(\s*req\b)/i.test(code)) {
|
|
168
|
+
return true;
|
|
169
|
+
}
|
|
170
|
+
// Pattern 5: middleware passed inline to express route registration.
|
|
171
|
+
// e.g. `app.get('/x', requireAuth, handler)` or `router.post('/y', authMiddleware, ...)`.
|
|
172
|
+
if (/(?:app|router)\.(?:get|post|put|delete|patch|all|use)\s*\([^,)]+,\s*(?:require|auth|protect|verify|guard|ensure|check|assert|authorize|isAuthenticated|isLoggedIn|hasPermission)\w*\s*[,\)]/i.test(code)) {
|
|
173
|
+
return true;
|
|
174
|
+
}
|
|
165
175
|
return false;
|
|
166
176
|
}
|
|
167
177
|
/**
|
|
@@ -580,6 +590,17 @@ export function analyzeCode(code, language, framework, filePath, configDir, rule
|
|
|
580
590
|
if (pkgMatch && isLegitimatePackage(pkgMatch[1]))
|
|
581
591
|
continue;
|
|
582
592
|
}
|
|
593
|
+
// Skip VG863 for non-publishable apps. Signals that this is an application, not a library:
|
|
594
|
+
// no publishing fields (bin/exports/module/types), main does not point at a build dir,
|
|
595
|
+
// and start script runs a runtime/framework directly.
|
|
596
|
+
if (rule.id === "VG863") {
|
|
597
|
+
const hasPublishingFields = /"(?:bin|exports|module|types|typings)"\s*:/i.test(code);
|
|
598
|
+
const mainPointsToBuild = /"main"\s*:\s*"(?:dist|build|lib|out)\//i.test(code);
|
|
599
|
+
const runtimeNames = "node|nodemon|tsx|ts-node|next|nest|vite|remix|astro";
|
|
600
|
+
const startsAsApp = new RegExp('"start"\\s*:\\s*"(?:' + runtimeNames + ')\\b', "i").test(code);
|
|
601
|
+
if (!hasPublishingFields && !mainPointsToBuild && startsAsApp)
|
|
602
|
+
continue;
|
|
603
|
+
}
|
|
583
604
|
// Skip VG106 for non-secret variable names (TokenCount, tokenBalance, hashMap, etc.)
|
|
584
605
|
if (rule.id === "VG106") {
|
|
585
606
|
const varName = match[0].split(/\s*(?:===|!==|==|!=)/)[0].trim();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "guardvibe",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.30",
|
|
4
4
|
"mcpName": "io.github.goklab/guardvibe",
|
|
5
5
|
"description": "Security MCP for vibe coding. 365 rules, 36 tools, CLI + doctor. Host security, auth coverage mapping, LLM-powered deep scan (IDOR/business logic), taint analysis. Plus Next.js, Supabase, Clerk, Stripe, Prisma, tRPC, Hono, GraphQL, Convex, Turso, Uploadthing, AI SDK, and the full AI-generated stack.",
|
|
6
6
|
"type": "module",
|