fix(message): decrypt secretEncryptedMessage MESSAGE_EDIT envelopes - #153
fix(message): decrypt secretEncryptedMessage MESSAGE_EDIT envelopes#153Caio-HD wants to merge 2 commits into
Conversation
WhatsApp now seals message edits in a secretEncryptedMessage envelope
instead of a plaintext protocolMessage, so edits reached consumers as an
opaque blob with no readable text.
Decrypt it with whatsmeow's DecryptSecretEncryptedMessage and rewrite the
message in place to the protocolMessage{MESSAGE_EDIT} shape consumers
already handle. Every failure path forwards the envelope untouched, so a
message is never dropped.
Reviewer's GuideDecrypts WhatsApp MESSAGE_EDIT secretEncryptedMessage envelopes and rewrites them into the legacy plaintext protocolMessage shape so downstream message typing and webhooks see the edited text, with conservative failure handling and targeted tests for the new behavior. Sequence diagram for decrypting MESSAGE_EDIT secretEncryptedMessage envelopessequenceDiagram
participant MyClient
participant MyClientClient as Client
participant EventsMessage as events.Message
MyClient->>EventsMessage: myEventHandler(rawEvt)
activate EventsMessage
MyClient->>EventsMessage: unwrapSecretEncryptedEdit(evt)
alt evt is MESSAGE_EDIT secretEncryptedMessage
MyClient->>MyClientClient: DecryptSecretEncryptedMessage(context, evt)
MyClientClient-->>MyClient: decryptedMessage or error
alt decryptedMessage and targetMessageKey present
MyClient->>MyClient: buildEditProtocolMessage(targetKey, decryptedMessage, timestampMS)
MyClient-->>EventsMessage: evt.Message = rebuiltProtocolMessage
else decryption failed or missing targetMessageKey
MyClient-->>EventsMessage: evt.Message unchanged (envelope forwarded)
end
else not MESSAGE_EDIT secretEncryptedMessage
MyClient-->>EventsMessage: evt.Message unchanged
end
MyClient->>MyClient: utils.GetMessageType(evt.Message)
deactivate EventsMessage
File-Level Changes
Possibly linked issues
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
There was a problem hiding this comment.
Hey - I've left some high level feedback:
- isSecretEncryptedEdit dereferences message without a nil check but the tests expect it to handle nil safely; add an explicit message == nil guard to avoid panics.
- In unwrapSecretEncryptedEdit you call GetSecretEncryptedMessage twice; consider storing the result in a local variable to avoid repeated lookups and make the intent clearer when accessing TargetMessageKey.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- isSecretEncryptedEdit dereferences message without a nil check but the tests expect it to handle nil safely; add an explicit message == nil guard to avoid panics.
- In unwrapSecretEncryptedEdit you call GetSecretEncryptedMessage twice; consider storing the result in a local variable to avoid repeated lookups and make the intent clearer when accessing TargetMessageKey.Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
Address review feedback: secretEncryptedEdit now returns the envelope it matched, so the caller reaches TargetMessageKey from that value instead of looking the envelope up a second time. Also guard the nil message explicitly, matching the style already used by getContextInfoFromMessage in referral.go.
|
Both addressed. secretEncryptedEdit now returns the matched envelope, so the caller reads TargetMessageKey from that value instead of looking it up again. On the nil guard: there was no panic risk, GetSecretEncryptedMessage is a generated getter with a nil-receiver check, and the nil case was already covered by a passing test. Added the explicit guard anyway for consistency with getContextInfoFromMessage in referral.go. |
Description
WhatsApp no longer sends message edits as a plaintext
protocolMessage. The edited content nowarrives sealed in a
secretEncryptedMessageenvelope withsecretEncType: MESSAGE_EDIT, encryptedwith a key derived from the target message secret.
evolution-go forwards that envelope untouched, so
utils.GetMessageTypeclassifies it assecret encryptedand the webhook carries no text at all. Consumers can tell that something wasedited only by parsing the envelope themselves — and they can't read what it says, because the
payload is encrypted.
whatsmeow already solves the decryption:
Client.DecryptSecretEncryptedMessagehandles theMESSAGE_EDITcase, and the whatsmeow version pinned ingo.mod(
v0.0.0-20260630180629-b572e5bcb92b) includes it. This PR just wires it up.In the
*events.Messagehandler the envelope is now decrypted and the message rewritten in placeto the plaintext shape consumers already handle:
Since that is the exact shape WhatsApp used before, no consumer contract changes:
GetMessageTypereturnseditjust as it did for plaintext edits, and the webhook payload nowcarries the corrected text.
Failure behaviour
Every failure path leaves the event exactly as it behaves today — the envelope is forwarded, never
dropped:
ErrOriginalMessageSecretNotFound) → logged, envelope forwarded;targetMessageKey→ logged, envelope forwarded.Known limitation
whatsmeow derives the key from the original message secret (
Store.MsgSecrets), so an edit of amessage the instance never received cannot be decrypted. That is still strictly better than the
current behaviour, where no edit can be read at all.
Related Issue
N/A — reported downstream: edits reach consumers as an empty/opaque message while the original text
stays stale.
Type of Change
Testing
Automated:
go test ./pkg/whatsmeow/service/...— passing, including 5 new tests insecret_edit_test.gocovering envelope detection (
MESSAGE_EDITvsPOLL_EDITvs plain message), the rebuiltprotocolMessageshape, the timestamp being carried over and omitted when unknown, the nilguards, and the end result being typed as
editbyutils.GetMessageType.go vet ./pkg/whatsmeow/service/...— clean.gofmt— clean.Additional Notes
The change is deliberately scoped to
MESSAGE_EDIT. OthersecretEncTypevalues (EVENT_EDIT,POLL_EDIT,POLL_ADD_OPTION) keep their current behaviour, since each one needs its own targetshape and they are not part of this fix.
Summary by Sourcery
Handle WhatsApp message edits sent in secretEncryptedMessage envelopes by decrypting and rewriting them into the existing plaintext edit protocolMessage shape before message typing and webhook delivery.
Bug Fixes:
Enhancements:
Tests: