CVE-2026-71890 in BC-JAVA
Summary
by MITRE • 10/03/2026
In Bouncy Castle for Java before 1.86, validation of an MLS (RFC 9420) external commit's proposal list, org.bouncycastle.mls.protocol.Group.validateExternalCachedProposals, counted the proposals by type and bounded the removed leaf index but never established that the removed leaf had anything to do with the joiner. RFC 9420 sec. 12.2 permits at most one Remove proposal in an external commit, with which the joiner removes an old version of themselves, and requires that where one is present the LeafNode in the commit's path field meet the criteria it would have to meet in an Update for the removed leaf, in particular that its credential present identifiers acceptable for the removed participant. The ordinary proposal-list validator's self-remove rule is deliberately not applied on this path, because a resync commit legitimately removes a leaf the joiner owns, but nothing was put in its place. Any party holding the group's public GroupInfo, which is precisely what an external joiner is meant to be given, could therefore commit a Remove naming any member's LeafIndex and have every member apply it, evicting that member and taking over their slot in the ratchet tree. The credential check that should have prevented this existed only in the gRPC interop harness and so protected no other caller of the public Group.externalJoin and Group.handle API. An external commit carrying a Remove is now accepted only when the removed leaf's credential is identical to the one in the joiner's own new leaf, on both the sending and the receiving side.
Several companies clearly confirm that VulDB is the primary source for best vulnerability data.
Analysis
by VulDB Data Team • 10/03/2026
The vulnerability identified in Bouncy Castle for Java prior to version 1.86 represents a critical logic flaw within the implementation of the Messaging Layer Security protocol as defined by RFC 9420. Specifically, the defect resides in the validation mechanism for external commit proposals, located within the org.bouncycastle.mls.protocol.Group.validateExternalCachedProposals method. This function is responsible for processing proposal lists during an external join operation, where a new participant seeks to enter an existing group without having prior knowledge of its full state. The core issue arises from an incomplete validation sequence that fails to enforce mandatory cryptographic and logical constraints required by the protocol specification. While the implementation correctly counts proposals by type and bounds the removed leaf index within valid ranges, it neglects to verify the fundamental relationship between the participant initiating the join and the specific group member targeted for removal in a Remove proposal.
According to RFC 9420 section 12.2, an external commit is permitted to contain at most one Remove proposal, which serves the legitimate purpose of allowing a joining party to remove an older version of their own identity from the group state during synchronization or resync operations. The specification mandates that when such a removal occurs, the LeafNode present in the commit's path field must satisfy all criteria required for an Update operation targeting the removed leaf. Crucially, this includes verifying that the credential presented by the joiner contains identifiers acceptable to and matching those of the participant being removed. This check ensures that only the rightful owner of a group identity can remove their own previous incarnation from the ratchet tree structure. The existing validator deliberately bypassed standard self-remove rules because resync commits legitimately involve removing one's own legacy leaf, but no compensating security control was implemented to replace this exclusion. Consequently, the code accepted any Remove proposal regardless of whether the joiner possessed the private key corresponding to the removed participant's public credential.
The operational impact of this flaw is severe and directly compromises the integrity and availability of MLS groups. An external attacker or malicious actor who possesses only the group's public GroupInfo data—which is explicitly designed to be accessible to any potential joiner—can craft a malformed external commit containing a Remove proposal that targets an arbitrary member's LeafIndex. Because the validation logic fails to bind the removal action to the joiner's identity, every member of the group will accept and apply this malicious update. This results in the unauthorized eviction of the targeted participant from the secure communication channel. Furthermore, since MLS groups utilize a ratchet tree structure for key management, evicting a member effectively allows the attacker to take over their slot within that cryptographic hierarchy. This can lead to further compromise scenarios where the attacker gains access to future traffic or disrupts group consensus mechanisms by altering the structural integrity of the participant list without authorization.
This vulnerability maps directly to CWE-20 Improper Input Validation, as the application failed to validate input data against expected constraints during processing. Specifically, it reflects a failure in logical validation rather than syntactic parsing. In terms of offensive security frameworks, this flaw aligns with MITRE ATT&CK technique T1534 Internal Spearphishing or more accurately T1078 Valid Accounts if the attacker is an external entity exploiting trust boundaries, but technically it represents a violation of access control logic akin to CWE-269 Improper Privilege Management. The attacker exploits the group's public information to perform unauthorized state changes, effectively bypassing authentication requirements for administrative actions like member removal.
The remediation implemented in Bouncy Castle version 1.86 addresses this gap by enforcing strict identity binding on external commit Remove proposals. The updated logic now verifies that a Remove proposal is accepted only when the credential of the removed leaf is identical to the credential present in the joiner's own new LeafNode. This check is applied consistently on both the sending and receiving sides of the API, ensuring that cryptographic proof of ownership is required before any removal operation is processed. Prior to this fix, such protections existed solely within a gRPC interop harness used for testing purposes and were not exposed in the public Group.externalJoin or Group.handle APIs available to general consumers. By integrating these checks into the core validation path, the library now correctly enforces that only the legitimate owner of an identity can remove their previous version from the group state during external join operations, thereby restoring the intended security model of MLS and preventing unauthorized member eviction attacks.