Skip to content

security: bind a fetched KeyPackage to the requested signer (group add path) - #202

Open
xAlisher wants to merge 1 commit into
logos-messaging:mainfrom
xAlisher:security/keypackage-device-binding
Open

security: bind a fetched KeyPackage to the requested signer (group add path)#202
xAlisher wants to merge 1 commit into
logos-messaging:mainfrom
xAlisher:security/keypackage-device-binding

Conversation

@xAlisher

@xAlisher xAlisher commented Aug 8, 2026

Copy link
Copy Markdown

What

On the group add path, a KeyPackage fetched from the registry for a requested signer id is validate()d but never checked to belong to that signer — the member id is read from the package's own credential. A registry that returns an attacker's (validly self-signed) package for a victim's id inserts the attacker's leaf under the victim's identity: a confidentiality break + sender-attribution spoof. validate() isn't meant to enforce this binding; the AS/application layer is.

Fix

Bind the validated leaf's signature_key (hex) to the requested signer id in both GroupV1::key_package_for_signer and GroupV2::add_member, rejecting a mismatch. Bind to the key, not the credential bytes — an impostor can copy an id into a credential but cannot sign a leaf with the victim's key.

Notes

  • Courtesy patch from the downstream Peers Android fork, which fixed + shipped this on our side and carries it as a fork patch. Coordinated privately via the libchat security advisory (GHSA-82q9-xqc8-636c); acknowledged as a known issue and slated for the account redesign — offered here as an interim; take it or fold it in as you prefer.
  • Scoped to the add path. The inbound-attribution equivalent (derive the sender from the authenticated signer key — e.g. de-mls member_signature_key — rather than the credential) is the separate structural change you flagged; not included here.
  • Reported by @x0net.

…oup add path

On the group add path, a KeyPackage fetched from the registry for a requested
signer id is validated but never checked to belong to that signer: the member id
is read from the package's own credential. A registry that returns an attacker's
(validly self-signed) package for a victim's id therefore inserts the attacker's
leaf under the victim's identity — a confidentiality break and sender-attribution
spoof. validate() is not meant to enforce this; the application (AS) layer is.

Bind the validated leaf's signature_key (hex) to the requested signer id in both
GroupV1::key_package_for_signer and GroupV2::add_member, rejecting a mismatch.
Bind to the key, not the credential bytes: an impostor can copy an id into a
credential but cannot sign a leaf with the victim's key.

Courtesy patch from the downstream Peers fork; coordinated via the libchat
security advisory. Reported by @x0net.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@xAlisher

xAlisher commented Aug 8, 2026

Copy link
Copy Markdown
Author

cc @x0net — thank you again for the careful report that surfaced this. You're credited on the fix and here. The downstream fix shipped in Peers v0.9.7 (both the core add-path binding and the #239 offline-contact-card injection point); this PR offers the upstream binding as a courtesy interim. The inbound-attribution variant you flagged is tracked separately (upstream-gated behind de-mls #143 + a libchat re-pin).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant