CVE-2024-47080 Overview
CVE-2024-47080 is an information disclosure vulnerability in matrix-js-sdk, the Matrix Client-Server SDK for JavaScript and TypeScript. Versions 9.11.0 through 34.7.0 are affected when running the legacy crypto stack. The MatrixClient.sendSharedHistoryKeys method, introduced by MSC3061, transmits historical message decryption keys to all of an invited user's devices without verifying the user's cryptographic identity or device signatures. A malicious homeserver can inject attacker-controlled devices into a target user's device list and receive shared historical keys, gaining access to past encrypted room messages.
Critical Impact
A malicious homeserver can inject rogue devices to receive historical room encryption keys, exposing past encrypted messages in affected Matrix clients.
Affected Products
- matrix-js-sdk versions 9.11.0 through 34.7.0 (legacy crypto stack)
- Matrix clients invoking MatrixClient.sendSharedHistoryKeys() via MatrixClient.initCrypto()
- Not affected: clients using the Rust crypto stack via MatrixClient.initRustCrypto()
Discovery Timeline
- 2024-10-15 - CVE-2024-47080 published to NVD
- 2026-06-17 - Last updated in NVD database
Technical Details for CVE-2024-47080
Vulnerability Analysis
The vulnerability resides in the MatrixClient.sendSharedHistoryKeys method. This API, defined by Matrix Spec Change proposal 3061 (MSC3061), shares historical Megolm session keys with users newly invited to an encrypted room. The intent is to grant new members access to messages sent before they joined.
The legacy crypto implementation calls this.crypto.downloadKeys(userIds) and then sends the shared history keys to every device returned for each user. The code performs no verification of the recipient user's cross-signing identity and does not validate that each device is signed by that identity. Any device the homeserver claims belongs to the invited user receives the keys.
The weakness is classified as [CWE-200] Exposure of Sensitive Information to an Unauthorized Actor. Because Matrix homeservers control the device list responses returned to clients, a compromised or malicious homeserver can append attacker-owned devices and harvest historical room keys.
Root Cause
The root cause is missing trust validation in sendSharedHistoryKeys. The function bypasses the verification gates that normally apply to sensitive key sharing, treating all homeserver-supplied devices as legitimate recipients. End-to-end encryption guarantees fail when the homeserver itself is the adversary in the threat model.
Attack Vector
An attacker controlling the homeserver waits for a target user to be invited to an encrypted room. When the inviter's client invokes sendSharedHistoryKeys, the homeserver returns a device list that includes attacker-controlled devices alongside the legitimate ones. The inviting client encrypts and transmits historical Megolm keys to all listed devices, including the attacker's. The attacker then decrypts past room messages.
The fix removes the vulnerable method entirely. The patch in src/client.ts deletes the sendSharedHistoryKeys function, and src/models/MSC3089TreeSpace.ts no longer imports isRoomSharedHistory from the Megolm algorithm module.
// Patch: removal of sendSharedHistoryKeys in src/client.ts
- /**
- * Share shared-history decryption keys with the given users.
- *
- * @param roomId - the room for which keys should be shared.
- * @param userIds - a list of users to share with. The keys will be sent to
- * all of the user's current devices.
- *
- * @deprecated Do not use this method. It does not work with the Rust crypto stack,
- * and even with the legacy stack it introduces a security vulnerability.
- */
- public async sendSharedHistoryKeys(roomId: string, userIds: string[]): Promise<void> {
- if (!this.crypto) {
- throw new Error("End-to-end encryption disabled");
- }
-
- const roomEncryption = this.crypto?.getRoomEncryption(roomId);
- if (!roomEncryption) {
- this.logger.error("Unknown room. Not sharing decryption keys");
- return;
- }
-
- const deviceInfos = await this.crypto.downloadKeys(userIds);
- const devicesByUser: Map<string, DeviceInfo[]> = new Map();
- for (const [userId, devices] of deviceInfos) {
- devicesByUser.set(userId, Array.from(devices.values()));
- }
Source: matrix-js-sdk commit 2fb1e659
Detection Methods for CVE-2024-47080
Indicators of Compromise
- Unexpected device entries appearing in a user's device list shortly before or after an invite to an encrypted room
- m.room_key to-device messages addressed to devices that lack cross-signing signatures from the owning user
- Use of MatrixClient.sendSharedHistoryKeys in application logs of clients running matrix-js-sdk versions 9.11.0 through 34.7.0
Detection Strategies
- Inventory all deployed Matrix clients and identify those linking matrix-js-sdk between 9.11.0 and 34.7.0 with initCrypto() (legacy stack)
- Audit homeserver /_matrix/client/v3/keys/query responses for devices not signed by the user's self-signing key
- Review client source code for direct or indirect calls to sendSharedHistoryKeys and flag any usage
Monitoring Recommendations
- Log and alert on m.room_key to-device events sent to newly added or unverified devices following room invitations
- Track matrix-js-sdk dependency versions in software bills of materials and CI pipelines
- Monitor for new device registrations on homeservers that occur out of band from user activity
How to Mitigate CVE-2024-47080
Immediate Actions Required
- Upgrade matrix-js-sdk to version 34.8.0 or later, which removes the vulnerable sendSharedHistoryKeys method
- Migrate clients from the legacy crypto stack to the Rust crypto stack by replacing MatrixClient.initCrypto() with MatrixClient.initRustCrypto()
- Audit application code and remove any call sites that invoke sendSharedHistoryKeys
Patch Information
The vulnerability is fixed in matrix-js-sdk 34.8.0. The fix removes MatrixClient.sendSharedHistoryKeys from src/client.ts and drops the associated isRoomSharedHistory import in src/models/MSC3089TreeSpace.ts. See the GitHub Security Advisory GHSA-4jf8-g8wp-cx7c and the upstream patch commit. Background on the original feature is documented in the MSC3061 spec proposal.
Workarounds
- Remove all client code paths that call MatrixClient.sendSharedHistoryKeys until upgrading is possible
- Initialize the Rust crypto stack via initRustCrypto(), in which sendSharedHistoryKeys raises an exception and cannot be exploited
- Restrict trust to known, verified homeservers and avoid federating with untrusted servers when sharing historical keys
# Upgrade matrix-js-sdk to the patched release
npm install matrix-js-sdk@^34.8.0
# Verify installed version
npm ls matrix-js-sdk
# Grep for residual usage of the removed API
grep -rn "sendSharedHistoryKeys" ./src
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

