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 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
  [![npm provenance](https://img.shields.io/badge/provenance-verified-brightgreen)](https://www.npmjs.com/package/guardvibe)
7
7
  [![codecov](https://codecov.io/gh/goklab/guardvibe/graph/badge.svg)](https://codecov.io/gh/goklab/guardvibe)
8
8
 
9
- **The security MCP built for vibe coding.** 422 security rules, 36 tools covering the entire AI-generated code journey — from first line to production deployment.
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
- - **422 security rules, 36 tools** purpose-built for the stacks AI agents generate
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 60 known vulnerable package versions in package.json, refreshed every day from GHSA / OSV.dev / CISA KEV
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.23 alone added 22 new CVE / supply-chain / AI-runtime rules covering the 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
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 | 60 packages, refreshed daily | Extensive | Extensive |
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 | 422 (focused, 68 AI-native) | 5000+ (broad) | N/A |
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 (60 CVEs, refreshed daily)
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 (390 rules across 25 modules)
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.3`) at init time for fast deterministic startup. As of v3.1.2 the re-run also rewrites stale pins automatically (`Upgraded GuardVibe pin (3.0.55 → 3.1.3)`). 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.
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.
@@ -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
- const full = flags["full"] === true;
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 (424 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: '.'})", {
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
- * Format audit result as markdown, JSON, or terminal-friendly output.
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 formatAuditResult(result: AuditResult, format: "markdown" | "json" | "terminal"): string;
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 : 424;
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") {
@@ -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.25",
3
+ "version": "3.1.27",
4
4
  "mcpName": "io.github.goklab/guardvibe",
5
- "description": "Security MCP for vibe coding. 424 rules, 36 tools, CLI + doctor. Host security, auth coverage mapping, LLM-powered deep scan (IDOR/business logic), taint analysis. 61 CVE rules refreshed daily from GHSA/OSV/CISA KEV — Next.js May 2026 13-advisory cluster, Drizzle/MikroORM/Kysely SQL 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), and CI/CD supply-chain hardening (VG1070 npm --expect-provenance / --ignore-scripts enforcement).",
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.18",
111
+ "hono": "^4.12.21",
112
112
  "fast-uri": "^3.1.2",
113
113
  "ip-address": "^10.2.0"
114
114
  },