Skip to content

security: sign UserProfile broadcasts (#145)#155

Merged
intendednull merged 1 commit into
mainfrom
fix/issue-145
Apr 19, 2026
Merged

security: sign UserProfile broadcasts (#145)#155
intendednull merged 1 commit into
mainfrom
fix/issue-145

Conversation

@intendednull
Copy link
Copy Markdown
Owner

Summary

  • UserProfile broadcasts were wrapped in a plain Envelope with no signature, so any peer could broadcast a profile claiming any peer_id and spoof that peer's display name.
  • Added willow_identity::pack_profile / unpack_profile helpers that Ed25519-sign the profile and reject it on receive unless the verified signer equals profile.peer_id.
  • New typed error variant IdentityError::PeerMismatch { claimed, signer }; mismatches are rejected and logged at warn! in the listener.
  • Updated both profile broadcast sites (connect.rs NeighborUp retry + broadcast_profile_via_network) and the receive path in listeners.rs.

Threat addressed

Display-name spoofing on the _willow_profiles topic. Any peer could publish a signed-looking envelope with another peer's peer_id and an arbitrary display_name, which the client would blindly store and render. With this change the receive path drops any profile whose verified Ed25519 signer does not match the claimed peer_id.

Test plan

  • cargo fmt --check
  • cargo clippy -p willow-identity --all-targets -- -D warnings
  • cargo clippy -p willow-client --all-targets -- -D warnings
  • cargo test -p willow-identity — 26 passed, including new pack_and_unpack_profile_accepts_self_signed, unpack_profile_rejects_spoofed_peer_id, unpack_profile_rejects_tampered_bytes
  • cargo test -p willow-client — 74 passed
  • cargo check --target wasm32-unknown-unknown -p willow-client

Closes #145

UserProfile broadcasts were wrapped in a plain Envelope with no signature,
so any peer could broadcast a profile claiming any peer_id and spoof that
peer's display name in the UI.

Replace the unsigned envelope with an Ed25519-signed pack/unpack pair
dedicated to profiles: `willow_identity::pack_profile` signs the profile,
and `unpack_profile` verifies the signature AND that the signer matches
the claimed `profile.peer_id`. Mismatches return a new typed
`IdentityError::PeerMismatch` and are logged at `warn!` on the receive
path. The wire format changes (envelope -> signed envelope); no
deployed consumer depends on the old format.

Closes #145

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@intendednull intendednull merged commit 9579e05 into main Apr 19, 2026
4 checks passed
@intendednull intendednull deleted the fix/issue-145 branch April 19, 2026 05:26
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.

security: UserProfile broadcasts are unsigned — display names can be spoofed

1 participant