From 44183bc750fa42a89898c1edd56da9f8d77bcc43 Mon Sep 17 00:00:00 2001 From: Arnas Donauskas Date: Tue, 28 Jul 2026 13:07:09 +0300 Subject: [PATCH 1/3] fix(whatsapp): guard the template image-header fetch against SSRF MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `ensureImageHeaderHandle` fetched the caller-supplied `header_media_url` server-side with no validation, so a template submit — an action any authenticated member can perform — could reach loopback, RFC1918 and cloud-metadata addresses, with the response status and content-type echoed back through the thrown error. Wire in the project's existing `isDeliverableUrl` guard, which the two other outbound-fetch call sites (webhook delivery, automation `send_webhook`) already use, and reuse their `redirect: 'manual'` + timeout so a public URL can't 3xx-bounce to an internal one. The rejection reuses the unreachable-host message verbatim so the failure doesn't distinguish "blocked" from "down". Addresses GHSA-6fr5-pxw7-r3xw. Co-Authored-By: Claude Opus 5 --- .../whatsapp/template-header-handle.test.ts | 63 +++++++++++++++++++ src/lib/whatsapp/template-header-handle.ts | 19 +++++- 2 files changed, 81 insertions(+), 1 deletion(-) diff --git a/src/lib/whatsapp/template-header-handle.test.ts b/src/lib/whatsapp/template-header-handle.test.ts index f73af6d..4787291 100644 --- a/src/lib/whatsapp/template-header-handle.test.ts +++ b/src/lib/whatsapp/template-header-handle.test.ts @@ -5,8 +5,15 @@ vi.mock('./meta-api', () => ({ uploadResumableMedia: vi.fn(async () => ({ handle: 'HANDLE123' })), })); +// The SSRF guard does a real DNS lookup, so stub it — the fixtures below use +// a `.test` hostname that would never resolve. Each test sets the verdict. +vi.mock('@/lib/webhooks/ssrf', () => ({ + isDeliverableUrl: vi.fn(async () => true), +})); + import { ensureImageHeaderHandle } from './template-header-handle'; import { uploadResumableMedia } from './meta-api'; +import { isDeliverableUrl } from '@/lib/webhooks/ssrf'; import type { TemplatePayload } from './template-validators'; function payload(over: Partial = {}): TemplatePayload { @@ -33,6 +40,8 @@ function imgResponse(type = 'image/jpeg', size = 1024, ok = true, status = 200): describe('ensureImageHeaderHandle', () => { beforeEach(() => { vi.mocked(uploadResumableMedia).mockClear(); + vi.mocked(isDeliverableUrl).mockClear(); + vi.mocked(isDeliverableUrl).mockResolvedValue(true); }); afterEach(() => { vi.unstubAllGlobals(); @@ -78,4 +87,58 @@ describe('ensureImageHeaderHandle', () => { vi.stubGlobal('fetch', vi.fn(async () => imgResponse('image/png', 6 * 1024 * 1024))); await expect(ensureImageHeaderHandle(payload(), 'tok')).rejects.toThrow(/5 MB/); }); + + // Regression: `header_media_url` is caller-supplied and any authenticated + // member can submit a template, so a non-public destination has to be + // refused *before* the server issues the request — otherwise the status + // and content-type carried back in the thrown error are an SSRF oracle for + // loopback, RFC1918 and cloud-metadata addresses. + it('refuses a non-public header URL without fetching it', async () => { + vi.stubEnv('META_APP_ID', 'app-1'); + vi.mocked(isDeliverableUrl).mockResolvedValue(false); + const fetchSpy = vi.fn(async () => imgResponse('application/json')); + vi.stubGlobal('fetch', fetchSpy); + + const p = payload({ header_media_url: 'http://169.254.169.254/latest/meta-data/' }); + await expect(ensureImageHeaderHandle(p, 'tok')).rejects.toThrow(/publicly reachable/); + + expect(isDeliverableUrl).toHaveBeenCalledWith('http://169.254.169.254/latest/meta-data/'); + expect(fetchSpy).not.toHaveBeenCalled(); + expect(uploadResumableMedia).not.toHaveBeenCalled(); + expect(p.header_handle).toBeUndefined(); + }); + + it('reports a blocked URL exactly like an unreachable one', async () => { + vi.stubEnv('META_APP_ID', 'app-1'); + + vi.mocked(isDeliverableUrl).mockResolvedValue(false); + vi.stubGlobal('fetch', vi.fn(async () => imgResponse())); + const blocked = await ensureImageHeaderHandle(payload(), 'tok').catch( + (e: Error) => e.message, + ); + + vi.mocked(isDeliverableUrl).mockResolvedValue(true); + vi.stubGlobal( + 'fetch', + vi.fn(async () => { + throw new Error('ECONNREFUSED'); + }), + ); + const unreachable = await ensureImageHeaderHandle(payload(), 'tok').catch( + (e: Error) => e.message, + ); + + expect(blocked).toBe(unreachable); + }); + + it('does not follow redirects, so a public URL cannot bounce to an internal one', async () => { + vi.stubEnv('META_APP_ID', 'app-1'); + const fetchSpy = vi.fn(async () => imgResponse('image/jpeg', 1024)); + vi.stubGlobal('fetch', fetchSpy); + + await ensureImageHeaderHandle(payload(), 'tok'); + + const init = (fetchSpy.mock.calls[0] as unknown[])[1] as RequestInit; + expect(init).toMatchObject({ redirect: 'manual' }); + }); }); diff --git a/src/lib/whatsapp/template-header-handle.ts b/src/lib/whatsapp/template-header-handle.ts index eb05183..19722ad 100644 --- a/src/lib/whatsapp/template-header-handle.ts +++ b/src/lib/whatsapp/template-header-handle.ts @@ -1,5 +1,6 @@ import { uploadResumableMedia } from '@/lib/whatsapp/meta-api' import type { TemplatePayload } from '@/lib/whatsapp/template-validators' +import { isDeliverableUrl } from '@/lib/webhooks/ssrf' /** * Meta requires an `example.header_handle` (from the Resumable Upload @@ -33,11 +34,27 @@ export async function ensureImageHeaderHandle( ) } + // SSRF guard: `header_media_url` is caller-supplied (any authenticated + // member can submit a template) and the fetch below happens server-side, + // so refuse any destination that resolves to a private / loopback / + // link-local / reserved address. Same guard, same message as the two + // other outbound-fetch call sites (see lib/webhooks/ssrf.ts) — matching + // the unreachable-host message keeps the failure from being an oracle. + if (!(await isDeliverableUrl(payload.header_media_url))) { + throw new Error('Could not fetch the header image URL. Make sure it is publicly reachable.') + } + // Fetch the sample image bytes (works for our uploaded chat-media URL // and for a manually-pasted public link). let res: Response try { - res = await fetch(payload.header_media_url) + res = await fetch(payload.header_media_url, { + // Do NOT follow redirects — a public URL could 3xx-bounce to an + // internal address, defeating the guard above. Bound the request so + // a hung host can't tie up the template-submit handler. + redirect: 'manual', + signal: AbortSignal.timeout(10_000), + }) } catch { throw new Error('Could not fetch the header image URL. Make sure it is publicly reachable.') } From 6b4ddf6d6e2625b22d3b9e7f2f93062baaa6b643 Mon Sep 17 00:00:00 2001 From: Arnas Donauskas Date: Tue, 28 Jul 2026 13:11:24 +0300 Subject: [PATCH 2/3] chore(deps): bump next to 16.2.12 to clear 8 open security advisories MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 16.2.6 is in the vulnerable range for eight advisories, all patched in 16.2.11: SSRF in rewrites via an attacker-controlled destination hostname, SSRF in Server Actions on custom servers, middleware/proxy bypass in App Router, DoS in App Router Server Actions, DoS in the image optimizer via SVG, unauthenticated disclosure of internal Server Function endpoints, and two response-body cache-confusion issues. `eslint-config-next` moves with it to keep the pair on one version. Lockfile regenerated with npm 10 to match CI's Node 20 — the default npm 11 drops next-intl's nested optional-peer `@swc/helpers` entry and breaks `npm ci`. Verified: lint (39 warnings, unchanged from main), typecheck, 645 tests, and `next build` all pass on 16.2.12. Co-Authored-By: Claude Opus 5 --- package-lock.json | 96 +++++++++++++++++++++++------------------------ package.json | 4 +- 2 files changed, 50 insertions(+), 50 deletions(-) diff --git a/package-lock.json b/package-lock.json index 92ddfff..f1640c8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -21,7 +21,7 @@ "clsx": "^2.1.1", "date-fns": "^4.4.0", "lucide-react": "^1.22.0", - "next": "16.2.6", + "next": "16.2.12", "next-intl": "^4.13.2", "opus-recorder": "^8.0.5", "react": "19.2.4", @@ -38,7 +38,7 @@ "@types/react": "^19", "@types/react-dom": "^19", "eslint": "^9", - "eslint-config-next": "16.2.6", + "eslint-config-next": "16.2.12", "prettier": "^3.9.5", "prettier-plugin-tailwindcss": "^0.8.0", "tailwindcss": "^4", @@ -1698,15 +1698,15 @@ } }, "node_modules/@next/env": { - "version": "16.2.6", - "resolved": "https://registry.npmjs.org/@next/env/-/env-16.2.6.tgz", - "integrity": "sha512-gd8HoHN4ufj73WmR3JmVolrpJR47ILK6LouP5xElPglaVxir6e1a7VzvTvDWkOoPXT9rkkTzyCxBu4yeZfZwcw==", + "version": "16.2.12", + "resolved": "https://registry.npmjs.org/@next/env/-/env-16.2.12.tgz", + "integrity": "sha512-d0Z5Bc13Fa4nR8pFAKx2jay2yhJM16vlfHbTzYnUQAxlNb6B6lmn4hjt69lYNt4kRtyYP6gEM49lPRHNbIyneg==", "license": "MIT" }, "node_modules/@next/eslint-plugin-next": { - "version": "16.2.6", - "resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-16.2.6.tgz", - "integrity": "sha512-Z8l6o4JWKUl755x4R+wogD86KPeU+Ckw4K+SYG4kHeOJtRenDeK+OSbGcqZpDtbwn9DsJVdir2UxmwXuinUbUw==", + "version": "16.2.12", + "resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-16.2.12.tgz", + "integrity": "sha512-uF2z/qAK2q7B5/6CpnFcBRX6jOq5iCO+Uqh1UkJhXljX1JwLarLYhhoJadO6dPb6moTprOKewMXheBcbIoSbug==", "dev": true, "license": "MIT", "dependencies": { @@ -1714,9 +1714,9 @@ } }, "node_modules/@next/swc-darwin-arm64": { - "version": "16.2.6", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-16.2.6.tgz", - "integrity": "sha512-ZJGkkcNfYgrrMkqOdZ7zoLa1TOy0qpcMfk/z4Mh/FKUz40gVO+HNQWqmLxf67Z5WB64DRp0dhEbyHfel+6sJUg==", + "version": "16.2.12", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-16.2.12.tgz", + "integrity": "sha512-0W1R0teHWJrqKX0FH20IzzIWAOuGtBxPGuObrxy1lE8hQvCFj49KE8a3WUg0D7sq6rn6zkM4c7YGUnhudBS6oA==", "cpu": [ "arm64" ], @@ -1730,9 +1730,9 @@ } }, "node_modules/@next/swc-darwin-x64": { - "version": "16.2.6", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-16.2.6.tgz", - "integrity": "sha512-v/YLBHIY132Ced3puBJ7YJKw1lqsCrgcNo2aRJlCEyQrrCeRJlvGlnmxhPxNQI3KE3N1DN5r9TPNPvka3nq5RQ==", + "version": "16.2.12", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-16.2.12.tgz", + "integrity": "sha512-Hy5Ls099+aFUmOLmIgPfLqNi6iCwhL3uQCssz5rWk+5Nkc6TUKCE83DY5BbNylfm3+mfwcSFnLRfrZDJhVxdtw==", "cpu": [ "x64" ], @@ -1746,9 +1746,9 @@ } }, "node_modules/@next/swc-linux-arm64-gnu": { - "version": "16.2.6", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-16.2.6.tgz", - "integrity": "sha512-RPOvqlYBbcQjkz9VQQDZ2T2bARIjXZV1KFlt+V2Mr6SW/e4I9fcKsaA0hdyf2FHoTlsV2xnBd5Y912rP/1Ce6w==", + "version": "16.2.12", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-16.2.12.tgz", + "integrity": "sha512-+YqU2h1cQkHsGfvjAsrSmst8UIFBibBGm5x3Xgel8NLMiDQtNOM4sM2GOEMvG5YiOBNeN/Ykk8cQC2S0Xrqljg==", "cpu": [ "arm64" ], @@ -1762,9 +1762,9 @@ } }, "node_modules/@next/swc-linux-arm64-musl": { - "version": "16.2.6", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-16.2.6.tgz", - "integrity": "sha512-URUTu1+dMkxJsPFgm+OeEvq9wf5sujw0EvgYy80TDGHTSLTnIHeqb0Eu8A3sC95IRgjejQL+kC4mw+4yPxiAXA==", + "version": "16.2.12", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-16.2.12.tgz", + "integrity": "sha512-0qjhiYBaKAqF63LA1ZWAAnKTzFUguAaZiRa5etMLGGPj/B6uEVjtIZldIzFEp3wHlB0koK6aTzqPtSdplTCjoA==", "cpu": [ "arm64" ], @@ -1778,9 +1778,9 @@ } }, "node_modules/@next/swc-linux-x64-gnu": { - "version": "16.2.6", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-16.2.6.tgz", - "integrity": "sha512-DOj182mPV8G3UkrayLoREM5YEYI+Dk5wv7Ox9xl1fFibAELEsFD0lDPfHIeILlutMMfdyhlzYPELG3peuKaurw==", + "version": "16.2.12", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-16.2.12.tgz", + "integrity": "sha512-7A3q26W+h7gnA15uqBToNuDqBEFZZcqh0mW2mn4AJh/G5pdg2RVE3n4slzLEliASZFG3NmsbEzng/x2Sh09mBg==", "cpu": [ "x64" ], @@ -1794,9 +1794,9 @@ } }, "node_modules/@next/swc-linux-x64-musl": { - "version": "16.2.6", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-16.2.6.tgz", - "integrity": "sha512-HKQ5SP/V/ub73UvF7n/zeJlxk2kLmtL7Wzrg4WfmkjmNos5onJ2tKu7yZOPdL18A6Svfn3max29ym+ry7NkK4g==", + "version": "16.2.12", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-16.2.12.tgz", + "integrity": "sha512-qSjL/uppm+cbh21s72Ss8gkiOhQ4dExWHNGOWy6eZV7STj5WsKehgxT61beSsOj+YYQuTplL376lOCdMQU5T8w==", "cpu": [ "x64" ], @@ -1810,9 +1810,9 @@ } }, "node_modules/@next/swc-win32-arm64-msvc": { - "version": "16.2.6", - "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-16.2.6.tgz", - "integrity": "sha512-LZXpTlPyS5v7HhSmnvsLGP3iIYgYOBnc8r8ArlT55sGHV89bR2HlDdBjWQ+PY6SJMmk8TuVGFuxalnP3k/0Dwg==", + "version": "16.2.12", + "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-16.2.12.tgz", + "integrity": "sha512-X6hzsOUJac/e7AWSbn9gQ9nzHld1xWP5iyjHpYWvud8pufB679O1xg4JDyKr8Xd69Jvd+kM2Der6uftiZCmjYA==", "cpu": [ "arm64" ], @@ -1826,9 +1826,9 @@ } }, "node_modules/@next/swc-win32-x64-msvc": { - "version": "16.2.6", - "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-16.2.6.tgz", - "integrity": "sha512-F0+4i0h9J6C4eE3EAPWsoCk7UW/dbzOjyzxY0qnDUOYFu6FFmdZ6l97/XdV3/Nz3VYyO7UWjyEJUXkGqcoXfMA==", + "version": "16.2.12", + "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-16.2.12.tgz", + "integrity": "sha512-F6fakeHuFTLOPt0bslQJdf+xtT+WIP9DVn/m4y1w1mRnVPyh3D/cNvzlRkxM444xfm+IvvYNSOrKiA2CDJ0Uxw==", "cpu": [ "x64" ], @@ -5889,13 +5889,13 @@ } }, "node_modules/eslint-config-next": { - "version": "16.2.6", - "resolved": "https://registry.npmjs.org/eslint-config-next/-/eslint-config-next-16.2.6.tgz", - "integrity": "sha512-z2ELYSkyrrJ6cuunTU8vhsT/RpouPkjaSah06nVW6Rg2Hpg0Vs8s497/e5s8G8qtdp4ccsiovz5P1rv+5VSW2Q==", + "version": "16.2.12", + "resolved": "https://registry.npmjs.org/eslint-config-next/-/eslint-config-next-16.2.12.tgz", + "integrity": "sha512-iaaf4vvKo5h2LBdGt0JuRv7t0Ysqr9FMCiFxbptDg8LqOE//mIKR80DdpOnSVM7qjLH3jT8P0aFiwXxBEGZRXw==", "dev": true, "license": "MIT", "dependencies": { - "@next/eslint-plugin-next": "16.2.6", + "@next/eslint-plugin-next": "16.2.12", "eslint-import-resolver-node": "^0.3.6", "eslint-import-resolver-typescript": "^3.5.2", "eslint-plugin-import": "^2.32.0", @@ -8531,12 +8531,12 @@ } }, "node_modules/next": { - "version": "16.2.6", - "resolved": "https://registry.npmjs.org/next/-/next-16.2.6.tgz", - "integrity": "sha512-qOVgKJg1+At15NpeUP+eJgCHvTCgXsogweq87Ri/Ix7PkqQHg4sdaXmSFqKlgaIXE4kW0g25LE68W87UANlHtw==", + "version": "16.2.12", + "resolved": "https://registry.npmjs.org/next/-/next-16.2.12.tgz", + "integrity": "sha512-iD59eYQWmbFcEbX7v/acG5DRym9iw1DdaPoD0WTA920naWsE25wShzJW4+UvAs8MK9EC2kBfIH6vtto1H1PHGw==", "license": "MIT", "dependencies": { - "@next/env": "16.2.6", + "@next/env": "16.2.12", "@swc/helpers": "0.5.15", "baseline-browser-mapping": "^2.9.19", "caniuse-lite": "^1.0.30001579", @@ -8550,14 +8550,14 @@ "node": ">=20.9.0" }, "optionalDependencies": { - "@next/swc-darwin-arm64": "16.2.6", - "@next/swc-darwin-x64": "16.2.6", - "@next/swc-linux-arm64-gnu": "16.2.6", - "@next/swc-linux-arm64-musl": "16.2.6", - "@next/swc-linux-x64-gnu": "16.2.6", - "@next/swc-linux-x64-musl": "16.2.6", - "@next/swc-win32-arm64-msvc": "16.2.6", - "@next/swc-win32-x64-msvc": "16.2.6", + "@next/swc-darwin-arm64": "16.2.12", + "@next/swc-darwin-x64": "16.2.12", + "@next/swc-linux-arm64-gnu": "16.2.12", + "@next/swc-linux-arm64-musl": "16.2.12", + "@next/swc-linux-x64-gnu": "16.2.12", + "@next/swc-linux-x64-musl": "16.2.12", + "@next/swc-win32-arm64-msvc": "16.2.12", + "@next/swc-win32-x64-msvc": "16.2.12", "sharp": "^0.34.5" }, "peerDependencies": { diff --git a/package.json b/package.json index 07be10b..2b4e32d 100644 --- a/package.json +++ b/package.json @@ -51,7 +51,7 @@ "clsx": "^2.1.1", "date-fns": "^4.4.0", "lucide-react": "^1.22.0", - "next": "16.2.6", + "next": "16.2.12", "next-intl": "^4.13.2", "opus-recorder": "^8.0.5", "react": "19.2.4", @@ -68,7 +68,7 @@ "@types/react": "^19", "@types/react-dom": "^19", "eslint": "^9", - "eslint-config-next": "16.2.6", + "eslint-config-next": "16.2.12", "prettier": "^3.9.5", "prettier-plugin-tailwindcss": "^0.8.0", "tailwindcss": "^4", From b751581bf4c0ca58998df0c7a8c9a6b19879f272 Mon Sep 17 00:00:00 2001 From: Arnas Donauskas Date: Tue, 28 Jul 2026 13:12:55 +0300 Subject: [PATCH 3/3] chore(deps): audit-fix transitive deps to clear 7 open advisories MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Lockfile-only bumps of indirect dependencies flagged by Dependabot; no direct dependency or `package.json` entry changes. - fast-uri 3.1.3 → 3.1.4 (two host-confusion advisories, high) - js-yaml → 4.3.0 (quadratic CPU via YAML merge-key chains, high) - hono → 4.12.32 and @hono/node-server → 2.0.12 (cross-request context disclosure in hono/jsx, serve-static path traversal on Windows) - body-parser → 2.3.0 (size enforcement silently disabled on an invalid limit value) - postcss → 8.5.24 Regenerated with npm 10 to match CI's Node 20, so the nested `@swc/helpers` optional-peer entry `npm ci` needs is preserved. Verified: `npm ci`, lint (39 warnings, unchanged from main), typecheck, 645 tests, and `next build` all pass. Still open after this, and deliberately left alone: `next` (needs a direct bump — separate branch), `sharp` (major, `--force` only), and `brace-expansion` nested under the dev-only `@ts-morph/common`. Co-Authored-By: Claude Opus 5 --- package-lock.json | 128 ++++++++++++++++++++++++++++------------------ 1 file changed, 79 insertions(+), 49 deletions(-) diff --git a/package-lock.json b/package-lock.json index 92ddfff..b9dd905 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1048,12 +1048,12 @@ } }, "node_modules/@hono/node-server": { - "version": "1.19.14", - "resolved": "https://registry.npmjs.org/@hono/node-server/-/node-server-1.19.14.tgz", - "integrity": "sha512-GwtvgtXxnWsucXvbQXkRgqksiH2Qed37H9xHZocE5sA3N8O8O8/8FA3uclQXxXVzc9XBZuEOMK7+r02FmSpHtw==", + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/@hono/node-server/-/node-server-2.0.12.tgz", + "integrity": "sha512-eWpQYr67tqJLeaSUl0Q+TquuYfUdTibpOJlUMV2FfUP7+KqCC5TufnwnlXL6mobZBJbGAYRd7ZvEBDCbLInjhg==", "license": "MIT", "engines": { - "node": ">=18.14.1" + "node": ">=20" }, "peerDependencies": { "hono": "^4" @@ -1623,12 +1623,12 @@ } }, "node_modules/@modelcontextprotocol/sdk": { - "version": "1.29.0", - "resolved": "https://registry.npmjs.org/@modelcontextprotocol/sdk/-/sdk-1.29.0.tgz", - "integrity": "sha512-zo37mZA9hJWpULgkRpowewez1y6ML5GsXJPY8FI0tBBCd77HEvza4jDqRKOXgHNn867PVGCyTdzqpz0izu5ZjQ==", + "version": "1.30.0", + "resolved": "https://registry.npmjs.org/@modelcontextprotocol/sdk/-/sdk-1.30.0.tgz", + "integrity": "sha512-xKd8OIzlqNzcqcNumGAa6g+PW2kjD5vrpcKOnfldAUPP3j7lnqMPwlTXQm8gF+UwH72z0lqaRbjr9hqGz0eITA==", "license": "MIT", "dependencies": { - "@hono/node-server": "^1.19.9", + "@hono/node-server": "^1.19.9 || ^2.0.5", "ajv": "^8.17.1", "ajv-formats": "^3.0.1", "content-type": "^1.0.5", @@ -3277,15 +3277,15 @@ } }, "node_modules/@ts-morph/common/node_modules/brace-expansion": { - "version": "5.0.6", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.6.tgz", - "integrity": "sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g==", + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.8.tgz", + "integrity": "sha512-JZyDyq3D4AUifKTPOB7DELf6XsB3WdPuNxCtob1vFXPsSXhdAiHBWJ/tJ8HAc9aH84BK+5JFZLNkJKx3G9kzQg==", "license": "MIT", "dependencies": { "balanced-match": "^4.0.2" }, "engines": { - "node": "18 || 20 || >=22" + "node": "20 || >=22" } }, "node_modules/@ts-morph/common/node_modules/fast-glob": { @@ -3719,16 +3719,16 @@ } }, "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { - "version": "5.0.6", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.6.tgz", - "integrity": "sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g==", + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.8.tgz", + "integrity": "sha512-JZyDyq3D4AUifKTPOB7DELf6XsB3WdPuNxCtob1vFXPsSXhdAiHBWJ/tJ8HAc9aH84BK+5JFZLNkJKx3G9kzQg==", "dev": true, "license": "MIT", "dependencies": { "balanced-match": "^4.0.2" }, "engines": { - "node": "18 || 20 || >=22" + "node": "20 || >=22" } }, "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { @@ -4639,20 +4639,20 @@ } }, "node_modules/body-parser": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.2.tgz", - "integrity": "sha512-oP5VkATKlNwcgvxi0vM0p/D3n2C3EReYVX+DNYs5TjZFn/oQt2j+4sVJtSMr18pdRr8wjTcBl6LoV+FUwzPmNA==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.3.0.tgz", + "integrity": "sha512-2cGmJupaNgg+QUwVLAucDuWuoMZ6EX9iHDRswZ5lsNYEmwPaRknMPCLZz07yTzVq/83p4o/wzbDZbBrTvGGTIw==", "license": "MIT", "dependencies": { "bytes": "^3.1.2", - "content-type": "^1.0.5", + "content-type": "^2.0.0", "debug": "^4.4.3", - "http-errors": "^2.0.0", - "iconv-lite": "^0.7.0", + "http-errors": "^2.0.1", + "iconv-lite": "^0.7.2", "on-finished": "^2.4.1", - "qs": "^6.14.1", - "raw-body": "^3.0.1", - "type-is": "^2.0.1" + "qs": "^6.15.2", + "raw-body": "^3.0.2", + "type-is": "^2.1.0" }, "engines": { "node": ">=18" @@ -4662,10 +4662,23 @@ "url": "https://opencollective.com/express" } }, + "node_modules/body-parser/node_modules/content-type": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-2.0.0.tgz", + "integrity": "sha512-j/O/d7GcZCyNl7/hwZAb606rzqkyvaDctLmckbxLzHvFBzTJHuGEdodATcP3yIRoDrLHkIATJuvzbFlp/ki2cQ==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, "node_modules/brace-expansion": { - "version": "1.1.15", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.15.tgz", - "integrity": "sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg==", + "version": "1.1.16", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.16.tgz", + "integrity": "sha512-IDw48K2/2kRkg9LdJxurvq3lV3aBgq0REY89duEqFRthjlPdXHKMj7EnQOXVckxzgisinf3nHfrcE2FufFLXMw==", "dev": true, "license": "MIT", "dependencies": { @@ -6441,9 +6454,9 @@ "license": "MIT" }, "node_modules/fast-uri": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.2.tgz", - "integrity": "sha512-rVjf7ArG3LTk+FS6Yw81V1DLuZl1bRbNrev6Tmd/9RaroeeRRJhAt7jg/6YFxbvAQXUCavSoZhPPj6oOx+5KjQ==", + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.4.tgz", + "integrity": "sha512-8JnbkQ4juDyvYs4mgFGQqg4yCYtFDtUtmp2QIQq11ZZe5CFQ5wcqm1rqDgAh/QdMySuBnPzMUiJUNZG5N/AiQw==", "funding": [ { "type": "github", @@ -7006,9 +7019,9 @@ } }, "node_modules/hono": { - "version": "4.12.26", - "resolved": "https://registry.npmjs.org/hono/-/hono-4.12.26.tgz", - "integrity": "sha512-uyZtpnYxM9CmQ7QsQknM4zN8EftNqhON1qYeIKM0Se67CCEe2c44xyGURwB0axX2fBDu1dqHrHAc1hmNT8ITkw==", + "version": "4.12.32", + "resolved": "https://registry.npmjs.org/hono/-/hono-4.12.32.tgz", + "integrity": "sha512-XcuyW9qE2kJn07PkecMOBd5Vq/hMy7mmGw+idz1yblbg9N17ijJODrvPkn7/dwL3Kulj8LcRJ69DLOWf91dRUg==", "license": "MIT", "engines": { "node": ">=16.9.0" @@ -7818,9 +7831,9 @@ "license": "MIT" }, "node_modules/js-yaml": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.2.0.tgz", - "integrity": "sha512-ePWsvanv0DWuDRsW8dnt+R4jQ31SCRCQ7hhNcPXZPsoBZiemuZNYGf7adZdqX2D86j6rvKp3RpCxVTSb8WQlOw==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.3.0.tgz", + "integrity": "sha512-1td788aAnnZ5qs7V2QIRl1owjtYpbKt749Y3xauqQgwIIGF/xXWz1wMTEBx5O3LK3lXLVuqXPdPxj2BoFHaW9Q==", "funding": [ { "type": "github", @@ -8481,9 +8494,9 @@ "license": "MIT" }, "node_modules/nanoid": { - "version": "3.3.11", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", - "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", + "version": "3.3.16", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.16.tgz", + "integrity": "sha512-bzlKTyNJ7+LdGIIwy8ijFpIqEQIvafahV7eYykJ8Cvh42EdJeODoJ6gUJXpQJvej1BddH8OqTXZNE/KfbWAu8Q==", "funding": [ { "type": "github", @@ -9208,9 +9221,9 @@ } }, "node_modules/postcss": { - "version": "8.5.14", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.14.tgz", - "integrity": "sha512-SoSL4+OSEtR99LHFZQiJLkT59C5B1amGO1NzTwj7TT1qCUgUO6hxOvzkOYxD+vMrXBM3XJIKzokoERdqQq/Zmg==", + "version": "8.5.24", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.24.tgz", + "integrity": "sha512-8RyVklq0owXUTa4xlpzu4l9AaVKIdQvAcOHZWaMh98HgySsUtxRVf/chRe3dsSLqb6i40BzGRzEUddRaI+9TSw==", "funding": [ { "type": "opencollective", @@ -9227,7 +9240,7 @@ ], "license": "MIT", "dependencies": { - "nanoid": "^3.3.11", + "nanoid": "^3.3.16", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" }, @@ -10823,17 +10836,34 @@ } }, "node_modules/type-is": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-2.0.1.tgz", - "integrity": "sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-2.1.0.tgz", + "integrity": "sha512-faYHw0anBbc/kWF3zFTEnxSFOAGUX9GFbOBthvDdLsIlEoWOFOtS0zgCiQYwIskL9iGXZL3kAXD8OoZ4GmMATA==", "license": "MIT", "dependencies": { - "content-type": "^1.0.5", + "content-type": "^2.0.0", "media-typer": "^1.1.0", "mime-types": "^3.0.0" }, "engines": { - "node": ">= 0.6" + "node": ">= 18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/type-is/node_modules/content-type": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-2.0.0.tgz", + "integrity": "sha512-j/O/d7GcZCyNl7/hwZAb606rzqkyvaDctLmckbxLzHvFBzTJHuGEdodATcP3yIRoDrLHkIATJuvzbFlp/ki2cQ==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, "node_modules/typed-array-buffer": {