diff --git a/.changeset/fix-create-sei-bun-brotli.md b/.changeset/fix-create-sei-bun-brotli.md new file mode 100644 index 000000000..4d8577689 --- /dev/null +++ b/.changeset/fix-create-sei-bun-brotli.md @@ -0,0 +1,11 @@ +--- +'@sei-js/create-sei': patch +--- + +Require Bun 1.4.4 for generated applications, the first Bun release outside the Brotli decoder advisory `GHSA-9v8h-qqgm-4m35` (CVE-2026-111497). + +Bun vendors Google's Brotli library for `node:zlib` and for decompressing `fetch` responses. The `1.3.14` the template pinned ships Brotli 1.1.0, and Bun 1.4.3 still ships 1.2.0, both inside the advisory's 1.0.3 through 1.2.0 range. Bun 1.4.4 ships Brotli 1.2.1, and there is no fixed 1.3.x release. + +The template's `packageManager` moves from `bun@1.3.14` to `bun@1.4.4`, and the generated README and this package's README name 1.4.4 as the minimum. The release smoke now runs on Bun 1.4.4, so that is the version the template's overrides are validated with. + +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 new file mode 100644 index 000000000..1eeb991f0 --- /dev/null +++ b/.changeset/fix-mcp-server-brotli-node-floor.md @@ -0,0 +1,15 @@ +--- +'@sei-js/mcp-server': patch +--- + +Raise the supported Node.js range to the releases that patch the Brotli decoder advisory `GHSA-9v8h-qqgm-4m35` (CVE-2026-111497). + +**This drops support for Node.js 20, and for 22.x, 24.x, and 26.x releases before 22.23.4, 24.22.1, and 26.12.1.** npm only warns about the engine mismatch, but Yarn 1, and npm with `engine-strict` set, refuse to install this release on them. + +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. + +`engines.node` moves from `>=20.0.0` to `^22.23.4 || ^24.22.1 || >=26.12.1`, and the README's requirement matches. + +No dependency or peer range changes. diff --git a/.github/workflows/checks.yml b/.github/workflows/checks.yml index 6deeb61e8..ddaf02f5b 100644 --- a/.github/workflows/checks.yml +++ b/.github/workflows/checks.yml @@ -26,7 +26,7 @@ jobs: - uses: oven-sh/setup-bun@v2 with: - bun-version: '1.3.14' + bun-version: '1.4.4' - name: Install system dependencies run: sudo apt-get update && sudo apt-get install -y rsync diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index aaad0d649..d77ca850b 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -35,7 +35,7 @@ jobs: - uses: oven-sh/setup-bun@v2 with: - bun-version: '1.3.14' + bun-version: '1.4.4' - name: Install dependencies run: bun install --frozen-lockfile diff --git a/.github/workflows/create-sei-smoke.yml b/.github/workflows/create-sei-smoke.yml index b98eda94d..ebc280b89 100644 --- a/.github/workflows/create-sei-smoke.yml +++ b/.github/workflows/create-sei-smoke.yml @@ -60,7 +60,7 @@ jobs: - name: Setup Bun uses: oven-sh/setup-bun@v2 with: - bun-version: '1.3.14' + bun-version: '1.4.4' - name: Install system dependencies run: sudo apt-get update && sudo apt-get install -y rsync diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 1b3ea6b79..9a469a7b8 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -31,7 +31,7 @@ jobs: - uses: oven-sh/setup-bun@v2 with: - bun-version: '1.3.14' + bun-version: '1.4.4' - name: Install system dependencies run: sudo apt-get update && sudo apt-get install -y rsync diff --git a/.github/workflows/sei-global-wallet-smoke.yml b/.github/workflows/sei-global-wallet-smoke.yml index df5476c98..9c8afd3fc 100644 --- a/.github/workflows/sei-global-wallet-smoke.yml +++ b/.github/workflows/sei-global-wallet-smoke.yml @@ -58,7 +58,7 @@ jobs: - name: Setup Bun uses: oven-sh/setup-bun@v2 with: - bun-version: '1.3.14' + bun-version: '1.4.4' - name: Install workspace dependencies run: bun install --frozen-lockfile diff --git a/.nvmrc b/.nvmrc index a45fd52cc..ce62013c3 100644 --- a/.nvmrc +++ b/.nvmrc @@ -1 +1 @@ -24 +24.22.1 diff --git a/README.md b/README.md index 4fc1a9a94..c37118be5 100644 --- a/README.md +++ b/README.md @@ -20,9 +20,9 @@ This project uses [Bun](https://bun.sh) for package management, tests, and scrip ### Prerequisites -Install Bun 1.3.14: https://bun.sh/docs/installation +Install Bun 1.4.4: https://bun.sh/docs/installation -Node.js 24 is pinned in `.nvmrc` for npm package validation and OIDC publishing; Bun remains the workspace package manager and test runner. +Node.js 24.22.1 is pinned in `.nvmrc` for npm package validation and OIDC publishing; Bun remains the workspace package manager and test runner. ### Install, build, test diff --git a/package.json b/package.json index 44ff42332..3806ce0b8 100644 --- a/package.json +++ b/package.json @@ -46,5 +46,5 @@ "publint": "0.3.23", "typescript": "^5.8.2" }, - "packageManager": "bun@1.3.14" + "packageManager": "bun@1.4.4" } diff --git a/packages/create-sei/README.md b/packages/create-sei/README.md index 0207042a9..2949655d7 100644 --- a/packages/create-sei/README.md +++ b/packages/create-sei/README.md @@ -19,7 +19,7 @@ npx @sei-js/create-sei app -n my-sei-app ``` -Generated applications require Bun 1.3.14 or newer. Their dependency overrides and smoke coverage are Bun-specific; using npm, Yarn, or pnpm can resolve a different, unverified security graph. +Generated applications require Bun 1.4.4 or newer. Their dependency overrides and smoke coverage are Bun-specific; using npm, Yarn, or pnpm can resolve a different, unverified security graph. ## Release verification diff --git a/packages/create-sei/templates/next-template/README.md b/packages/create-sei/templates/next-template/README.md index e2d77be9b..d9299d092 100644 --- a/packages/create-sei/templates/next-template/README.md +++ b/packages/create-sei/templates/next-template/README.md @@ -4,7 +4,7 @@ This app was generated by `@sei-js/create-sei`. It uses Next.js, Wagmi, Viem, Ra ## Package manager -Bun 1.3.14 or newer is required for this starter. Its security overrides and release smoke are validated with Bun; npm, Yarn, and pnpm do not share one override contract and may silently resolve a different dependency graph. +Bun 1.4.4 or newer is required for this starter. Its security overrides and release smoke are validated with Bun; npm, Yarn, and pnpm do not share one override contract and may silently resolve a different dependency graph. The generated project intentionally does not ship a lockfile. Exact direct pins reduce drift, but transitive dependencies are resolved when you run `bun install`; the dedicated smoke validates the current graph rather than claiming every future install is byte-for-byte reproducible. Commit the resulting `bun.lock` after your first reviewed install. diff --git a/packages/create-sei/templates/next-template/package.json b/packages/create-sei/templates/next-template/package.json index 221c62fe8..444d1f619 100644 --- a/packages/create-sei/templates/next-template/package.json +++ b/packages/create-sei/templates/next-template/package.json @@ -51,5 +51,5 @@ "uuid": "11.1.1", "ws": "8.21.3" }, - "packageManager": "bun@1.3.14" + "packageManager": "bun@1.4.4" } diff --git a/packages/mcp-server/README.md b/packages/mcp-server/README.md index 60690d1e6..026d1c5cb 100644 --- a/packages/mcp-server/README.md +++ b/packages/mcp-server/README.md @@ -15,7 +15,7 @@ ## Requirements -Node.js 20 or newer. +Node.js 22.23.4 or a later 22.x release, 24.22.1 or a later 24.x release, or 26.12.1 and newer. Earlier releases ship a Brotli decoder affected by [CVE-2026-111497](https://nodejs.org/en/blog/vulnerability/october-2026-security-releases), which `fetch` uses to decompress the RPC and docs responses this server reads. ## Quick Start diff --git a/packages/mcp-server/package.json b/packages/mcp-server/package.json index 244f4c906..ef99b6372 100644 --- a/packages/mcp-server/package.json +++ b/packages/mcp-server/package.json @@ -56,7 +56,7 @@ "author": "@codebycarson", "license": "MIT", "engines": { - "node": ">=20.0.0" + "node": "^22.23.4 || ^24.22.1 || >=26.12.1" }, "repository": { "type": "git", 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 aed28f178..514bf9cda 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 @@ -387,7 +387,12 @@ describe('StreamableHttpTransport', () => { }).catch(() => undefined); await withTimeout(started, 'request startup'); - await expect(transport.stop()).rejects.toBeInstanceOf(AggregateError); + // Under Bun 1.4, `expect(...).rejects` never settles a stop() that has to close a live request. + const stopError = await transport.stop().then( + () => undefined, + (error: unknown) => error + ); + expect(stopError).toBeInstanceOf(AggregateError); expect(requestTransport.close).toHaveBeenCalledTimes(1); expect(requestServer.close).toHaveBeenCalledTimes(1); await expect(transport.stop()).resolves.toBeUndefined(); diff --git a/scripts/check-sei-global-wallet.ts b/scripts/check-sei-global-wallet.ts index d2933bf2c..6dd9dfe88 100644 --- a/scripts/check-sei-global-wallet.ts +++ b/scripts/check-sei-global-wallet.ts @@ -631,10 +631,14 @@ const runEdgeBundle = async (bundlePath: string) => { filename: bundlePath, timeout: 10_000 }); - assert.deepEqual(context.__edgeCheck, { - aliases: true, - entrypoints: true - }); + // The result object belongs to the vm realm, and a strict deep comparison rejects its foreign prototype. + assert.deepEqual( + { ...(context.__edgeCheck as Record) }, + { + aliases: true, + entrypoints: true + } + ); }; /**