guardvibe 3.1.25 → 3.1.27
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 +28 -0
- package/README.md +13 -13
- package/build/cli/audit.js +2 -1
- package/build/cli/init.js +14 -4
- package/build/data/rules/api-security.js +13 -0
- package/build/data/rules/database.js +13 -0
- package/build/data/rules/modern-stack.js +13 -0
- package/build/data/rules/supply-chain.js +26 -0
- package/build/index.js +1 -1
- package/build/tools/full-audit.d.ts +7 -2
- package/build/tools/full-audit.js +81 -1
- package/build/utils/config.js +7 -1
- package/package.json +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,34 @@ 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.1.27] - 2026-06-06
|
|
9
|
+
|
|
10
|
+
### Fixed
|
|
11
|
+
- **`audit --format sarif` now emits real SARIF v2.1.0** (was silently falling back to a markdown report). The audit SARIF covers all six sections — code, secrets, dependencies, config, taint, auth-coverage — so it is strictly richer than `scan --format sarif` (code-only). `audit --format sarif` now implies `--full` so CI gets every finding with no silent truncation; each result carries its originating section + severity in `properties`, and run-level `properties` carry verdict / score / grade / resultHash
|
|
12
|
+
- **`init claude` hook is now version-pinned** (was `guardvibe@latest`). The PostToolUse hook command now pins to the same version as the MCP server, restoring the determinism guarantee; re-running `init` also rewrites a stale `@latest` (or older-pinned) hook to the current version
|
|
13
|
+
- **Malformed `.guardviberc` no longer fails silently.** A `.guardviberc` that is not valid JSON now prints a warning to **stderr** (stdout stays clean for MCP JSON-RPC and machine formats) telling the user their `rules.disable` / `authExceptions` / `scan.exclude` are NOT being applied — previously the parse error was swallowed and defaults were used with no signal
|
|
14
|
+
|
|
15
|
+
### Notes
|
|
16
|
+
- Surfaced by a fresh-user end-to-end simulation (CLI commands, MCP tools, host inits, output formats, edge cases, real-world dogfood). Self-audit PASS A 100; dogfood result hashes unchanged (dvna 58, juice-shop 199, nodejs-goof 295)
|
|
17
|
+
|
|
18
|
+
## [3.1.26] - 2026-06-06
|
|
19
|
+
|
|
20
|
+
### Added — 5 new rules (424 → 429)
|
|
21
|
+
- **VG1071** axios proxy-auth credential leak on cross-origin redirect. Flags axios client pins on vulnerable ranges where `proxy.auth` Basic credentials are forwarded to the redirect target host; fix advises pinning via `overrides`/`resolutions` to the patched line and stripping `Proxy-Authorization` on host change via a request interceptor
|
|
22
|
+
- **VG1072** hono `setCookie` attribute injection / cookie smuggling. Detects untrusted input flowing into `setCookie(c, name, value, …)` without sanitization of CR / LF / `;` bytes — enables Set-Cookie header injection and downstream cookie smuggling on the same response
|
|
23
|
+
- **VG1073** drizzle `sql.raw()` user-input interpolation. Flags `sql.raw(\`…${userInput}…\`)` and `db.execute(sql.raw(…))` patterns that splice request data into raw SQL — bypasses drizzle's parameterized-query safety net. Fix advises switching to the `sql\`…${userInput}\`` tagged-template form which parameterizes the binding
|
|
24
|
+
- **VG1074** Miasma supply-chain IOC — `@redhat-cloud-services/*` namespace compromise (RHSB-2026-006). Pins the maintainer-account-takeover wave that shipped credential-exfil postinstall scripts under the Red Hat scope; fix advises pinning to pre-compromise versions via `overrides` and rotating any npm/CI tokens reachable from `npm install`
|
|
25
|
+
- **VG1075** Session messenger exfil endpoint IOC (`filev2.getsession.org`). Detects callsites and stringified URLs that point at the Session-relay endpoint used by the Miasma wave (and other recent supply-chain payloads) to POST exfiltrated `process.env` + `~/.npmrc` content to attacker infrastructure
|
|
26
|
+
|
|
27
|
+
### Changed
|
|
28
|
+
- `overrides` bumped: `hono` → `^4.12.21` (covers VG1042 + VG1072 patched line)
|
|
29
|
+
- CLI `rulesApplied` default 424 → 429 (src/index.ts + src/tools/full-audit.ts)
|
|
30
|
+
- `server.json` (MCP registry metadata) refreshed: 390 → 429 rules, version 3.1.22 → 3.1.26
|
|
31
|
+
- README updated end-to-end: hero count 422 → 429, CVE-version intelligence 60 → 63, new threat-intel bullet for VG1069 → VG1075, supply-chain section calls out VG1069 / VG1070 / VG1074 / VG1075
|
|
32
|
+
|
|
33
|
+
### Self-audit
|
|
34
|
+
- `npx guardvibe audit` after `npm audit fix` → PASS A 100 (0 findings, 0 advisories)
|
|
35
|
+
|
|
8
36
|
## [3.1.25] - 2026-05-16
|
|
9
37
|
|
|
10
38
|
### Added — 2 new rules (422 → 424)
|
package/README.md
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
[](https://www.npmjs.com/package/guardvibe)
|
|
7
7
|
[](https://codecov.io/gh/goklab/guardvibe)
|
|
8
8
|
|
|
9
|
-
**The security MCP built for vibe coding.**
|
|
9
|
+
**The security MCP built for vibe coding.** 429 security rules, 36 tools covering the entire AI-generated code journey — from first line to production deployment.
|
|
10
10
|
|
|
11
11
|
Works with **Claude Code, Cursor, Gemini CLI, Codex, VS Code (Copilot), Windsurf**, and any MCP-compatible coding agent.
|
|
12
12
|
|
|
@@ -14,11 +14,11 @@ Works with **Claude Code, Cursor, Gemini CLI, Codex, VS Code (Copilot), Windsurf
|
|
|
14
14
|
|
|
15
15
|
Most security tools are built for enterprise security teams. GuardVibe is built for **you** — the developer using AI to build and ship web apps fast.
|
|
16
16
|
|
|
17
|
-
- **
|
|
17
|
+
- **429 security rules, 36 tools** purpose-built for the stacks AI agents generate
|
|
18
18
|
- **Zero setup friction** — `npx guardvibe` and you're scanning
|
|
19
19
|
- **No account required** — runs 100% locally, no API keys, no cloud
|
|
20
20
|
- **Understands your stack** — not generic SAST, but rules that know Next.js, Supabase, Stripe, Clerk, and the tools you actually use
|
|
21
|
-
- **CVE version intelligence** — detects
|
|
21
|
+
- **CVE version intelligence** — detects 63 known vulnerable package versions in package.json, refreshed every day from GHSA / OSV.dev / CISA KEV
|
|
22
22
|
- **AI agent & MCP security** — detects MCP server vulnerabilities, tool-description prompt injection (OWASP MCP Top 10), model-controlled sandbox-disable flags, excessive AI permissions, indirect prompt injection
|
|
23
23
|
- **Auto-fix suggestions** — `fix_code` tool returns concrete patches and structured edits the AI agent can apply mechanically. Coverage: hardcoded credentials → env-var migration; public-prefix LLM keys (`NEXT_PUBLIC_/VITE_/EXPO_PUBLIC_/REACT_APP_`) → prefix removal; CORS wildcards → env allowlist; `dangerouslyAllowBrowser` flags → drop; sandbox bypass flags (`unsafe`/`noSandbox`/`allowEval`) → drop; agent loops → add `maxSteps`; raw-HTML React props → `<ReactMarkdown>`; missing auth checks → insert auth guard; SQL injection → parameterized queries; missing rate limiters / CSRF / security headers → snippet templates.
|
|
24
24
|
- **Pre-commit hook** — block insecure code before it reaches your repo
|
|
@@ -28,7 +28,7 @@ Most security tools are built for enterprise security teams. GuardVibe is built
|
|
|
28
28
|
|
|
29
29
|
## New in v3.1.x
|
|
30
30
|
|
|
31
|
-
- **Daily threat-intel pipeline** — rule set tracks GHSA / OSV.dev / CISA KEV every day. v3.1.
|
|
31
|
+
- **Daily threat-intel pipeline** — rule set tracks GHSA / OSV.dev / CISA KEV every day. Latest shipments (v3.1.24 → v3.1.26) added `VG1069` node-ipc protestware detection, `VG1070` CI `npm` provenance / `--ignore-scripts` hardening, `VG1071` axios proxy-auth redirect credential leak, `VG1072` hono `setCookie` attribute injection, `VG1073` drizzle `sql.raw` interpolation, `VG1074` Miasma `@redhat-cloud-services` namespace compromise IOC (RHSB-2026-006), and `VG1075` Session messenger exfil endpoint IOC (`filev2.getsession.org`). The hono override floor is pinned to `^4.12.21`. Earlier in the v3.1.2x line: Next.js May 2026 13-advisory cluster, Drizzle ORM SQL identifier injection (CVE-2026-39356), Clerk `clerkFrontendApiProxy` SSRF (CVE-2026-34076), tRPC `experimental_nextAppDirCaller` prototype pollution (CVE-2025-68130), MikroORM SQL injection, angular-expressions filter RCE, `@tanstack/*` Mini Shai-Hulud supply-chain attack, Kysely JSON-path traversal, `@nyariv/sandboxjs` sandbox escape, OpenClaude `dangerouslyDisableSandbox` model-controlled flag, Strapi content-type builder SQL injection, LangSmith untrusted prompt-manifest deserialization, and more
|
|
32
32
|
- **OWASP MCP Top 10 alignment** — `VG1068` flags MCP / AI tool definitions whose `description`, `instructions`, or `systemPrompt` fields carry prompt-injection markers (`ignore previous instructions`, `you are now`, `jailbreak mode`, `system prompt:`, `override safety`, …); pair with `VG1063` which catches `dangerouslyDisableSandbox: true` in agent runtimes
|
|
33
33
|
- **Inline suppress** — `// guardvibe-ignore VG001` silences individual findings per-line
|
|
34
34
|
- **CLI-first approach** — `npx guardvibe audit`, `npx guardvibe scan`, `npx guardvibe doctor` all work standalone without MCP
|
|
@@ -49,10 +49,10 @@ GuardVibe is purpose-built for the AI coding workflow. Traditional tools are exc
|
|
|
49
49
|
| AI/LLM security (prompt injection, MCP, tool abuse) | 68 rules | Experimental/None | None |
|
|
50
50
|
| AI host security (CVE-2025-59536, CVE-2026-21852) | `guardvibe doctor` | Not supported | Not supported |
|
|
51
51
|
| Auto-fix suggestions for AI agents | `fix_code` tool | CLI autofix | Not supported |
|
|
52
|
-
| CVE version detection |
|
|
52
|
+
| CVE version detection | 63 packages, refreshed daily | Extensive | Extensive |
|
|
53
53
|
| Compliance mapping (SOC2, PCI-DSS, HIPAA) | Built-in | Paid tier | None |
|
|
54
54
|
| SARIF CI/CD export | Yes | Yes | Limited |
|
|
55
|
-
| Rule count |
|
|
55
|
+
| Rule count | 429 (focused, 68 AI-native) | 5000+ (broad) | N/A |
|
|
56
56
|
|
|
57
57
|
**When to use GuardVibe:** You're building with AI agents and want security scanning integrated into your coding workflow — no dashboard, no account, no CI setup.
|
|
58
58
|
|
|
@@ -176,13 +176,13 @@ React Native, Expo — AsyncStorage secrets, deep link token exposure, hardcoded
|
|
|
176
176
|
### Firebase
|
|
177
177
|
Firestore security rules, Firebase Admin SDK exposure, storage rules, custom token validation
|
|
178
178
|
|
|
179
|
-
### CVE Version Intelligence (
|
|
179
|
+
### CVE Version Intelligence (63 CVEs, refreshed daily)
|
|
180
180
|
**Frameworks:** Next.js (CVE-2024-34351, CVE-2024-46982, CVE-2025-29927, CVE-2026-23869, CVE-2026-44573 / 44574 / 44575 / 44578 / 44579 / 45109 May 2026 cluster), React + react-server-dom-* (CVE-2025-55182, CVE-2026-23870), Express, Hono pre-4.12.18 cluster, @vitejs/plugin-rsc, Strapi content-type-builder (CVE-2026-22599)
|
|
181
181
|
**Auth:** Clerk middleware bypass (GHSA-vqx2), Clerk `has()` org/billing/reverification bypass (GHSA-w24r), Clerk `clerkFrontendApiProxy` SSRF (CVE-2026-34076), NextAuth.js (2 CVEs), jsonwebtoken
|
|
182
|
-
**ORMs / SQL:** Drizzle SQL identifier injection (CVE-2026-39356), MikroORM SQL injection (CVE-2026-44680), Prisma raw-query call-form, Kysely JSON-path traversal (CVE-2026-44635)
|
|
182
|
+
**ORMs / SQL:** Drizzle SQL identifier injection (CVE-2026-39356) + Drizzle `sql.raw` interpolation (VG1073), MikroORM SQL injection (CVE-2026-44680), Prisma raw-query call-form, Kysely JSON-path traversal (CVE-2026-44635)
|
|
183
183
|
**AI ecosystem:** @anthropic-ai/sdk (CVE-2026-34451 + memory tool path escape), Vercel AI SDK file-type bypass (CVE-2025-48985), LangSmith untrusted prompt manifest (CVE-2026-45134), OpenClaude sandbox bypass (CVE-2026-42074), @nyariv/sandboxjs Function.caller escape (CVE-2026-43898)
|
|
184
|
-
**HTTP / parsing:** Axios pre-1.15.2 cluster (SSRF + prototype-pollution + DoS + CRLF), fast-uri path traversal + host confusion (CVE-2026-6321 / 6322), fast-xml-parser CDATA injection, xmldom CDATA, protobuf.js multi-CVE cluster, undici (2 CVEs), ws
|
|
185
|
-
**Tools / supply chain:** @tanstack/* Mini Shai-Hulud (84 malicious versions, May 2026), @wdio/browserstack-service command injection (CVE-2026-25244), @babel/plugin-transform-modules-systemjs arbitrary code (CVE-2026-44728), @opentelemetry exporter-prometheus DoS (CVE-2026-44902), systeminformation Linux cmd injection (CVE-2026-44724), velocityjs prototype pollution, defu, sharp, lodash, node-fetch, tar, xml2js, crypto-js, angular-expressions RCE, i18next-http-backend, vm2 sandbox breakouts
|
|
184
|
+
**HTTP / parsing:** Axios pre-1.15.2 cluster (SSRF + prototype-pollution + DoS + CRLF) + axios proxy-auth redirect leak (VG1071), Hono `setCookie` attribute injection (VG1072, override pinned `^4.12.21`), fast-uri path traversal + host confusion (CVE-2026-6321 / 6322), fast-xml-parser CDATA injection, xmldom CDATA, protobuf.js multi-CVE cluster, undici (2 CVEs), ws
|
|
185
|
+
**Tools / supply chain:** node-ipc protestware (VG1069), Miasma `@redhat-cloud-services` namespace compromise IOC (VG1074), Session messenger exfil endpoint IOC (VG1075), @tanstack/* Mini Shai-Hulud (84 malicious versions, May 2026), @wdio/browserstack-service command injection (CVE-2026-25244), @babel/plugin-transform-modules-systemjs arbitrary code (CVE-2026-44728), @opentelemetry exporter-prometheus DoS (CVE-2026-44902), systeminformation Linux cmd injection (CVE-2026-44724), velocityjs prototype pollution, defu, sharp, lodash, node-fetch, tar, xml2js, crypto-js, angular-expressions RCE, i18next-http-backend, vm2 sandbox breakouts
|
|
186
186
|
|
|
187
187
|
### Deployment & Config
|
|
188
188
|
Vercel (vercel.json, cron secrets, headers), Next.js config, Docker, Docker Compose, Fly.io, Render, Netlify, Cloudflare
|
|
@@ -197,7 +197,7 @@ API keys (AWS, GitHub, Stripe, OpenAI, Resend, Turso), .env management, .gitigno
|
|
|
197
197
|
Maps security findings to SOC2, PCI-DSS, HIPAA, GDPR, ISO27001, and EU AI Act (EUAIACT) controls. Identifies which code-level vulnerabilities are relevant to specific compliance requirements. **Not a substitute for professional compliance audits.**
|
|
198
198
|
|
|
199
199
|
### Supply Chain
|
|
200
|
-
Malicious postinstall scripts, unpinned GitHub Actions, typosquat detection, `@tanstack/*` Mini Shai-Hulud mass-malware versions (May 2026), `@wdio/browserstack-service` command injection via git branch names (CVE-2026-25244), lockfile poisoning patterns
|
|
200
|
+
Malicious postinstall scripts, unpinned GitHub Actions, CI `npm` provenance / `--ignore-scripts` hardening (VG1070), typosquat detection, `node-ipc` protestware versions (VG1069), Miasma `@redhat-cloud-services` namespace compromise IOC (VG1074, RHSB-2026-006), Session messenger exfil endpoint IOC (VG1075, `filev2.getsession.org`), `@tanstack/*` Mini Shai-Hulud mass-malware versions (May 2026), `@wdio/browserstack-service` command injection via git branch names (CVE-2026-25244), lockfile poisoning patterns
|
|
201
201
|
|
|
202
202
|
## Tools (36 MCP tools)
|
|
203
203
|
|
|
@@ -242,7 +242,7 @@ Malicious postinstall scripts, unpinned GitHub Actions, typosquat detection, `@t
|
|
|
242
242
|
|
|
243
243
|
All scanning tools support `format: "json"` for machine-readable output.
|
|
244
244
|
|
|
245
|
-
## Security Rules (
|
|
245
|
+
## Security Rules (429 rules across 25 modules)
|
|
246
246
|
|
|
247
247
|
| Category | Rules | Coverage |
|
|
248
248
|
|----------|-------|----------|
|
|
@@ -457,7 +457,7 @@ If your AI agent cannot connect to GuardVibe:
|
|
|
457
457
|
|
|
458
458
|
1. **Restart your IDE/agent.** MCP servers are started by the host application. After running `npx guardvibe init`, restart Claude Code, Cursor, or Gemini CLI for the config to take effect.
|
|
459
459
|
2. **Check the config path.** Run `npx guardvibe init claude` again and verify the output shows the correct config file location (`.mcp.json` in your project root for Claude Code, `.cursor/mcp.json` for Cursor).
|
|
460
|
-
3. **Re-run `init` to upgrade.** When upgrading GuardVibe, re-run `npx guardvibe init claude` — `.mcp.json` is pinned to a specific version (e.g. `guardvibe@3.1.
|
|
460
|
+
3. **Re-run `init` to upgrade.** When upgrading GuardVibe, re-run `npx guardvibe init claude` — `.mcp.json` is pinned to a specific version (e.g. `guardvibe@3.1.27`) at init time for fast deterministic startup. As of v3.1.2 the re-run also rewrites stale pins automatically (`Upgraded GuardVibe pin (3.1.26 → 3.1.27)`); since v3.1.27 the PostToolUse hook command is pinned to the same version (was `@latest`) and re-run upgrades a stale hook too. The same applies to `npx guardvibe hook install` and `npx guardvibe ci github` (since v3.1.3) — both are version-pinned at install/generate time and re-run to upgrade.
|
|
461
461
|
4. **Pre-3.1.1 users won't see the auto-update banner.** GuardVibe started writing a once-per-day "newer version available" notice to stderr in v3.1.1. If your install predates that, you'll never see it — run `npx -y guardvibe@latest init <host>` once to bake in the latest pin and start receiving banners on subsequent sessions.
|
|
462
462
|
5. **Verify Node.js version.** GuardVibe requires Node.js >= 18.0.0. Check with `node --version`.
|
|
463
463
|
6. **Check npx cache.** If you upgraded GuardVibe and the old version is cached, run `npx -y guardvibe@latest` to force the latest version.
|
package/build/cli/audit.js
CHANGED
|
@@ -16,7 +16,8 @@ export async function runAudit(args) {
|
|
|
16
16
|
const failOn = getStringFlag(flags, "fail-on") ?? "critical";
|
|
17
17
|
const skipDeps = flags["skip-deps"] === true;
|
|
18
18
|
const skipSecrets = flags["skip-secrets"] === true;
|
|
19
|
-
|
|
19
|
+
// SARIF is consumed by CI / code-scanning — never silently truncate findings.
|
|
20
|
+
const full = flags["full"] === true || rawFormat === "sarif";
|
|
20
21
|
setRules(builtinRules);
|
|
21
22
|
// Terminal format by default when outputting to TTY, unless --format is specified
|
|
22
23
|
const isTerminal = !outputFile && process.stdout.isTTY && !flags["format"];
|
package/build/cli/init.js
CHANGED
|
@@ -109,17 +109,27 @@ function setupClaudeGuide() {
|
|
|
109
109
|
const existingSettings = readJsonFile(claudeSettingsPath) || {};
|
|
110
110
|
if (!existingSettings.hooks)
|
|
111
111
|
existingSettings.hooks = {};
|
|
112
|
+
const hookCommand = `jq -r '.tool_input.file_path' | xargs npx -y guardvibe@${pkg.version} check --format buddy 2>/dev/null || true`;
|
|
112
113
|
if (!existingSettings.hooks.PostToolUse) {
|
|
113
114
|
existingSettings.hooks.PostToolUse = [
|
|
114
115
|
{
|
|
115
116
|
matcher: "Edit|Write",
|
|
116
|
-
hooks: [{
|
|
117
|
-
type: "command",
|
|
118
|
-
command: "jq -r '.tool_input.file_path' | xargs npx -y guardvibe@latest check --format buddy 2>/dev/null || true"
|
|
119
|
-
}]
|
|
117
|
+
hooks: [{ type: "command", command: hookCommand }]
|
|
120
118
|
}
|
|
121
119
|
];
|
|
122
120
|
}
|
|
121
|
+
else {
|
|
122
|
+
// Re-run upgrade: rewrite any stale GuardVibe hook command (e.g. @latest or an
|
|
123
|
+
// older pin) to the current pinned version — keeps the hook scanner deterministic
|
|
124
|
+
// and in lock-step with the pinned MCP server.
|
|
125
|
+
for (const entry of existingSettings.hooks.PostToolUse) {
|
|
126
|
+
for (const h of entry?.hooks ?? []) {
|
|
127
|
+
if (typeof h.command === "string" && /npx\s+-y\s+guardvibe@[^\s]+\s+check/.test(h.command)) {
|
|
128
|
+
h.command = hookCommand;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
123
133
|
writeJsonFile(claudeSettingsPath, existingSettings);
|
|
124
134
|
console.log(` [OK] Claude Code hooks configured (.claude/settings.json)`);
|
|
125
135
|
const claudeMdPath = join(process.cwd(), "CLAUDE.md");
|
|
@@ -128,4 +128,17 @@ export const apiSecurityRules = [
|
|
|
128
128
|
fixCode: 'catch (error) {\n console.error("Internal error:", error); // log server-side\n return Response.json(\n { error: "Something went wrong" }, // generic to client\n { status: 500 }\n );\n}',
|
|
129
129
|
compliance: ["SOC2:CC7.2"],
|
|
130
130
|
},
|
|
131
|
+
{
|
|
132
|
+
id: "VG1071",
|
|
133
|
+
name: "Axios Proxy Auth Leak Through Redirect (CVE-2026-44486 / CVE-2026-44487)",
|
|
134
|
+
severity: "high",
|
|
135
|
+
owasp: "API8:2023 Security Misconfiguration",
|
|
136
|
+
description: "An axios() call or axios.create() config sets a proxy with auth credentials (or a Proxy-Authorization header) without disabling redirect-following. When axios follows a 3xx redirect, the original Proxy-Authorization header is replayed against the redirect destination — leaking proxy credentials to whatever origin an attacker can redirect to. CVE-2026-44486 (Proxy-Authorization leak to redirect target) and CVE-2026-44487 (header carry-over to origin server) describe the dual leak; either is enough to compromise the proxy account. The rule fires when proxy auth is present and no nearby maxRedirects: 0 mitigation is set; pair the upgrade with a hard-coded maxRedirects: 0 on any request that traverses an authenticated proxy.",
|
|
137
|
+
pattern: /\baxios(?:\.create)?\s*\(\s*\{(?:(?!maxRedirects\s*:\s*0)[\s\S]){0,800}?\bproxy\s*:\s*\{(?:(?!maxRedirects\s*:\s*0)[\s\S]){0,400}?(?:\bauth\s*:|Proxy-Authorization)(?!(?:(?!\}\s*\))[\s\S]){0,1500}?\bmaxRedirects\s*:\s*0\b)/g,
|
|
138
|
+
languages: ["javascript", "typescript"],
|
|
139
|
+
fix: "Upgrade axios to a patched release that strips Proxy-Authorization on redirects. For pre-patch versions, force maxRedirects: 0 on every request that traverses an authenticated proxy, or replace the credentialed proxy with a non-authenticated proxy plus a signed-URL pattern.",
|
|
140
|
+
fixCode: "// BAD — proxy auth + default redirect-following leaks creds\nconst client = axios.create({\n proxy: {\n host: 'proxy.internal',\n port: 8080,\n auth: { username: process.env.PROXY_USER, password: process.env.PROXY_PASS },\n },\n // maxRedirects defaults to 5 — Proxy-Authorization travels with every hop\n});\n\n// GOOD — hard-disable redirects on the authenticated proxy path\nconst client = axios.create({\n proxy: {\n host: 'proxy.internal',\n port: 8080,\n auth: { username: process.env.PROXY_USER, password: process.env.PROXY_PASS },\n },\n maxRedirects: 0,\n});",
|
|
141
|
+
compliance: ["SOC2:CC6.1", "PCI-DSS:Req4.1", "ISO27001:A.13.2.1"],
|
|
142
|
+
exploit: "Attacker controls a redirect target the proxied request reaches (open redirect on a partner site, attacker-owned subdomain, or DNS-rebinding). Axios issues the second-hop request and replays the cached Proxy-Authorization header — the attacker captures the proxy username/password from the second hop's logs and uses them to pivot inside the corporate network the proxy fronts.",
|
|
143
|
+
},
|
|
131
144
|
];
|
|
@@ -147,4 +147,17 @@ export const databaseRules = [
|
|
|
147
147
|
fixCode: 'import { sql } from "drizzle-orm";\n\n// BAD: user input in identifier\nconst col = req.query.sortBy;\ndb.select().from(sql.identifier(col)); // SQL injection!\n\n// GOOD: allowlist valid identifiers\nconst ALLOWED_COLUMNS = ["name", "email", "created_at"] as const;\nconst col = ALLOWED_COLUMNS.find(c => c === req.query.sortBy);\nif (!col) throw new Error("Invalid column");\ndb.select().from(users).orderBy(users[col]);',
|
|
148
148
|
compliance: ["SOC2:CC7.1", "PCI-DSS:Req6.5.1"],
|
|
149
149
|
},
|
|
150
|
+
{
|
|
151
|
+
id: "VG1073",
|
|
152
|
+
name: "Drizzle sql.raw / sql.identifier with Interpolation or Concatenation (CVE-2026-39356 follow-on)",
|
|
153
|
+
severity: "critical",
|
|
154
|
+
owasp: "A02:2025 Injection",
|
|
155
|
+
description: "A sql.raw(...) or sql.identifier(...) call receives either a backtick template with ${...} interpolation or a string built with + concatenation. Both bypass Drizzle's parameterizer — the constructed string is fed straight into the executed query, exposing the same identifier-escape gap CVE-2026-39356 patched (drizzle-orm < 0.45.2 / 1.0.0-beta.20). On older builds it is a hard SQL injection; on patched builds sql.raw still has no escape at all. The supported safe shape is the tagged template `sql`... ${value}`` (auto-parameterized) plus a strict allowlist for any identifier the caller must vary. Distinct from VG1011, which catches the variable-name form sql.identifier(req.X) only; this rule covers the template-literal and string-concatenation shapes plus the previously-uncovered sql.raw call.",
|
|
156
|
+
pattern: /\bsql\s*\.\s*(?:raw|identifier)\s*\(\s*(?:`[^`]{0,400}\$\{|[\s\S]{0,200}?(?<![=!<>])\+(?!\+|=))/g,
|
|
157
|
+
languages: ["javascript", "typescript"],
|
|
158
|
+
fix: "Replace sql.raw / sql.identifier interpolation with the tagged-template form sql`... ${value}` (auto-parameterized) for values, and a hardcoded allowlist for any table/column identifier you must vary by request. Upgrade drizzle-orm to 0.45.2+ (stable) or 1.0.0-beta.20+ (beta) to close the escape gap covered by VG1052.",
|
|
159
|
+
fixCode: "// BAD — template-literal interpolation feeds attacker input straight in\nawait db.execute(sql.raw(`SELECT * FROM ${table} WHERE id = ${id}`));\n\n// BAD — string concatenation into sql.raw\nawait db.execute(sql.raw('SELECT * FROM users WHERE name = \\'' + name + '\\''));\n\n// GOOD — tagged template auto-parameterizes the value\nimport { sql } from 'drizzle-orm';\nawait db.execute(sql`SELECT * FROM users WHERE id = ${id}`);\n\n// GOOD — strict allowlist when the identifier really must vary\nconst ALLOWED_TABLES = ['users', 'orders'] as const;\nif (!ALLOWED_TABLES.includes(table as never)) throw new Error('Invalid table');\nawait db.execute(sql`SELECT * FROM ${sql.identifier(table)}`);",
|
|
160
|
+
compliance: ["SOC2:CC7.1", "PCI-DSS:Req6.5.1"],
|
|
161
|
+
exploit: "Attacker controls a request field that becomes the value of `table` or `id`. A payload like `users WHERE 1=1; DROP TABLE users; --` is concatenated into the raw query string; Drizzle hands the whole string to the driver and the driver executes the injected statements with the application's database role.",
|
|
162
|
+
},
|
|
150
163
|
];
|
|
@@ -593,4 +593,17 @@ export const modernStackRules = [
|
|
|
593
593
|
fixCode: '// BAD: unvalidated Server Action argument\n"use server";\nexport async function updateUser(data: any) {\n await prisma.user.update({ where: { id: data.id }, data });\n}\n\n// GOOD: validate with zod before any operation\n"use server";\nimport { z } from "zod";\nconst schema = z.object({ id: z.string().uuid(), name: z.string().max(100) });\nexport async function updateUser(raw: unknown) {\n const data = schema.parse(raw);\n await prisma.user.update({ where: { id: data.id }, data: { name: data.name } });\n}',
|
|
594
594
|
compliance: ["SOC2:CC7.1", "PCI-DSS:Req6.2", "PCI-DSS:Req6.5.1"],
|
|
595
595
|
},
|
|
596
|
+
{
|
|
597
|
+
id: "VG1072",
|
|
598
|
+
name: "Hono setCookie sameSite/priority From User Input (CVE-2026-47675)",
|
|
599
|
+
severity: "medium",
|
|
600
|
+
owasp: "A02:2025 Injection",
|
|
601
|
+
description: "Hono's setCookie / setSignedCookie helper accepts a config object with sameSite and priority attributes. When user-controlled input (c.req.X, c.get(), req.body, query/params, formData, etc.) flows into one of those attributes, an attacker can break out of the intended enum value and inject extra cookie attributes — flipping Secure or HttpOnly off, downgrading SameSite from Strict to None, or appending a duplicate Set-Cookie segment that overrides the legitimate one. CVE-2026-47675 documents the attribute-injection bypass in the affected hono line; the safe pattern always passes a literal enum value or maps the input through a strict allowlist first. Distinct from VG924, which is the older CRLF-injection CVE-2026-29086 in the cookie value itself.",
|
|
602
|
+
pattern: /\b(?:setCookie|setSignedCookie)\s*\([\s\S]{0,300}?(?:\bsameSite\b|\bpriority\b)\s*:\s*(?:c\.req\.|c\.get\(|req\.|request\.|input\.|params\.|body\.|query\.|searchParams|formData|ctx\.|args\.)/g,
|
|
603
|
+
languages: ["javascript", "typescript"],
|
|
604
|
+
fix: "Never pass user-controlled input to the sameSite or priority cookie attributes. Use a literal enum value ('Strict'/'Lax'/'None' for sameSite, 'Low'/'Medium'/'High' for priority) or map the user input through a strict allowlist first. Also upgrade hono to the patched release.",
|
|
605
|
+
fixCode: "// BAD — user input flows into sameSite attribute\nsetCookie(c, 'session', token, {\n sameSite: c.req.query('site_mode'), // attacker chooses\n httpOnly: true,\n});\n\n// GOOD — literal value, never user input\nsetCookie(c, 'session', token, {\n sameSite: 'Strict',\n httpOnly: true,\n secure: true,\n});\n\n// GOOD — allowlist if you really need to vary\nconst SAFE_SAMESITE = { strict: 'Strict', lax: 'Lax' } as const;\nconst mode = SAFE_SAMESITE[c.req.query('site_mode') as keyof typeof SAFE_SAMESITE] ?? 'Strict';\nsetCookie(c, 'session', token, { sameSite: mode, httpOnly: true });",
|
|
606
|
+
compliance: ["SOC2:CC7.1", "PCI-DSS:Req6.5.10"],
|
|
607
|
+
exploit: "Attacker submits a query parameter whose value contains cookie-attribute terminators (e.g. `Lax; Secure=false; HttpOnly=false` or `Strict\\r\\nSet-Cookie: tracker=x`). The helper renders the value into the Set-Cookie header verbatim — the browser then either downgrades the cookie's flags or treats the injected segment as a separate Set-Cookie, hijacking the session.",
|
|
608
|
+
},
|
|
596
609
|
];
|
|
@@ -204,4 +204,30 @@ export const supplyChainRules = [
|
|
|
204
204
|
fixCode: '// package.json — pin to clean versions\n"@tanstack/react-router": "^1.169.9", // or latest non-malicious\n"@tanstack/router-core": "^1.169.9",\n"@tanstack/react-start": "^1.167.72"\n\n// pnpm / yarn / npm overrides to evict transitive copies\n"overrides": {\n "@tanstack/react-router": "^1.169.9",\n "@tanstack/router-core": "^1.169.9"\n}\n\n// Network mitigation while rotating: block *.getsession.org egress',
|
|
205
205
|
compliance: ["SOC2:CC6.1", "SOC2:CC7.1", "PCI-DSS:Req6.2", "PCI-DSS:Req3.5"],
|
|
206
206
|
},
|
|
207
|
+
{
|
|
208
|
+
id: "VG1074",
|
|
209
|
+
name: "@redhat-cloud-services/* Miasma Supply-Chain Compromise (RHSB-2026-006)",
|
|
210
|
+
severity: "high",
|
|
211
|
+
owasp: "A03:2025 Software Supply Chain Failures",
|
|
212
|
+
description: "On 2026-06-01 the Miasma campaign published trojanized versions across at least 32 packages in the @redhat-cloud-services npm namespace (combined ~80K weekly downloads). The attacker reused a compromised Red Hat employee GitHub account to push orphan commits, then leveraged the repository's GitHub Actions OIDC trusted-publisher chain to ship malicious packages WITH valid SLSA provenance attestations — provenance alone is no longer a sufficient trust signal here. A preinstall hook fetches a ~4.29 MB obfuscated dropper that downloads the Bun runtime and exfiltrates GitHub / npm / AWS / Azure / GCP credentials, SSH private keys, browser-stored secrets, and crypto-wallet data over the Session/Oxen messenger network (filev2.getsession.org — same exfil family as VG1056 @tanstack). Sources: Wiz blog, Microsoft Security Response Center, Red Hat RHSB-2026-006. Until the namespace publishes a clean, audited replacement series, treat every @redhat-cloud-services/* version reference in a package.json or lockfile as suspect; rotate every credential the install host could reach.",
|
|
213
|
+
pattern: /["']@redhat-cloud-services\/[a-z0-9._-]+["']\s*:\s*["'](?:\^|~|>=?|=)?\s*[^"']{1,80}["']/g,
|
|
214
|
+
languages: ["json"],
|
|
215
|
+
fix: "Remove every @redhat-cloud-services/* dependency until Red Hat publishes a clean replacement series under a new (un-compromised) namespace or numbered re-release. Rotate every credential the install host could reach: AWS access keys, GCP service-account keys, Azure tokens, GitHub PATs, npm tokens, SSH private keys, browser-cached cookies, and any crypto-wallet seed. Wipe and reissue the CI runner if the install ran in CI. Add filev2.getsession.org and *.getsession.org to your egress denylist. Do NOT trust SLSA provenance as sole evidence — the attacker forged provenance via the OIDC trusted-publisher chain.",
|
|
216
|
+
fixCode: '// package.json — remove every @redhat-cloud-services/* entry\n// (currently EVERY version in this namespace is suspect)\n\n// If a transitive copy is pulled in by another dep, evict via overrides:\n"overrides": {\n "@redhat-cloud-services/some-package": "npm:noop@1.0.0"\n}\n\n// Egress controls while rotating credentials:\n// - block *.getsession.org\n// - block bun.sh and github.com/oven-sh/bun/releases on CI runners\n// that have no legitimate Bun runtime usage',
|
|
217
|
+
compliance: ["SOC2:CC6.1", "SOC2:CC7.1", "PCI-DSS:Req6.2", "PCI-DSS:Req3.5"],
|
|
218
|
+
exploit: "Attacker who compromised a Red Hat employee's GitHub credentials pushes an orphan commit that adds a preinstall lifecycle script to one or more @redhat-cloud-services/* packages, then triggers the repository's publish workflow. The workflow uses the OIDC trusted-publisher chain, so npm accepts the malicious tarball with a valid provenance attestation. Any developer or CI runner that runs `npm install` on a project depending on the package — directly or transitively — executes the preinstall script, which downloads the Bun runtime, decodes a credential-stealer payload, harvests environment files and cloud credentials, and exfiltrates them over Session messenger to filev2.getsession.org.",
|
|
219
|
+
},
|
|
220
|
+
{
|
|
221
|
+
id: "VG1075",
|
|
222
|
+
name: "Session Messenger Exfil Endpoint Reference (filev2.getsession.org)",
|
|
223
|
+
severity: "critical",
|
|
224
|
+
owasp: "A03:2025 Software Supply Chain Failures",
|
|
225
|
+
description: "Code, configuration, or dependency references the Session/Oxen messenger file-relay endpoint filev2.getsession.org (or another *.getsession.org host) as a fetch target, base URL, or hardcoded constant. This endpoint is the documented exfiltration channel for two distinct 2026 supply-chain campaigns: @tanstack mass malware (CVE-2026-45321, VG1056) and the Miasma @redhat-cloud-services compromise (RHSB-2026-006, VG1074). A web/server codebase has no legitimate reason to talk to this host; presence is a high-confidence Indicator of Compromise. Audit the host running this code for credential rotation candidates immediately.",
|
|
226
|
+
pattern: /\b(?:[a-z0-9-]+\.)?getsession\.org\b/gi,
|
|
227
|
+
languages: ["javascript", "typescript", "json"],
|
|
228
|
+
fix: "Treat the host running this code as potentially compromised. Block *.getsession.org egress at the firewall, rotate every cloud, npm, GitHub, and SSH credential reachable from the host, wipe and reissue the runner if it is a CI box, and search the lockfile for the upstream package that introduced the reference. Pin away from that package or use overrides to evict it. Search git history for when the reference appeared to estimate the exposure window.",
|
|
229
|
+
fixCode: "// REMOVE — never legitimate in a web/server codebase\n// const exfilUrl = 'https://filev2.getsession.org/file';\n\n// If you genuinely use Session as an end-user feature (not as an exfil channel),\n// move the URL behind a feature flag and document why. Add an explicit allowlist\n// comment so this rule can be suppressed via .guardviberc:\n// { rules: { allow: [{ id: 'VG1075', paths: ['src/features/session-link.ts'] }] } }",
|
|
230
|
+
compliance: ["SOC2:CC6.1", "SOC2:CC7.1", "PCI-DSS:Req6.2"],
|
|
231
|
+
exploit: "Attacker leverages Session's anonymity-by-design file relay (no DNS exposure, encrypted at the network layer, no account binding) to exfiltrate stolen credentials. Any code or dependency that posts to filev2.getsession.org is almost certainly an installed credential stealer staged by a supply-chain compromise — most often a malicious npm preinstall script that has already executed once on this host.",
|
|
232
|
+
},
|
|
207
233
|
];
|
package/build/index.js
CHANGED
|
@@ -889,7 +889,7 @@ server.tool("deep_scan", "LLM-powered deep security analysis for vulnerabilities
|
|
|
889
889
|
return { content: [{ type: "text", text: output }] };
|
|
890
890
|
});
|
|
891
891
|
// Tool 33: Full audit — single source of truth
|
|
892
|
-
server.tool("full_audit", "Single command that runs ALL checks: code scan (
|
|
892
|
+
server.tool("full_audit", "Single command that runs ALL checks: code scan (429 rules), secret detection, dependency CVEs, config audit, taint analysis, and auth coverage. Returns PASS/FAIL/WARN verdict with deterministic hash. IMPORTANT: If verdict is FAIL or WARN, you MUST call remediation_plan next to get a section-by-section fix checklist — do NOT skip any section. After fixing, call verify_remediation to confirm ALL sections are addressed. Example: full_audit({path: '.'})", {
|
|
893
893
|
path: z.string().default(".").describe("Project root directory"),
|
|
894
894
|
format: z.enum(["markdown", "json"]).default("markdown").describe("Output format"),
|
|
895
895
|
skipDeps: z.boolean().default(false).describe("Skip dependency vulnerability check"),
|
|
@@ -92,6 +92,11 @@ export declare function runFullAudit(path: string, options?: {
|
|
|
92
92
|
full?: boolean;
|
|
93
93
|
}): Promise<AuditResult>;
|
|
94
94
|
/**
|
|
95
|
-
*
|
|
95
|
+
* Build a SARIF v2.1.0 document from a full audit result.
|
|
96
|
+
* Covers every section (code, secrets, dependencies, config, taint, auth-coverage)
|
|
97
|
+
* — richer than `scan --format sarif`, which is code-only.
|
|
98
|
+
* Note: for complete CI coverage, run the audit with `full: true` so sectionFindings
|
|
99
|
+
* are not capped before they reach this formatter.
|
|
96
100
|
*/
|
|
97
|
-
export declare function
|
|
101
|
+
export declare function formatAuditSarif(result: AuditResult): string;
|
|
102
|
+
export declare function formatAuditResult(result: AuditResult, format: "markdown" | "json" | "terminal" | "sarif"): string;
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
* - Coverage metrics (files scanned, rules applied, %)
|
|
8
8
|
*/
|
|
9
9
|
import { createHash } from "node:crypto";
|
|
10
|
+
import { createRequire } from "node:module";
|
|
10
11
|
import { resolve } from "node:path";
|
|
11
12
|
import { readdirSync, readFileSync, statSync, existsSync } from "node:fs";
|
|
12
13
|
import { scanDirectory } from "./scan-directory.js";
|
|
@@ -18,6 +19,8 @@ import { analyzeAuthCoverage } from "./auth-coverage.js";
|
|
|
18
19
|
import { getRules } from "../utils/rule-registry.js";
|
|
19
20
|
import { loadConfig } from "../utils/config.js";
|
|
20
21
|
import { isExcludedFilename } from "../utils/constants.js";
|
|
22
|
+
const _require = createRequire(import.meta.url);
|
|
23
|
+
const _pkg = _require("../../package.json");
|
|
21
24
|
// --- Core Logic ---
|
|
22
25
|
/**
|
|
23
26
|
* Compute verdict: PASS (0 critical + 0 high), WARN (high > 0), FAIL (critical > 0)
|
|
@@ -392,7 +395,7 @@ export async function runFullAudit(path, options) {
|
|
|
392
395
|
const totalHigh = sections.reduce((s, sec) => s + sec.high, 0);
|
|
393
396
|
const totalMedium = sections.reduce((s, sec) => s + sec.medium, 0);
|
|
394
397
|
const totalFindings = sections.reduce((s, sec) => s + sec.findings, 0);
|
|
395
|
-
const rulesApplied = rules.length > 0 ? rules.length :
|
|
398
|
+
const rulesApplied = rules.length > 0 ? rules.length : 429;
|
|
396
399
|
// Adjust score to reflect ALL sections, not just code
|
|
397
400
|
// Each critical finding deducts 5 points, high deducts 3, medium deducts 1
|
|
398
401
|
// Score from code scan is the baseline, other sections reduce it further
|
|
@@ -522,7 +525,84 @@ function buildInlineRemediationPlan(result) {
|
|
|
522
525
|
/**
|
|
523
526
|
* Format audit result as markdown, JSON, or terminal-friendly output.
|
|
524
527
|
*/
|
|
528
|
+
/**
|
|
529
|
+
* Map an audit severity string to a SARIF level.
|
|
530
|
+
*/
|
|
531
|
+
function auditSeverityToLevel(severity) {
|
|
532
|
+
if (severity === "critical" || severity === "high")
|
|
533
|
+
return "error";
|
|
534
|
+
if (severity === "medium")
|
|
535
|
+
return "warning";
|
|
536
|
+
return "note";
|
|
537
|
+
}
|
|
538
|
+
/**
|
|
539
|
+
* Build a SARIF v2.1.0 document from a full audit result.
|
|
540
|
+
* Covers every section (code, secrets, dependencies, config, taint, auth-coverage)
|
|
541
|
+
* — richer than `scan --format sarif`, which is code-only.
|
|
542
|
+
* Note: for complete CI coverage, run the audit with `full: true` so sectionFindings
|
|
543
|
+
* are not capped before they reach this formatter.
|
|
544
|
+
*/
|
|
545
|
+
export function formatAuditSarif(result) {
|
|
546
|
+
const sarifResults = [];
|
|
547
|
+
const ruleMap = new Map();
|
|
548
|
+
for (const section of result.sections) {
|
|
549
|
+
for (const f of section.sectionFindings ?? []) {
|
|
550
|
+
const ruleName = f.name ?? f.ruleId;
|
|
551
|
+
const description = f.description ?? f.name ?? f.ruleId;
|
|
552
|
+
if (!ruleMap.has(f.ruleId)) {
|
|
553
|
+
ruleMap.set(f.ruleId, { id: f.ruleId, name: ruleName, description });
|
|
554
|
+
}
|
|
555
|
+
const messageText = f.fix
|
|
556
|
+
? `${ruleName}: ${description} Fix: ${f.fix}`
|
|
557
|
+
: `${ruleName}: ${description}`;
|
|
558
|
+
sarifResults.push({
|
|
559
|
+
ruleId: f.ruleId,
|
|
560
|
+
level: auditSeverityToLevel(f.severity),
|
|
561
|
+
message: { text: messageText },
|
|
562
|
+
locations: [{
|
|
563
|
+
physicalLocation: {
|
|
564
|
+
artifactLocation: { uri: f.file || "unknown" },
|
|
565
|
+
region: { startLine: f.line > 0 ? f.line : 1 },
|
|
566
|
+
},
|
|
567
|
+
}],
|
|
568
|
+
properties: { section: section.name, severity: f.severity },
|
|
569
|
+
});
|
|
570
|
+
}
|
|
571
|
+
}
|
|
572
|
+
const sarifRules = [...ruleMap.values()].map(r => ({
|
|
573
|
+
id: r.id,
|
|
574
|
+
name: r.name,
|
|
575
|
+
shortDescription: { text: r.name },
|
|
576
|
+
fullDescription: { text: r.description },
|
|
577
|
+
helpUri: "https://guardvibe.dev",
|
|
578
|
+
}));
|
|
579
|
+
const sarif = {
|
|
580
|
+
$schema: "https://raw.githubusercontent.com/oasis-tcs/sarif-spec/main/sarif-2.1/schema/sarif-schema-2.1.0.json",
|
|
581
|
+
version: "2.1.0",
|
|
582
|
+
runs: [{
|
|
583
|
+
tool: {
|
|
584
|
+
driver: {
|
|
585
|
+
name: "GuardVibe",
|
|
586
|
+
version: _pkg.version,
|
|
587
|
+
informationUri: "https://guardvibe.dev",
|
|
588
|
+
rules: sarifRules,
|
|
589
|
+
},
|
|
590
|
+
},
|
|
591
|
+
results: sarifResults,
|
|
592
|
+
properties: {
|
|
593
|
+
verdict: result.verdict,
|
|
594
|
+
score: result.score,
|
|
595
|
+
grade: result.grade,
|
|
596
|
+
resultHash: result.resultHash,
|
|
597
|
+
},
|
|
598
|
+
}],
|
|
599
|
+
};
|
|
600
|
+
return JSON.stringify(sarif, null, 2);
|
|
601
|
+
}
|
|
525
602
|
export function formatAuditResult(result, format) {
|
|
603
|
+
if (format === "sarif") {
|
|
604
|
+
return formatAuditSarif(result);
|
|
605
|
+
}
|
|
526
606
|
if (format === "json") {
|
|
527
607
|
// Embed remediation plan directly in JSON when verdict is not PASS
|
|
528
608
|
if (result.verdict !== "PASS") {
|
package/build/utils/config.js
CHANGED
|
@@ -74,7 +74,13 @@ export function loadConfig(dir) {
|
|
|
74
74
|
} : undefined,
|
|
75
75
|
};
|
|
76
76
|
}
|
|
77
|
-
catch {
|
|
77
|
+
catch (err) {
|
|
78
|
+
// A .guardviberc exists but could not be parsed. Warn on stderr (never stdout —
|
|
79
|
+
// stdout must stay clean for MCP JSON-RPC and CLI machine formats) so the user
|
|
80
|
+
// knows their rule disables / authExceptions / scan.exclude are NOT being applied.
|
|
81
|
+
const reason = err instanceof Error ? err.message : String(err);
|
|
82
|
+
console.error(`[guardvibe] Warning: failed to parse ${configPath} — ${reason}. Using default config; your .guardviberc settings are NOT applied.`);
|
|
83
|
+
}
|
|
78
84
|
configCache.set(configDir, resolvedConfig);
|
|
79
85
|
return resolvedConfig;
|
|
80
86
|
}
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "guardvibe",
|
|
3
|
-
"version": "3.1.
|
|
3
|
+
"version": "3.1.27",
|
|
4
4
|
"mcpName": "io.github.goklab/guardvibe",
|
|
5
|
-
"description": "Security MCP for vibe coding.
|
|
5
|
+
"description": "Security MCP for vibe coding. 429 rules, 36 tools, CLI + doctor. Host security, auth coverage mapping, LLM-powered deep scan (IDOR/business logic), taint analysis. 63 CVE rules refreshed daily from GHSA/OSV/CISA KEV — 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",
|
|
7
7
|
"bin": {
|
|
8
8
|
"guardvibe": "build/cli.js",
|
|
@@ -108,7 +108,7 @@
|
|
|
108
108
|
"zod": "^3.25.0"
|
|
109
109
|
},
|
|
110
110
|
"overrides": {
|
|
111
|
-
"hono": "^4.12.
|
|
111
|
+
"hono": "^4.12.21",
|
|
112
112
|
"fast-uri": "^3.1.2",
|
|
113
113
|
"ip-address": "^10.2.0"
|
|
114
114
|
},
|