From b8234e75996ed9f2186e39655e66c0163f06dd34 Mon Sep 17 00:00:00 2001 From: helix4u <4317663+helix4u@users.noreply.github.com> Date: Fri, 5 Jun 2026 13:13:00 -0600 Subject: [PATCH] fix(desktop): avoid restricted oauth request header --- apps/desktop/electron/main.cjs | 4 +-- apps/desktop/electron/oauth-net-request.cjs | 20 +++++++++++ .../electron/oauth-net-request.test.cjs | 34 +++++++++++++++++++ apps/desktop/package.json | 2 +- 4 files changed, 57 insertions(+), 3 deletions(-) create mode 100644 apps/desktop/electron/oauth-net-request.cjs create mode 100644 apps/desktop/electron/oauth-net-request.test.cjs diff --git a/apps/desktop/electron/main.cjs b/apps/desktop/electron/main.cjs index b42913093d7..775408f959a 100644 --- a/apps/desktop/electron/main.cjs +++ b/apps/desktop/electron/main.cjs @@ -28,6 +28,7 @@ const { detectRemoteDisplay, isWindowsBinaryPathInWsl, isWslEnvironment } = requ const { runBootstrap } = require('./bootstrap-runner.cjs') const { canImportHermesCli, verifyHermesCli } = require('./backend-probes.cjs') const { probeGatewayWebSocket } = require('./gateway-ws-probe.cjs') +const { serializeJsonBody, setJsonRequestHeaders } = require('./oauth-net-request.cjs') const { authModeFromStatus, buildGatewayWsUrl, @@ -3477,8 +3478,7 @@ function fetchJsonViaOauthSession(url, options = {}) { useSessionCookies: true, redirect: 'follow' }) - request.setHeader('Content-Type', 'application/json') - if (body) request.setHeader('Content-Length', String(body.length)) + setJsonRequestHeaders(request) let timedOut = false const timer = setTimeout(() => { diff --git a/apps/desktop/electron/oauth-net-request.cjs b/apps/desktop/electron/oauth-net-request.cjs new file mode 100644 index 00000000000..0498a7333fa --- /dev/null +++ b/apps/desktop/electron/oauth-net-request.cjs @@ -0,0 +1,20 @@ +/** + * Helpers for Electron net.request calls that ride the OAuth session partition. + * + * Electron's ClientRequest forbids app-set restricted headers such as + * Content-Length. Let Chromium frame the body itself; only set the JSON content + * type here. + */ + +function serializeJsonBody(body) { + return body === undefined ? undefined : Buffer.from(JSON.stringify(body)) +} + +function setJsonRequestHeaders(request) { + request.setHeader('Content-Type', 'application/json') +} + +module.exports = { + serializeJsonBody, + setJsonRequestHeaders +} diff --git a/apps/desktop/electron/oauth-net-request.test.cjs b/apps/desktop/electron/oauth-net-request.test.cjs new file mode 100644 index 00000000000..7d53bde5092 --- /dev/null +++ b/apps/desktop/electron/oauth-net-request.test.cjs @@ -0,0 +1,34 @@ +/** + * Tests for OAuth-session Electron net.request helpers. + * + * Run with: node --test electron/oauth-net-request.test.cjs + */ + +const test = require('node:test') +const assert = require('node:assert/strict') + +const { serializeJsonBody, setJsonRequestHeaders } = require('./oauth-net-request.cjs') + +test('serializeJsonBody returns undefined for absent bodies', () => { + assert.equal(serializeJsonBody(undefined), undefined) +}) + +test('serializeJsonBody JSON-encodes request bodies', () => { + const body = serializeJsonBody({ archived: true }) + assert.ok(Buffer.isBuffer(body)) + assert.equal(body.toString('utf8'), '{"archived":true}') +}) + +test('setJsonRequestHeaders does not set Electron-restricted Content-Length', () => { + const headers = [] + const request = { + setHeader(name, value) { + headers.push([name, value]) + } + } + + setJsonRequestHeaders(request) + + assert.deepEqual(headers, [['Content-Type', 'application/json']]) + assert.equal(headers.some(([name]) => name.toLowerCase() === 'content-length'), false) +}) diff --git a/apps/desktop/package.json b/apps/desktop/package.json index bcb46c855a0..f4bf696f8a1 100644 --- a/apps/desktop/package.json +++ b/apps/desktop/package.json @@ -35,7 +35,7 @@ "test:desktop:nsis": "node scripts/test-desktop.mjs nsis", "test:desktop:existing": "node scripts/test-desktop.mjs existing", "test:desktop:fresh": "node scripts/test-desktop.mjs fresh", - "test:desktop:platforms": "node --test electron/bootstrap-platform.test.cjs electron/hardening.test.cjs electron/backend-probes.test.cjs electron/bootstrap-runner.test.cjs electron/connection-config.test.cjs electron/gateway-ws-probe.test.cjs", + "test:desktop:platforms": "node --test electron/bootstrap-platform.test.cjs electron/hardening.test.cjs electron/backend-probes.test.cjs electron/bootstrap-runner.test.cjs electron/connection-config.test.cjs electron/gateway-ws-probe.test.cjs electron/oauth-net-request.test.cjs", "type-check": "tsc -b", "lint": "eslint src/ electron/", "lint:fix": "eslint src/ electron/ --fix",