From 6c78684e84ba7f460aedba6f017760e2323fdf4b Mon Sep 17 00:00:00 2001 From: R Midhun Suresh Date: Tue, 15 Oct 2024 17:21:06 +0530 Subject: [PATCH 1/3] Merge commit from fork * Check url with homeserver * Move check to where access-token is added * Do IPC comm sparingly Before, the code would fetch the hs for every request. Since this needs the whole event-handler dance, it's best we do it only for the requests that match the media endpoints. Also added some try..catch since we create URL objects that could potentially throw * Check origin instead of just hostname --- src/media-auth.ts | 81 +++++++++++++++++++++++++++++++++-------------- src/preload.ts | 1 + 2 files changed, 59 insertions(+), 23 deletions(-) diff --git a/src/media-auth.ts b/src/media-auth.ts index 4560a92..ba25a48 100644 --- a/src/media-auth.ts +++ b/src/media-auth.ts @@ -33,39 +33,74 @@ async function getAccessToken(window: BrowserWindow): Promise { + return new Promise((resolve) => { + ipcMain.once("homeserverUrl", (_, homeserver) => { + resolve(homeserver); + }); + window.webContents.send("homeserverUrl"); // ping now that the listener exists + }); +} + export function setupMediaAuth(window: BrowserWindow): void { session.defaultSession.webRequest.onBeforeRequest(async (req, callback) => { // This handler emulates the element-web service worker, where URLs are rewritten late in the request // for backwards compatibility. As authenticated media becomes more prevalent, this should be replaced // by the app using authenticated URLs from the outset. - let url = req.url; - if (!url.includes("/_matrix/media/v3/download") && !url.includes("/_matrix/media/v3/thumbnail")) { - return callback({}); // not a URL we care about - } + try { + const url = new URL(req.url); + if ( + !url.pathname.startsWith("/_matrix/media/v3/download") && + !url.pathname.startsWith("/_matrix/media/v3/thumbnail") + ) { + return callback({}); // not a URL we care about + } - const supportedVersions = await getSupportedVersions(window); - // We have to check that the access token is truthy otherwise we'd be intercepting pre-login media request too, - // e.g. those required for SSO button icons. - const accessToken = await getAccessToken(window); - if (supportedVersions.includes("v1.11") && accessToken) { - url = url.replace(/\/media\/v3\/(.*)\//, "/client/v1/media/$1/"); - return callback({ redirectURL: url }); - } else { - return callback({}); // no support == no modification + const supportedVersions = await getSupportedVersions(window); + // We have to check that the access token is truthy otherwise we'd be intercepting pre-login media request too, + // e.g. those required for SSO button icons. + const accessToken = await getAccessToken(window); + if (supportedVersions.includes("v1.11") && accessToken) { + url.href = url.href.replace(/\/media\/v3\/(.*)\//, "/client/v1/media/$1/"); + return callback({ redirectURL: url.toString() }); + } else { + return callback({}); // no support == no modification + } + } catch (e) { + console.error(e); } }); session.defaultSession.webRequest.onBeforeSendHeaders(async (req, callback) => { - if (!req.url.includes("/_matrix/client/v1/media")) { - return callback({}); // invoke unmodified - } + try { + const url = new URL(req.url); + if (!url.pathname.startsWith("/_matrix/client/v1/media")) { + return callback({}); // invoke unmodified + } - // Only add authorization header to authenticated media URLs. This emulates the service worker - // behaviour in element-web. - const accessToken = await getAccessToken(window); - // `accessToken` can be falsy, but if we're trying to download media without authentication - // then we should expect failure anyway. - const headers = { ...req.requestHeaders, Authorization: `Bearer ${accessToken}` }; - return callback({ requestHeaders: headers }); + // Is this request actually going to the homeserver? + // We don't combine this check with the one above on purpose. + // We're fetching the homeserver url through IPC and should do so + // as sparingly as possible. + const homeserver = await getHomeserverUrl(window); + const isRequestToHomeServer = homeserver && url.origin === new URL(homeserver).origin; + if (!isRequestToHomeServer) { + return callback({}); // invoke unmodified + } + + // Only add authorization header to authenticated media URLs. This emulates the service worker + // behaviour in element-web. + const accessToken = await getAccessToken(window); + // `accessToken` can be falsy, but if we're trying to download media without authentication + // then we should expect failure anyway. + const headers = { ...req.requestHeaders, Authorization: `Bearer ${accessToken}` }; + return callback({ requestHeaders: headers }); + } catch (e) { + console.error(e); + } }); } diff --git a/src/preload.ts b/src/preload.ts index 398f944..faa86a4 100644 --- a/src/preload.ts +++ b/src/preload.ts @@ -28,6 +28,7 @@ const CHANNELS = [ "userDownloadAction", "openDesktopCapturerSourcePicker", "userAccessToken", + "homeserverUrl", "serverSupportedVersions", ]; From ea21a144cade2781e8cd12fb1b012ea66d1df120 Mon Sep 17 00:00:00 2001 From: David Baker Date: Mon, 14 Oct 2024 13:38:13 +0100 Subject: [PATCH 2/3] Pin GHA to ubuntu 22 (#1920) while we work out why 24 fails --- .github/workflows/backport.yml | 2 +- .github/workflows/build_and_deploy.yaml | 4 ++-- .github/workflows/build_and_test.yaml | 4 ++-- .github/workflows/build_linux.yaml | 4 ++-- .github/workflows/build_prepare.yaml | 2 +- .github/workflows/dockerbuild.yaml | 2 +- .github/workflows/release.yml | 2 +- .github/workflows/static_analysis.yaml | 8 ++++---- .github/workflows/triage-incoming.yml | 2 +- 9 files changed, 15 insertions(+), 15 deletions(-) diff --git a/.github/workflows/backport.yml b/.github/workflows/backport.yml index dd79389..01dfbe4 100644 --- a/.github/workflows/backport.yml +++ b/.github/workflows/backport.yml @@ -10,7 +10,7 @@ on: jobs: backport: name: Backport - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 # Only react to merged PRs for security reasons. # See https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#pull_request_target. if: > diff --git a/.github/workflows/build_and_deploy.yaml b/.github/workflows/build_and_deploy.yaml index 2343951..02a4df0 100644 --- a/.github/workflows/build_and_deploy.yaml +++ b/.github/workflows/build_and_deploy.yaml @@ -99,7 +99,7 @@ jobs: - macos - linux - windows - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 name: ${{ needs.prepare.outputs.deploy == 'true' && 'Deploy' || 'Deploy (dry-run)' }} if: always() && !contains(needs.*.result, 'failure') && !contains(needs.*.result, 'cancelled') environment: ${{ needs.prepare.outputs.deploy == 'true' && 'packages.element.io' || '' }} @@ -252,7 +252,7 @@ jobs: deploy-ess: needs: deploy - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 name: Deploy builds to ESS if: needs.prepare.outputs.deploy == 'true' && github.event_name == 'release' env: diff --git a/.github/workflows/build_and_test.yaml b/.github/workflows/build_and_test.yaml index 47ad0e4..9708b7a 100644 --- a/.github/workflows/build_and_test.yaml +++ b/.github/workflows/build_and_test.yaml @@ -60,12 +60,12 @@ jobs: rsync -a /Volumes/Element/Element.app ~/Applications/ && hdiutil detach /Volumes/Element - name: "Linux (amd64) (sqlcipher: system)" - os: ubuntu-latest + os: ubuntu-22.04 artifact: linux-amd64-sqlcipher-system executable: "/opt/Element/element-desktop" prepare_cmd: "sudo apt-get -qq update && sudo apt install ./dist/*.deb" - name: "Linux (amd64) (sqlcipher: static)" - os: ubuntu-latest + os: ubuntu-22.04 artifact: linux-amd64-sqlcipher-static executable: "/opt/Element/element-desktop" prepare_cmd: "sudo apt-get -qq update && sudo apt install ./dist/*.deb" diff --git a/.github/workflows/build_linux.yaml b/.github/workflows/build_linux.yaml index 832b472..56adf32 100644 --- a/.github/workflows/build_linux.yaml +++ b/.github/workflows/build_linux.yaml @@ -26,7 +26,7 @@ jobs: # We build the hak files on native infrastructure as matrix-seshat fails to cross-compile properly # https://github.com/matrix-org/seshat/issues/135 hak: - runs-on: ${{ inputs.arch == 'arm64' && 'dind-l-arm64' || 'ubuntu-latest' }} + runs-on: ${{ inputs.arch == 'arm64' && 'dind-l-arm64' || 'ubuntu-22.04' }} env: HAK_DOCKER_IMAGE: ghcr.io/element-hq/element-desktop-dockerbuild outputs: @@ -148,7 +148,7 @@ jobs: build: needs: hak - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 steps: - uses: actions/checkout@v4 diff --git a/.github/workflows/build_prepare.yaml b/.github/workflows/build_prepare.yaml index ffb727c..b0fca35 100644 --- a/.github/workflows/build_prepare.yaml +++ b/.github/workflows/build_prepare.yaml @@ -45,7 +45,7 @@ jobs: prepare: name: Prepare environment: ${{ inputs.nightly && 'packages.element.io' || '' }} - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 outputs: nightly-version: ${{ steps.versions.outputs.nightly }} steps: diff --git a/.github/workflows/dockerbuild.yaml b/.github/workflows/dockerbuild.yaml index 5d1d049..4ff2e4e 100644 --- a/.github/workflows/dockerbuild.yaml +++ b/.github/workflows/dockerbuild.yaml @@ -12,7 +12,7 @@ env: jobs: build: name: Docker Build - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 permissions: contents: read packages: write diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index efda150..c81116f 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -26,7 +26,7 @@ jobs: check: name: Post release checks needs: release - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 steps: - name: Wait for desktop packaging uses: t3chguy/wait-on-check-action@18541021811b56544d90e0f073401c2b99e249d6 # fork diff --git a/.github/workflows/static_analysis.yaml b/.github/workflows/static_analysis.yaml index d9014f1..92b3283 100644 --- a/.github/workflows/static_analysis.yaml +++ b/.github/workflows/static_analysis.yaml @@ -6,7 +6,7 @@ on: jobs: ts_lint: name: "Typescript Syntax Check" - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 steps: - uses: actions/checkout@v4 @@ -30,7 +30,7 @@ jobs: js_lint: name: "ESLint" - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 steps: - uses: actions/checkout@v4 @@ -48,7 +48,7 @@ jobs: workflow_lint: name: "Workflow Lint" - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 steps: - uses: actions/checkout@v4 @@ -66,7 +66,7 @@ jobs: analyse_dead_code: name: "Analyse Dead Code" - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 steps: - uses: actions/checkout@v4 diff --git a/.github/workflows/triage-incoming.yml b/.github/workflows/triage-incoming.yml index 2535fbf..a62c1c8 100644 --- a/.github/workflows/triage-incoming.yml +++ b/.github/workflows/triage-incoming.yml @@ -6,7 +6,7 @@ on: jobs: automate-project-columns-next: - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 steps: - uses: actions/add-to-project@main with: From ed95434513a76420f5e448fb787f25cef4647586 Mon Sep 17 00:00:00 2001 From: RiotRobot Date: Tue, 15 Oct 2024 11:58:59 +0000 Subject: [PATCH 3/3] v1.11.81 --- CHANGELOG.md | 4 ++++ package.json | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3c9d251..442b768 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +Changes in [1.11.81](https://github.com/element-hq/element-desktop/releases/tag/v1.11.81) (2024-10-15) +====================================================================================================== +This release fixes High severity vulnerability CVE-2024-47771 / GHSA-963w-49j9-gxj6. + Changes in [1.11.80](https://github.com/element-hq/element-desktop/releases/tag/v1.11.80) (2024-10-08) ====================================================================================================== ## ✨ Features diff --git a/package.json b/package.json index 1a7de15..aff6f4b 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "element-desktop", "productName": "Element", "main": "lib/electron-main.js", - "version": "1.11.80", + "version": "1.11.81", "description": "A feature-rich client for Matrix.org", "author": "Element", "homepage": "https://element.io",