diff --git a/.changeset/fix-create-sei-next-sharp-october-advisories.md b/.changeset/fix-create-sei-next-sharp-october-advisories.md index 5736c51a..4d253957 100644 --- a/.changeset/fix-create-sei-next-sharp-october-advisories.md +++ b/.changeset/fix-create-sei-next-sharp-october-advisories.md @@ -15,4 +15,7 @@ Five advisories landed against the pinned `next@15.5.25` and the `sharp@0.35.4` Next 15.5.28 declares Sharp `^0.34.3 || ^0.35.5`, so the override stays inside the range Next supports. The image notes in the template README and `next.config.mjs` now name `0.35.5` as the advisory floor, because the `0.34.x` half of Next's range is inside both Sharp advisories. -The remaining `decode-uri-component` finding is moderate and does not block the smoke. +Generated apps still report two advisories on install: + +- `GHSA-mrhx-c7xc-m3w5` — high, memory exhaustion in Zod's array validation, `<4.6.6`. It reaches every generated app through the `zod@3.22.4` that `@reown/appkit-wallet` pins exactly under wagmi's WalletConnect connector, and Reown's newest release, 1.8.24, still pins it. Zod published no fixed 3.x release, so the only override would move Reown onto Zod 4, a major it does not declare support for. +- `GHSA-vcc3-ghjq-m6fr` — moderate, denial of service in `decode-uri-component`, `<=0.4.2`. diff --git a/.changeset/fix-global-wallet-zod-override.md b/.changeset/fix-global-wallet-zod-override.md new file mode 100644 index 00000000..9f120db2 --- /dev/null +++ b/.changeset/fix-global-wallet-zod-override.md @@ -0,0 +1,11 @@ +--- +'@sei-js/sei-global-wallet': patch +--- + +Add `"zod": "4.6.7"` to the documented consumer overrides, clearing `GHSA-mrhx-c7xc-m3w5` on the wallet path. + +`GHSA-mrhx-c7xc-m3w5` (high, CVSS 7.5) covers Zod's array validation: an array schema without a length constraint records an issue for every failing element, so one large array can exhaust memory. It was published on October 1, and since its October 23 update it reports the `zod@4.0.5` that `@dynamic-labs-sdk/client` and `@dynamic-labs/wallet-book` pin exactly. The newest `@dynamic-labs-sdk/client`, 1.45.0, still pins it. The wallet-only npm consumer, which is held to a strictly clean audit, reported `zod` plus the eight packages above it in the dependency chain, so the consumer smoke failed without any change in this repository. + +All three [Required consumer overrides](https://github.com/sei-protocol/sei-js/blob/main/packages/sei-global-wallet/README.md#required-consumer-overrides) blocks now carry `"zod": "4.6.7"`, a minor-level move inside Zod 4. Nothing else in the wallet's dependency graph, including the optional AA path, needs Zod 3, so the override is safe as one of Bun's global overrides. Applications with a Zod 3 dependency of their own, such as the one wagmi's WalletConnect connector installs, can scope the override on npm instead, as the README describes. + +No published dependency or peer range changes. diff --git a/.changeset/fix-mcp-server-brotli-node-floor.md b/.changeset/fix-mcp-server-brotli-node-floor.md index 1eeb991f..198d475c 100644 --- a/.changeset/fix-mcp-server-brotli-node-floor.md +++ b/.changeset/fix-mcp-server-brotli-node-floor.md @@ -8,7 +8,7 @@ Raise the supported Node.js range to the releases that patch the Brotli decoder Node.js bundles Google's Brotli library, and the decoder in Brotli 1.0.3 through 1.2.0 can be driven into an out-of-bounds write by a crafted compressed stream. Node fixed it in the [October 21, 2026 security releases](https://nodejs.org/en/blog/vulnerability/october-2026-security-releases): 22.23.4, 24.22.1, and 26.12.1. Node 20 is end-of-life and gets no fix. -The server reaches that decoder through `fetch`, which decompresses Brotli-encoded responses automatically: viem's HTTP transport for the configured RPC endpoints, and the docs client for `https://docs.sei.io/mcp`. Its own HTTP transports do not, because Express 4's body parser only inflates gzip and deflate request bodies and rejects `Content-Encoding: br` with a 415. +The server reaches that decoder through `fetch`, which decompresses Brotli-encoded responses automatically: viem's HTTP transport for the configured RPC endpoints, and the docs client for `https://docs.sei.io/mcp`. Its own HTTP transports do not, because they reject every compressed request body with a 415. `engines.node` moves from `>=20.0.0` to `^22.23.4 || ^24.22.1 || >=26.12.1`, and the README's requirement matches. diff --git a/.changeset/fix-mcp-server-reject-compressed-bodies.md b/.changeset/fix-mcp-server-reject-compressed-bodies.md new file mode 100644 index 00000000..f7d69309 --- /dev/null +++ b/.changeset/fix-mcp-server-reject-compressed-bodies.md @@ -0,0 +1,9 @@ +--- +'@sei-js/mcp-server': patch +--- + +Reject compressed request bodies on the `streamable-http` and `http-sse` transports, the documented workaround for the `body-parser` advisory `GHSA-27r3-jxmh-p828`. + +`GHSA-27r3-jxmh-p828` (high, CVSS 7.5, published October 23) covers `body-parser` below `1.20.9`, and `2.x` below `2.4.0`. With default options, `body-parser` pipes a request that carries a `Content-Encoding` into a decompression stream and leaves that stream without an error listener, so a compressed frame followed by trailing bytes can raise an uncaught exception that terminates the process. Parsing runs before routing, so the request needs no valid session or route. Both HTTP transports parse JSON with Express 4's `express.json()`. + +A fresh install resolves the fixed `body-parser@1.20.9`, but Express 4 accepts `~1.20.5`, so no dependency floor in this package can move an existing lockfile off a vulnerable copy. Both transports now pass `inflate: false`, so a request body with any `Content-Encoding` other than `identity` gets a 415 before a decompression stream exists, whichever `body-parser` is installed. The SDK's HTTP client transports send uncompressed JSON, and stdio is not affected. diff --git a/.changeset/fix-mcp-server-sdk-zod-floors.md b/.changeset/fix-mcp-server-sdk-zod-floors.md new file mode 100644 index 00000000..0f6428e1 --- /dev/null +++ b/.changeset/fix-mcp-server-sdk-zod-floors.md @@ -0,0 +1,15 @@ +--- +'@sei-js/mcp-server': patch +--- + +Raise the `@modelcontextprotocol/sdk` floor from `^1.23.0` to `^1.32.0` and the `zod` floor from `^4.0.5` to `^4.6.6`, so an in-place upgrade cannot keep a release inside their advisories. + +A fresh install already resolved fixed releases of both, but the old floors let an existing lockfile keep vulnerable ones. Three of the advisories reach this server: + +- `GHSA-46jr-4wx8-v453` — high, `@modelcontextprotocol/sdk` `>=1.3.0 <1.32.0`. The SDK put no limit on how many array elements and object keys it validated in one request, so one unauthenticated HTTP request could exhaust the server's memory. It affects the `streamable-http` and `http-sse` transports; stdio is not affected. +- `GHSA-mrhx-c7xc-m3w5` — high, `zod` `<4.6.6`. An array schema without a length constraint records an issue for every failing element, so one large array can exhaust memory. Tool arguments are validated with Zod. +- `GHSA-6prh-2h8m-c8cw` — moderate, `@modelcontextprotocol/sdk` `<1.32.0`. The SDK's HTTP client transports followed redirects to any origin and re-sent the `mcp-session-id` header, and on a `307` or `308` the request body. The docs client reaches `https://docs.sei.io/mcp` through `StreamableHTTPClientTransport`. + +The other three SDK advisories fixed in 1.31.0 and 1.32.0 do not reach it: the server passes no `taskStore` (`GHSA-22jm-h49p-29qw`), uses no SDK OAuth client (`GHSA-6qxp-vccf-f47h`), and does not use `requireBearerAuth()` (`GHSA-rvq5-wwqv-78pq`). + +No other dependency changes. diff --git a/bun.lock b/bun.lock index 90986f66..daee23cf 100644 --- a/bun.lock +++ b/bun.lock @@ -35,14 +35,14 @@ "version": "1.0.1", "bin": "./bin/mcp-server.js", "dependencies": { - "@modelcontextprotocol/sdk": "^1.23.0", + "@modelcontextprotocol/sdk": "^1.32.0", "@noble/hashes": "^1.8.0", "commander": "^14.0.0", "cors": "^2.8.5", "dotenv": "^16.5.0", "express": "^4.21.2", "viem": "2.55.16", - "zod": "^4.0.5", + "zod": "^4.6.6", }, "devDependencies": { "@types/cors": "^2.8.17", @@ -116,6 +116,7 @@ "overrides": { "axios": "1.20.0", "uuid": "11.1.1", + "zod": "4.6.7", }, "packages": { "@ably/msgpack-js": ["@ably/msgpack-js@0.4.1", "", { "dependencies": { "bops": "^1.0.1" } }, "sha512-Sjxj6SOr17hExAVrsycN7u6oV4PhZcK7Z2S8dM71CH/butgO47cSo/TL6FJPCXUyDAzKkOWjMUpJGyZkEpyu4Q=="], @@ -358,7 +359,7 @@ "@manypkg/get-packages": ["@manypkg/get-packages@1.1.3", "", { "dependencies": { "@babel/runtime": "^7.5.5", "@changesets/types": "^4.0.1", "@manypkg/find-root": "^1.1.0", "fs-extra": "^8.1.0", "globby": "^11.0.0", "read-yaml-file": "^1.1.0" } }, "sha512-fo+QhuU3qE/2TQMQmbVMqaQ6EWbMhi4ABWP+O4AM1NqPBuy0OrApV5LO6BrrgnhtAHS2NH6RrVk9OL181tTi8A=="], - "@modelcontextprotocol/sdk": ["@modelcontextprotocol/sdk@1.30.0", "", { "dependencies": { "@hono/node-server": "^1.19.9 || ^2.0.5", "ajv": "^8.17.1", "ajv-formats": "^3.0.1", "content-type": "^1.0.5", "cors": "^2.8.5", "cross-spawn": "^7.0.5", "eventsource": "^3.0.2", "eventsource-parser": "^3.0.0", "express": "^5.2.1", "express-rate-limit": "^8.2.1", "hono": "^4.11.4", "jose": "^6.1.3", "json-schema-typed": "^8.0.2", "pkce-challenge": "^5.0.0", "raw-body": "^3.0.0", "zod": "^3.25 || ^4.0", "zod-to-json-schema": "^3.25.1" }, "peerDependencies": { "@cfworker/json-schema": "^4.1.1" }, "optionalPeers": ["@cfworker/json-schema"] }, "sha512-xKd8OIzlqNzcqcNumGAa6g+PW2kjD5vrpcKOnfldAUPP3j7lnqMPwlTXQm8gF+UwH72z0lqaRbjr9hqGz0eITA=="], + "@modelcontextprotocol/sdk": ["@modelcontextprotocol/sdk@1.32.2", "", { "dependencies": { "@hono/node-server": "^1.19.9 || ^2.0.5", "ajv": "^8.17.1", "ajv-formats": "^3.0.1", "content-type": "^1.0.5", "cors": "^2.8.5", "cross-spawn": "^7.0.5", "eventsource": "^3.0.2", "eventsource-parser": "^3.0.0", "express": "^5.2.1", "express-rate-limit": "^8.2.1", "hono": "^4.11.4", "jose": "^6.1.3", "json-schema-typed": "^8.0.2", "pkce-challenge": "^5.0.0", "raw-body": "^3.0.0", "zod": "^3.25 || ^4.0", "zod-to-json-schema": "^3.25.1" }, "peerDependencies": { "@cfworker/json-schema": "^4.1.1" }, "optionalPeers": ["@cfworker/json-schema"] }, "sha512-SWsVtH/0vULSQStoZ6xxH2K09Li8fXYTMC64ZeogCdpZ3XSi1eCPOByV1OpuJxuI3OcmHhosDWYyii07tpPsLw=="], "@noble/ciphers": ["@noble/ciphers@1.3.0", "", {}, "sha512-2I0gnIVPtfnMw9ee9h1dJG7tp81+8Ob3OJb3Mv37rx5L40/b0i7djjCVvGOVqc9AEIQyvyu1i6ypKdFw8R8gQw=="], @@ -1186,7 +1187,7 @@ "zksync-sso": ["zksync-sso@0.2.0", "", { "dependencies": { "@peculiar/asn1-ecc": "^2.3.13", "@peculiar/asn1-schema": "^2.3.13", "abitype": "^1.0.6", "bigint-conversion": "^2.4.3", "buffer": "^6.0.3", "ms": "^2.1.3" }, "peerDependencies": { "@simplewebauthn/browser": "13.x", "@simplewebauthn/server": "13.x", "@wagmi/core": "2.x", "typescript": "*" }, "optionalPeers": ["typescript"] }, "sha512-JyxmYx2KnreTEQANyihkhzQGqA0Opa0j1qT6BLBmjP8WOwsYEiOMolbwxNK7X/KETXI77IZhGxWl8ZMKQgYl8A=="], - "zod": ["zod@4.0.5", "", {}, "sha512-/5UuuRPStvHXu7RS+gmvRf4NXrNxpSllGwDnCBcJZtQsKrviYXm54yDGV2KYNLT5kq0lHGcl7lqWJLgSaG+tgA=="], + "zod": ["zod@4.6.7", "", {}, "sha512-g8W2D2kU6a8untc053fX1uVBKzM7yqAxW/3zwk83+6RyF2+SKOuV+c0wBDhUwzV1PaGapmZH+rmcUzPf+3CGwg=="], "zod-to-json-schema": ["zod-to-json-schema@3.25.2", "", { "peerDependencies": { "zod": "^3.25.28 || ^4" } }, "sha512-O/PgfnpT1xKSDeQYSCfRI5Gy3hPf91mKVDuYLUHZJMiDFptvP41MSnWofm8dnCm0256ZNfZIM7DSzuSMAFnjHA=="], diff --git a/package.json b/package.json index 3806ce0b..5caa56b1 100644 --- a/package.json +++ b/package.json @@ -8,7 +8,8 @@ ], "overrides": { "axios": "1.20.0", - "uuid": "11.1.1" + "uuid": "11.1.1", + "zod": "4.6.7" }, "scripts": { "build": "bun run --filter '*' build", diff --git a/packages/mcp-server/package.json b/packages/mcp-server/package.json index ef99b637..3ba3cb9b 100644 --- a/packages/mcp-server/package.json +++ b/packages/mcp-server/package.json @@ -33,14 +33,14 @@ "typescript": "^5.8.3" }, "dependencies": { - "@modelcontextprotocol/sdk": "^1.23.0", + "@modelcontextprotocol/sdk": "^1.32.0", "@noble/hashes": "^1.8.0", "commander": "^14.0.0", "cors": "^2.8.5", "dotenv": "^16.5.0", "express": "^4.21.2", "viem": "2.55.16", - "zod": "^4.0.5" + "zod": "^4.6.6" }, "keywords": [ "mcp", diff --git a/packages/mcp-server/src/server/transport/http-sse.ts b/packages/mcp-server/src/server/transport/http-sse.ts index 343f38ba..7accbfdb 100644 --- a/packages/mcp-server/src/server/transport/http-sse.ts +++ b/packages/mcp-server/src/server/transport/http-sse.ts @@ -76,7 +76,8 @@ export class HttpSseTransport implements McpTransport { } private setupMiddleware(): void { - this.app.use(express.json()); + // No compressed request bodies: body-parser's decoder can crash the process (GHSA-27r3-jxmh-p828). + this.app.use(express.json({ inflate: false })); this.app.use(createCorsMiddleware()); } diff --git a/packages/mcp-server/src/server/transport/streamable-http.ts b/packages/mcp-server/src/server/transport/streamable-http.ts index bb012a1f..7f0735ae 100644 --- a/packages/mcp-server/src/server/transport/streamable-http.ts +++ b/packages/mcp-server/src/server/transport/streamable-http.ts @@ -117,7 +117,8 @@ export class StreamableHttpTransport implements McpTransport { this.state = 'starting'; this.app = express(); - this.app.use(express.json()); + // No compressed request bodies: body-parser's decoder can crash the process (GHSA-27r3-jxmh-p828). + this.app.use(express.json({ inflate: false })); this.app.use(createCorsMiddleware()); this.app.get('/health', (_req: Request, res: Response) => { diff --git a/packages/mcp-server/src/tests/server/transport/http-sse.test.ts b/packages/mcp-server/src/tests/server/transport/http-sse.test.ts index 9c979bc0..34c413f8 100644 --- a/packages/mcp-server/src/tests/server/transport/http-sse.test.ts +++ b/packages/mcp-server/src/tests/server/transport/http-sse.test.ts @@ -1,6 +1,7 @@ import { afterEach, describe, expect, it, jest } from 'bun:test'; import { createServer } from 'node:http'; import { createConnection } from 'node:net'; +import { gzipSync } from 'node:zlib'; import { Client } from '@modelcontextprotocol/sdk/client/index.js'; import { SSEClientTransport } from '@modelcontextprotocol/sdk/client/sse.js'; import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'; @@ -340,6 +341,26 @@ describe('HttpSseTransport', () => { expect(await health.json()).toMatchObject({ status: 'ok' }); }); + it('rejects a compressed body with trailing bytes and keeps serving', async () => { + consoleErrorSpy = jest.spyOn(console, 'error').mockImplementation(() => {}); + const transport = new HttpSseTransport({ port: 0, host: HOST, path: PATH, appConfig: DISABLED_APP_CONFIG }); + transports.push(transport); + const bootstrap = new McpServer({ name: 'bootstrap', version: '1.0.0' }); + bootstrapServers.push(bootstrap); + await transport.start(bootstrap); + const baseUrl = `http://${HOST}:${transport.getListeningPort()}`; + + const body = Buffer.concat([gzipSync(JSON.stringify({ jsonrpc: '2.0', method: 'ping', id: 1 })), Buffer.from('trailing')]); + const response = await fetch(`${baseUrl}${PATH}/message?sessionId=unknown`, { + method: 'POST', + headers: { 'content-type': 'application/json', 'content-encoding': 'gzip' }, + body + }); + + expect(response.status).toBe(415); + expect((await fetch(`${baseUrl}/health`)).status).toBe(200); + }); + it('releases a reserved slot when SSE transport creation fails', async () => { consoleErrorSpy = jest.spyOn(console, 'error').mockImplementation(() => {}); const transportFactory = jest.fn(() => { diff --git a/packages/mcp-server/src/tests/server/transport/streamable-http.test.ts b/packages/mcp-server/src/tests/server/transport/streamable-http.test.ts index 514bf9cd..814020cc 100644 --- a/packages/mcp-server/src/tests/server/transport/streamable-http.test.ts +++ b/packages/mcp-server/src/tests/server/transport/streamable-http.test.ts @@ -1,5 +1,6 @@ import { afterEach, describe, expect, it, jest } from 'bun:test'; import { createServer, type Server } from 'node:http'; +import { gzipSync } from 'node:zlib'; import { Client } from '@modelcontextprotocol/sdk/client/index.js'; import { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js'; import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'; @@ -90,6 +91,25 @@ describe('StreamableHttpTransport', () => { await expect(invalidLimit.start(bootstrap)).rejects.toThrow('STREAMABLE_HTTP_MAX_REQUESTS must be a positive integer'); }); + it('rejects a compressed body with trailing bytes and keeps serving', async () => { + consoleErrorSpy = jest.spyOn(console, 'error').mockImplementation(() => {}); + const bootstrap = { close: jest.fn() } as unknown as McpServer; + const transport = new StreamableHttpTransport({ port: 0, host: HOST, path: PATH, appConfig: DISABLED_APP_CONFIG }); + transports.push(transport); + await transport.start(bootstrap); + const baseUrl = `http://${HOST}:${transport.getListeningPort()}`; + + const body = Buffer.concat([gzipSync(JSON.stringify({ jsonrpc: '2.0', method: 'initialize', id: 1, params: {} })), Buffer.from('trailing')]); + const response = await fetch(`${baseUrl}${PATH}`, { + method: 'POST', + headers: { 'content-type': 'application/json', 'content-encoding': 'gzip' }, + body + }); + + expect(response.status).toBe(415); + expect((await fetch(`${baseUrl}/health`)).status).toBe(200); + }); + it('serves a real local MCP client request', async () => { consoleErrorSpy = jest.spyOn(console, 'error').mockImplementation(() => {}); const transport = new StreamableHttpTransport( diff --git a/packages/sei-global-wallet/README.md b/packages/sei-global-wallet/README.md index ca5387bf..ec5cdbf9 100644 --- a/packages/sei-global-wallet/README.md +++ b/packages/sei-global-wallet/README.md @@ -14,7 +14,7 @@ > [!WARNING] -> **Temporary consumer security waiver:** Dynamic Global Wallet Client transitively pins vulnerable `axios`, `sharp`, and `uuid` as of 4.96.3, the current floor. +> **Temporary consumer security waiver:** Dynamic Global Wallet Client transitively pins vulnerable `axios`, `sharp`, `uuid`, and `zod` as of 4.96.3, the current floor. > Dependency overrides are root-only in both npm and Bun; this package cannot propagate them to your application. Add the overrides below before installing, and drop them once your install resolves a Dynamic release that corrects those pins. ## Required consumer overrides @@ -30,7 +30,8 @@ Complete npm root overrides when the optional AA path is not enabled: "uuid": "11.1.1", "viem": { "ws": "8.21.0" - } + }, + "zod": "4.6.7" } } ``` @@ -41,16 +42,18 @@ Complete Bun root overrides. The block is the same with or without the optional "overrides": { "axios": "1.20.0", "sharp": "0.35.5", - "uuid": "11.1.1" + "uuid": "11.1.1", + "zod": "4.6.7" } } ``` -The Axios, Sharp, and UUID overrides are temporary until Dynamic updates its exact transitive pins: +The Axios, Sharp, UUID, and Zod overrides are temporary until Dynamic updates its exact transitive pins: - Dynamic pins `axios@1.16.0` exactly, and `1.20.0` is the first release outside every advisory reported against it. The high-severity Axios issues are in Node-only transports (the HTTP adapter, opt-in HTTP/2, and `NO_PROXY` handling) or are prototype-pollution gadgets that need a separate pollution primitive in the same process. Browser wallet paths do not use the Node transports, which reduces exploitability but does not make the vulnerable install acceptable; the `toFormData` and fetch-adapter gadgets apply in browsers too. - `@dynamic-labs/iconic` pins `sharp@0.35.0` exactly, and `0.35.5` is the first release outside both high-severity Sharp advisories against it: the bundled libheif heap overflow `GHSA-rgj7-g3m4-5g8c`, triggered by decoding untrusted HEIF input, and the bundled librsvg memory bug `GHSA-wq5f-xc86-pv6w` (CVE-2026-96889), triggered by decoding untrusted SVG input, which can lead to remote code execution on glibc-based Linux. No wallet path decodes images, and `sharp` is a build-time image dependency that never reaches a browser bundle. The override is a patch-level move within `0.35.x`, so it carries no API change. - The UUID issue affects the v3, v5, and v6 buffer APIs. Dynamic's observed call sites use UUID v4, which reduces exploitability but does not clear the audit finding. +- `@dynamic-labs-sdk/client` and `@dynamic-labs/wallet-book` pin `zod@4.0.5` exactly, inside the high-severity `GHSA-mrhx-c7xc-m3w5` (CVSS 7.5): an array schema without a length constraint records an issue for every failing element, so one large array can exhaust memory. `4.6.6` is the first fixed release, and the override uses `4.6.7`, the current one, which stays on Zod 4. Because the override is global, it also moves any Zod 3 dependency of your application onto Zod 4, such as the `zod@3.22.4` that `@reown/appkit-wallet` pins under wagmi's WalletConnect connector. If you have one, scope the override on npm to the two Dynamic packages instead, as `"@dynamic-labs-sdk/client": { "zod": "4.6.7" }` and `"@dynamic-labs/wallet-book": { "zod": "4.6.7" }`; Bun cannot scope overrides. Applications using the optional `./zerodev` / Dynamic account-abstraction path must also replace the vulnerable exact `bn.js@4.11.6` copies used by `ethjs-unit` and `number-to-bn`. The complete npm root override block is: ```json @@ -67,7 +70,8 @@ Applications using the optional `./zerodev` / Dynamic account-abstraction path m "uuid": "11.1.1", "viem": { "ws": "8.21.0" - } + }, + "zod": "4.6.7" } } ``` diff --git a/scripts/check-sei-global-wallet.ts b/scripts/check-sei-global-wallet.ts index c6bc0259..41ce63dd 100644 --- a/scripts/check-sei-global-wallet.ts +++ b/scripts/check-sei-global-wallet.ts @@ -175,7 +175,8 @@ const assertTestedPeersFitPublishedRanges = (testedPeerVersions: TestedPeerVersi const baseSafeOverrides = { axios: '1.20.0', sharp: '0.35.5', - uuid: '11.1.1' + uuid: '11.1.1', + zod: '4.6.7' }; const overriddenTransitivePins = Object.keys(baseSafeOverrides); const npmRuntimeOverrides = { diff --git a/scripts/mcp-zod-lock.test.ts b/scripts/mcp-zod-lock.test.ts index 810d5cd2..3623dec5 100644 --- a/scripts/mcp-zod-lock.test.ts +++ b/scripts/mcp-zod-lock.test.ts @@ -35,7 +35,7 @@ describe('mcp sdk zod lock', () => { ).toBeUndefined(); }); - test('mcp-server SDK range excludes versions that only declare zod 3', () => { + test('mcp-server SDK range excludes zod-3-only and advisory-affected versions', () => { const mcpServerPackage = JSON.parse(readFileSync(join(import.meta.dir, '..', 'packages/mcp-server/package.json'), 'utf8')) as { dependencies: { '@modelcontextprotocol/sdk': string }; }; @@ -43,8 +43,9 @@ describe('mcp sdk zod lock', () => { expect(Bun.semver.satisfies('1.17.5', sdkRange)).toBe(false); expect(Bun.semver.satisfies('1.22.0', sdkRange)).toBe(false); - expect(Bun.semver.satisfies('1.23.0', sdkRange)).toBe(true); - expect(Bun.semver.satisfies('1.30.0', sdkRange)).toBe(true); + // GHSA-46jr-4wx8-v453 and GHSA-6prh-2h8m-c8cw are fixed in 1.32.0. + expect(Bun.semver.satisfies('1.31.0', sdkRange)).toBe(false); + expect(Bun.semver.satisfies('1.32.0', sdkRange)).toBe(true); }); test('the repo lockfile keeps the MCP SDK on the same zod as mcp-server', () => {