From 777c493a9b3230a31f6a6cac5fe8ae510ace4fe7 Mon Sep 17 00:00:00 2001 From: Dean Sheather Date: Fri, 23 Oct 2026 15:02:23 +0000 Subject: [PATCH] Upgrade Node to 24.22.1 --- .node-version | 2 +- CHANGELOG.md | 7 +++++++ patches/node-version.diff | 16 ++++++++++++++++ patches/series | 1 + src/node/routes/index.ts | 6 ++++-- src/node/vscodeSocket.ts | 2 +- test/unit/node/routes/login.test.ts | 11 +++++++++++ 7 files changed, 41 insertions(+), 4 deletions(-) create mode 100644 patches/node-version.diff diff --git a/.node-version b/.node-version index df6ae3370f9f..ce62013c39ae 100644 --- a/.node-version +++ b/.node-version @@ -1 +1 @@ -24.21.0 +24.22.1 diff --git a/CHANGELOG.md b/CHANGELOG.md index e86bd3bea33c..25aa34777c67 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,13 @@ Code v99.99.999 ## Unreleased +### Security + +- Update bundled Node.js to 24.22.1 to fix a remote code execution bug in the + Brotli decoder (CVE-2026-111497). +- Reject compressed request bodies (`Content-Encoding: br`, `gzip`, or + `deflate`) instead of decompressing them. + ## [4.141.0](https://github.com/coder/code-server/releases/tag/v4.141.0) - 2026-10-08 Code v1.141.0 diff --git a/patches/node-version.diff b/patches/node-version.diff new file mode 100644 index 000000000000..365a9638b366 --- /dev/null +++ b/patches/node-version.diff @@ -0,0 +1,16 @@ +Bump the bundled Node.js version + +Pull in Node.js security fixes (Brotli decoder RCE) ahead of upstream. Drop +this patch once upstream targets this version or newer. + +Index: code-server/lib/vscode/remote/.npmrc +=================================================================== +--- code-server.orig/lib/vscode/remote/.npmrc ++++ code-server/lib/vscode/remote/.npmrc +@@ -1,5 +1,5 @@ + disturl="https://nodejs.org/dist" +-target="24.21.0" ++target="24.22.1" + ms_build_id="474716" + runtime="node" + build_from_source="true" diff --git a/patches/series b/patches/series index b102e9d2c5c6..ebbeb794f91e 100644 --- a/patches/series +++ b/patches/series @@ -27,3 +27,4 @@ app-name.diff remote-storage.diff remote-secret-storage.diff csp-hashes.diff +node-version.diff diff --git a/src/node/routes/index.ts b/src/node/routes/index.ts index 78e30566867d..ec2e3af0573d 100644 --- a/src/node/routes/index.ts +++ b/src/node/routes/index.ts @@ -132,8 +132,10 @@ export const register = async ( }) }) - app.router.use(express.json()) - app.router.use(express.urlencoded({ extended: true })) + // Reject compressed request bodies so unauthenticated requests cannot reach + // the zlib/Brotli decoders. Browsers never compress request bodies. + app.router.use(express.json({ inflate: false })) + app.router.use(express.urlencoded({ extended: true, inflate: false })) app.router.use( "/_static", diff --git a/src/node/vscodeSocket.ts b/src/node/vscodeSocket.ts index e01d1a15012b..70603e50b392 100644 --- a/src/node/vscodeSocket.ts +++ b/src/node/vscodeSocket.ts @@ -38,7 +38,7 @@ export async function makeEditorSessionManagerServer( ): Promise { const router = express() - router.use(express.json()) + router.use(express.json({ inflate: false })) router.get<{}, GetSessionResponse | string | unknown, undefined, { filePath?: string }>( "/session", diff --git a/test/unit/node/routes/login.test.ts b/test/unit/node/routes/login.test.ts index 2835bad82354..e7c9857bc607 100644 --- a/test/unit/node/routes/login.test.ts +++ b/test/unit/node/routes/login.test.ts @@ -75,6 +75,17 @@ describe("login", () => { expect(htmlContent).toContain("Missing password") }) + it("should reject compressed request bodies", async () => { + for (const encoding of ["br", "gzip", "deflate"]) { + const resp = await codeServer().fetch("/login", { + method: "POST", + headers: { "Content-Type": "application/x-www-form-urlencoded", "Content-Encoding": encoding }, + body: "password=test", + }) + expect(resp.status).toBe(415) + } + }) + it("should return HTML with 'Incorrect password' message", async () => { const params = new URLSearchParams() params.append("password", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")