guardvibe 3.0.50 → 3.0.52
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 +6 -0
- package/build/data/rules/core.js +2 -2
- package/build/tools/check-code.js +27 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -278,6 +278,7 @@ npx guardvibe diff [base] # Scan only changed files since git ref
|
|
|
278
278
|
npx guardvibe audit [path] # Full audit with PASS/FAIL verdict + hash
|
|
279
279
|
npx guardvibe audit . --format json # JSON output for CI pipelines
|
|
280
280
|
npx guardvibe audit --skip-deps # Skip dependency CVE check
|
|
281
|
+
npx guardvibe audit --full # Disable MCP-output truncation (full finding set)
|
|
281
282
|
|
|
282
283
|
# Host security audit
|
|
283
284
|
npx guardvibe doctor # Host hardening audit (project scope)
|
|
@@ -299,6 +300,7 @@ npx guardvibe-scan --format sarif --output results.sarif # CI mode
|
|
|
299
300
|
# --format markdown|json|sarif|buddy
|
|
300
301
|
# --output <file> Write results to file
|
|
301
302
|
# --fail-on <level> Exit 1 on findings: critical|high|medium|low|none
|
|
303
|
+
# --full Bypass response-size caps (50 JSON / 30 markdown / 200-file taint)
|
|
302
304
|
```
|
|
303
305
|
|
|
304
306
|
## Plugin System
|
|
@@ -514,6 +516,9 @@ Create a `.guardviberc` JSON file in your project root to customize GuardVibe be
|
|
|
514
516
|
}
|
|
515
517
|
],
|
|
516
518
|
"requiredControls": ["SOC2:CC6.1"]
|
|
519
|
+
},
|
|
520
|
+
"scoring": {
|
|
521
|
+
"densityModel": "exponential"
|
|
517
522
|
}
|
|
518
523
|
}
|
|
519
524
|
```
|
|
@@ -531,6 +536,7 @@ Create a `.guardviberc` JSON file in your project root to customize GuardVibe be
|
|
|
531
536
|
| `compliance.failOn` | `string` | `"high"` | Minimum severity that causes compliance failure |
|
|
532
537
|
| `compliance.exceptions` | `PolicyException[]` | `[]` | Approved exceptions with expiration dates |
|
|
533
538
|
| `compliance.requiredControls` | `string[]` | -- | Controls that must pass regardless of exceptions |
|
|
539
|
+
| `scoring.densityModel` | `"linear" \| "exponential"` | `"linear"` | Score decay curve. `linear` matches pre-v3.0.50 (cliff at density 5). `exponential` keeps resolution past density 5 — smoother decay for large repos. Severity caps (1+ critical → max C/60, 1+ high → max B/75) apply under both. |
|
|
534
540
|
|
|
535
541
|
## Security
|
|
536
542
|
|
package/build/data/rules/core.js
CHANGED
|
@@ -7,7 +7,7 @@ export const coreRules = [
|
|
|
7
7
|
severity: "critical",
|
|
8
8
|
owasp: "A01:2025 Broken Access Control",
|
|
9
9
|
description: "Hardcoded passwords, API keys, or secrets detected in source code.",
|
|
10
|
-
pattern: /(?:secret_?key|api_?key|api_?secret|private_?key|access_?key|password|passwd|pwd|auth_?token|jwt_?secret|app_?secret|master_?key|signing_?key|encryption_?key)\w*\s*[:=]\s*['"][^'"]{3,}['"]/gi,
|
|
10
|
+
pattern: /(?:secret_?key|api_?key|api_?secret|private_?key|access_?key|password|passwd|pwd|auth_?token|jwt_?secret|app_?secret|master_?key|signing_?key|encryption_?key)\w*\s*[:=]\s*['"][^'"\n]{3,}['"]/gi,
|
|
11
11
|
languages: ["javascript", "typescript", "python", "go"],
|
|
12
12
|
fix: "Use environment variables (process.env.SECRET) or a secrets manager. Never commit credentials to source code.",
|
|
13
13
|
fixCode: "// Use environment variables instead\nconst password = process.env.DB_PASSWORD;\nconst apiKey = process.env.API_KEY;",
|
|
@@ -212,7 +212,7 @@ export const coreRules = [
|
|
|
212
212
|
severity: "critical",
|
|
213
213
|
owasp: "A07:2025 Auth Failures",
|
|
214
214
|
description: "Variable named secret, password, or apiKey assigned a string literal. Secrets should come from environment variables or a secrets manager, never hardcoded in source.",
|
|
215
|
-
pattern: /(?:(?:const|let|var|export)\s+)?(?:secret|password|passwd|apiKey|api_key|privateKey|private_key|signingKey|signing_key|encryptionKey|encryption_key|masterKey|master_key|dbPassword|db_password)\s*(?::\s*string\s*)?=\s*["'][^"']{8,}["']/gi,
|
|
215
|
+
pattern: /(?:(?:const|let|var|export)\s+)?(?:secret|password|passwd|apiKey|api_key|privateKey|private_key|signingKey|signing_key|encryptionKey|encryption_key|masterKey|master_key|dbPassword|db_password)\s*(?::\s*string\s*)?=\s*["'][^"'\n]{8,}["']/gi,
|
|
216
216
|
languages: ["javascript", "typescript", "python"],
|
|
217
217
|
fix: "Use environment variables: const secret = process.env.MY_SECRET. Never hardcode secrets in source code.",
|
|
218
218
|
fixCode: "// Use environment variables\nconst secret = process.env.JWT_SECRET;\nconst apiKey = process.env.API_KEY;\n\n// In .env.local (never commit this file)\nJWT_SECRET=your-secret-here",
|
|
@@ -648,6 +648,11 @@ export function analyzeCode(code, language, framework, filePath, configDir, rule
|
|
|
648
648
|
if (rule.id === "VG001" || rule.id === "VG062") {
|
|
649
649
|
if (isHumanReadableString(lines, lineNumber))
|
|
650
650
|
continue;
|
|
651
|
+
// Translation/locale files and event-tracker key maps are not credential stores —
|
|
652
|
+
// values are UI strings (`password: "Heslo"`) or analytics event names
|
|
653
|
+
// (`forgot_password: "forgot_password_clicked"`).
|
|
654
|
+
if (filePath && /(?:\/i18n\/|\/locales?\/|\/translations?\/|\/event[-_]tracker\/|\/analytics\/events\/|\/messages\/[a-z]{2}(?:[-_][A-Z]{2})?\.[jt]sx?$)/i.test(filePath))
|
|
655
|
+
continue;
|
|
651
656
|
}
|
|
652
657
|
// Skip credential rules when the variable name signals test/example/mock intent.
|
|
653
658
|
// e.g. `testingPassword`, `examplePassword`, `mockApiKey`, `placeholderSecret`.
|
|
@@ -655,6 +660,15 @@ export function analyzeCode(code, language, framework, filePath, configDir, rule
|
|
|
655
660
|
const matchedLine = lines[lineNumber - 1] ?? "";
|
|
656
661
|
if (/(?:^|\s|\b)(?:testing|example|mock|placeholder|sample|demo|fake|dummy|stub|fixture)[A-Z_]/.test(matchedLine))
|
|
657
662
|
continue;
|
|
663
|
+
// Skip TypeScript string-enum stringification: `INLINE_PASSWORD = "INLINE_PASSWORD"`.
|
|
664
|
+
// No real credential has identical name and value — canonical TS enum-key pattern.
|
|
665
|
+
// Covers both SCREAMING_SNAKE (TS string enums) and snake_case (event-tracker key maps).
|
|
666
|
+
if (/\b([A-Za-z_][A-Za-z0-9_]*)\s*[:=]\s*["']\1["']/.test(matchedLine))
|
|
667
|
+
continue;
|
|
668
|
+
// Skip SCREAMING_SNAKE error/status codes whose value is digits-only.
|
|
669
|
+
// e.g. `INVALID_PASSWORD = "5020"` — error code, not a credential.
|
|
670
|
+
if (/\b[A-Z][A-Z0-9_]*\s*=\s*["']\d+["']/.test(matchedLine))
|
|
671
|
+
continue;
|
|
658
672
|
}
|
|
659
673
|
// Skip VG010 (SQL injection) on Angular HTTP service calls — http.get/post/etc.
|
|
660
674
|
// are HTTP client methods, not SQL. The existing pattern's `get` keyword catches them.
|
|
@@ -667,9 +681,21 @@ export function analyzeCode(code, language, framework, filePath, configDir, rule
|
|
|
667
681
|
continue;
|
|
668
682
|
// Also skip when matched call has no SQL keyword anywhere on the line — covers fetch/axios template-literal URLs.
|
|
669
683
|
const hasSqlKeyword = /\b(?:SELECT|INSERT|UPDATE|DELETE|FROM|WHERE|JOIN|UNION|DROP|TRUNCATE|ALTER|CREATE\s+TABLE)\b/i.test(matchedLine);
|
|
670
|
-
|
|
684
|
+
// Python `requests.get/post` and `requests.request(...)` are HTTP, not SQL.
|
|
685
|
+
const isFetchOrAxios = /(?:fetch|axios|got|ky|undici|requests?)\s*[.\(]|axios\.(?:get|post|put|delete|patch)/i.test(matchedLine);
|
|
671
686
|
if (isFetchOrAxios && !hasSqlKeyword)
|
|
672
687
|
continue;
|
|
688
|
+
// Skip when the first call argument is a URL path (starts with `/`) and no SQL keyword is on the line.
|
|
689
|
+
// Covers service-class HTTP wrappers like `this.get(`/api/...${id}/...`)` where the receiver
|
|
690
|
+
// isn't named http/api/client. SQL queries never start with `/`; URL paths always do.
|
|
691
|
+
const firstArgIsUrlPath = /\(\s*[`'"]\s*\/[a-zA-Z0-9_\-/{}$]/.test(matchedLine);
|
|
692
|
+
if (firstArgIsUrlPath && !hasSqlKeyword)
|
|
693
|
+
continue;
|
|
694
|
+
// Service-class HTTP wrapper: `this.get/post/...` with first arg starting from a URL-base var
|
|
695
|
+
// like `${this.basePath}/...` or `${apiUrl}/...`. SQL queries don't use `this.<verb>` style.
|
|
696
|
+
const isServiceVerbCall = /(?:^|[\s=])(?:return\s+|await\s+)?this\.(?:get|post|put|delete|patch|head|options|fetch|request)\s*\(/i.test(matchedLine);
|
|
697
|
+
if (isServiceVerbCall && !hasSqlKeyword)
|
|
698
|
+
continue;
|
|
673
699
|
}
|
|
674
700
|
// Skip supply chain rules for known legitimate packages
|
|
675
701
|
if (["VG872", "VG873"].includes(rule.id)) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "guardvibe",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.52",
|
|
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",
|