Jul 30, 2026·8 min read·11 visits
The matrix-commander CLI tool is cryptographically unsafe due to legacy dependencies on the deprecated libolm library, which contains timing side-channels and protocol confusion vulnerabilities. Users must migrate to the Rust alternative or upgrade downstream dependencies to use vodozemac.
GHSA-WCHH-9X6H-7F6P documents the critical deprecation of the cryptographic library libolm (Olm) and its Python binding wrapper python-olm, which matrix-commander depended upon via its downstream client library matrix-nio. Multiple cryptographic vulnerabilities (timing leaks, side-channels, signature malleability, and protocol confusion) were disclosed in 2022 and 2024. Because libolm is unmaintained, Python clients using matrix-commander are considered cryptographically unsafe until migrating to vodozemac.
The PyPI package matrix-commander is a command-line interface client designed for the Matrix chat protocol. Historically, the cryptographic security of its End-to-End Encryption (E2EE) layer depended on matrix-nio, a Python SDK that wraps python-olm. This wrapper acts as a direct interface to libolm, the original C implementation of the Olm and Megolm cryptographic protocols. As a result, any vulnerability residing within libolm or its bindings directly degrades the security posture of matrix-commander.
Over several years, security evaluations uncovered structural and implementation-level cryptographic weaknesses in libolm. In 2022, researchers disclosed CVE-2022-39255, a protocol confusion vulnerability in Olm and Megolm. In 2024, a subsequent comprehensive review disclosed CVE-2024-45193, exposing timing side-channels, base64 timing leaks, and Ed25519 signature malleability. Because the Matrix Foundation has deprecated libolm in favor of newer Rust-based implementations, these vulnerabilities will remain unpatched in the C codebase, leaving legacy clients permanently exposed.
This deprecation advisory, cataloged under GHSA-WCHH-9X6H-7F6P, highlights that Python-based implementations using the legacy libolm engine are structurally insecure. Furthermore, modern development environments struggle to compile the unmaintained python-olm package due to legacy CMake requirements, leading to severe build failures. The only viable path forward for the ecosystem involves migrating to vodozemac, a modern, memory-safe, constant-time cryptographic library implemented in Rust.
The root cause of this security degradation stems from multiple distinct vulnerabilities in libolm that cumulative maintenance cannot address. First, the AES decryption routines inside libolm are not implemented in constant-time. Because of this, hardware cache behaviors and execution latency vary predictably based on the secret key and the ciphertext being processed. An attacker capable of measuring these sub-millisecond differences can extract key material or reconstruct plaintext fragments through a timing side-channel attack.
Second, the Ed25519 signature verification engine within libolm fails to enforce strict compliance with the format specifications defined in RFC 8032. The parser does not validate whether the signature elements are properly reduced modulo the group order. This lax validation allows for signature malleability, where an attacker can modify a valid signature into another valid-looking signature without possessing the private key. In decentralized protocols like Matrix, signature malleability can undermine non-repudiation and authentication baselines.
Third, libolm exhibits timing leaks during the decoding of base64-encoded ciphertexts. Because the decoding functions process input bytes using non-constant-time branching logic, the execution time varies based on the values of the encoded payload. Finally, the protocol confusion vulnerability (CVE-2022-39255) occurs because the engine does not strictly bind the sender's Olm session keys to the corresponding Megolm session and the specific Room ID. This logical oversight allows a compromised Matrix homeserver to redirect a message from one encrypted room to another without triggering decryption failures on the target client.
To resolve these weaknesses, the upstream library matrix-nio implemented a total migration from python-olm to vodozemac in Commit 71a1c808bc2ae6ea2a6e8effa7c11bd09796c626. This migration involved deleting the legacy python-olm dependency and modifying the low-level cryptographic handlers. In pyproject.toml, the legacy package is replaced:
@@ -29,7 +29,7 @@ e2e = [
"atomicwrites~=1.4",
"cachetools~=5.3",
"peewee~=3.14",
- "python-olm~=3.2",
+ "vodozemac~=0.9",
]This change completely removes the reliance on the unmaintained C library and resolves modern compiler compatibility issues.
The core of the change lies in src/nio/crypto/olm_machine.py. The patch substitutes the insecure signature verification routine of libolm with the constant-time, memory-safe Rust wrapper provided by vodozemac:
@@ -1855,9 +1861,12 @@ def verify_json(self, json, user_key, user_id, device_id):
unsigned = json.pop("unsigned", None)
try:
- olm.ed25519_verify(user_key, Api.to_canonical_json(json), signature_base64)
+ user_key = vodozemac.Ed25519PublicKey.from_base64(user_key)
+ signature = vodozemac.Ed25519Signature.from_base64(signature_base64)
+ message = Api.to_canonical_json(json).encode()
+ user_key.verify_signature(message, signature)
success = True
- except olm.utility.OlmVerifyError:
+ except vodozemac.SignatureException:
success = FalseBy utilizing vodozemac.Ed25519PublicKey.from_base64, the library enforces strict cryptographic parsing rules, which eliminates the signature malleability vulnerability.
Additionally, session persistence logic in src/nio/crypto/sessions.py was rewritten to handle backward compatibility. Because legacy client databases store session states as pickled C-structures, matrix-nio developed a transition mechanism that reads legacy pickles and upgrades them to the new binary format:
+ @classmethod
+ def from_pickle(
+ cls,
+ pickle: bytes,
+ creation_time: datetime,
+ passphrase: str = "",
+ use_time: Optional[datetime] = None,
+ ) -> Session:
+ upgrade_pickle = False
+ try:
+ pickle_key = derive_pickle_key(passphrase)
+ _session = vodozemac.Session.from_pickle(pickle.decode(), pickle_key)
+ except vodozemac.PickleException:
+ pickle_key = passphrase.encode()
+ _session = vodozemac.Session.from_libolm_pickle(pickle.decode(), pickle_key)
+ upgrade_pickle = TrueThis migration logic detects when a database record contains a libolm pickled session, decrypts it using the old format, and then marks the session for re-serialization using vodozemac. This prevents data loss for existing users while upgrading them to a secure state.
Exploitation of the timing side-channels in libolm (CVE-2024-45193) requires precise execution measurement. An attacker sharing a physical host or positioned on an adjacent network could send crafted ciphertext payloads to the client and measure the exact timing response of the decryption process. Over thousands of measurements, statistical analysis can isolate the cache hit/miss latency differences of the non-constant-time AES engine. This allows the attacker to reconstruct the private keys, compromising all past and future encrypted communication for that session.
For the protocol confusion vulnerability (CVE-2022-39255), the threat model assumes a compromised or malicious Matrix homeserver. Because the protocol engine fails to bind session identity keys with specific room identifiers, the homeserver can perform a replay or redirection attack. When an authorized user transmits an encrypted message, the homeserver intercepts the ciphertext and forwards it to a different room. The receiving client decrypts the message, falsely assuming the message was intended for the current room context, which breaks the confidentiality boundaries of the system.
These exploitation vectors do not require user interaction beyond the normal sending and receiving of messages. However, they are highly dependent on the attacker's ability to monitor execution times or control the intermediate server. While weaponized, fully automated exploits are not publicly distributed in the wild, the theoretical viability of these attacks is well-documented in academic cryptographic research, making the deprecation of libolm a high priority for secure deployments.
The impact of this deprecation extends across both security and operational categories. From a security perspective, continuing to use matrix-commander with legacy dependencies exposes users to potential decryption key recovery and unauthorized message disclosure. In secure environments where Matrix is deployed for confidential communication, these vulnerabilities undermine the end-to-end encryption guarantees, reducing the protocol's security to that of standard transport-layer encryption.
From an operational perspective, the unmaintained status of libolm and its Python bindings introduces severe build failures on modern operating systems. For example, as detailed in matrix-commander Issue #204, attempts to install the package under newer python environments fail during the compilation of python-olm. This is due to modern CMake versions removing compatibility with older configuration structures, causing the build pipeline to halt with compilation errors. This effectively prevents automated deployments, upgrades, and normal installation procedures for new users.
Furthermore, a review of the patch implementation reveals potential integration risks. In matrix-nio's migration code, explicit assertion statements were added to the decrypt_megolm_event function, such as assert event.sender_key and assert event.session_id. If a malicious or misconfigured homeserver transmits an envelope that lacks these specific fields, the client code will trigger an uncaught AssertionError. Rather than handling this gracefully as a standard decryption error, the program will terminate abruptly, presenting a potential client-side Denial of Service (DoS) vulnerability.
Remediation of these security risks requires a complete departure from the legacy libolm engine. Because matrix-commander is heavily coupled to its underlying dependencies, users of the Python CLI implementation should transition to the Rust alternative, matrix-commander-rs, located at https://github.com/8go/matrix-commander-rs. The Rust-based client leverages memory-safe, constant-time cryptographic libraries by default, eliminating the compilation blockers and cryptographic vulnerabilities associated with the legacy Python dependencies.
If transitioning to the Rust alternative is not immediately feasible, administrators must ensure that the downstream matrix-nio package is updated to a version that includes the PR #555 merge. This pull request replaces the legacy python-olm module with vodozemac. To apply this fix in existing environments, developers should modify their dependency lock files to pin matrix-nio to the patched release containing commit 71a1c808bc2ae6ea2a6e8effa7c11bd09796c626, and verify that vodozemac >= 0.9 is successfully installed in place of python-olm.
Organizations should also implement defensive controls at the host level. Since the timing attacks rely on precision latency measurements, isolating the client within a sandboxed virtual container can reduce the accuracy of local cache timing attacks. Furthermore, regular session rotation policies can mitigate the impact of potential key leakage, ensuring that even if an attacker recovers a temporal session key, the historical and future message streams remain protected.
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:L/A:N| Product | Affected Versions | Fixed Version |
|---|---|---|
matrix-commander 8go | <= 8.0.6 | Migration to matrix-commander-rs |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-327 (Use of a Broken or Risky Cryptographic Algorithm) |
| Attack Vector | Network / Local Side-Channel / Compromised Homeserver |
| CVSS | 5.9 (Medium) / 4.3 (Medium) |
| EPSS | N/A (Deprecation Advisory) |
| Impact | Information Disclosure / Message Redirection / Build Failures |
| Exploit Status | No active public weaponized exploits (Theoretical PoC) |
| KEV Status | Not Listed |
The product uses a broken or risky cryptographic algorithm or implementation, which can compromise the confidentiality, integrity, or authenticity of communications.
Contao CMS versions 4.1.0 through 5.3.49 and 5.4.0-RC1 through 5.7.11 fail to validate form submission tokens and enforce rate limiting when processing activation email resend requests via HTTP POST, enabling resource exhaustion and account state enumeration.
An information disclosure vulnerability in Contao CMS allows unauthenticated site visitors to view protected page titles, URLs, and text excerpts through search queries when protected page indexing is disabled after previously being enabled.
In Vikunja prior to version 2.6.0, relation creation via the CalDAV endpoint fails to invoke the TaskRelation.CanCreate authorization check. This missing access control allows an authenticated user to establish unauthorized relationships and perform write operations against any task, provided its unique identifier (UID) is known.
A cross-project information disclosure vulnerability in Vikunja allows authenticated users with read access to one project to view private task details from unauthorized projects via subtask expansion parameters.
An information disclosure vulnerability in Vikunja allows authenticated users with read access to a task to expose private email addresses of assigned users through the API task assignees endpoint due to an unmasked database query.
An authorization bypass vulnerability in Vikunja versions prior to v2.6.0 permits authenticated users to delete relationships between tasks across project boundaries without requiring read or write authorization for the target related task.