Skip to content

fix: 🐛 panic on unknown keys#169

Merged
highesttt merged 4 commits into
mainfrom
168-bug-failed-to-decrypt-the-data-data-authentication-failure
Jun 3, 2026
Merged

fix: 🐛 panic on unknown keys#169
highesttt merged 4 commits into
mainfrom
168-bug-failed-to-decrypt-the-data-data-authentication-failure

Conversation

@highesttt

Copy link
Copy Markdown
Collaborator

This pr adds extra logs when handling messages and fixes a panic on receiving unknown keys.
Confirmed to work by 2 users

@highesttt highesttt linked an issue Jun 3, 2026 that may be closed by this pull request
@indent-zero

indent-zero Bot commented Jun 3, 2026

Copy link
Copy Markdown
Contributor
PR Summary

Hardens the LINE bridge against WASM-side crypto panics that crash the bridge process (issue #168 "Failed to decrypt the data: data authentication failure") and adds richer logging for group-decrypt failures. All six WASM crypto entry points most likely to fault on bad inputs are now wrapped in panic-recovery shims that surface the fault as a normal Go error, so the bridge keeps running and the message is reported as undecryptable instead of taking down the goroutine. Also merges main and rewires opType plumbing so the new structured group-decrypt logs work in both the live and backfill paths.

  • Add ltsmPanicError plus six *PanicSafe wrappers in pkg/runner.go around E2EEKey.exportKey, E2EEChannel.unwrapGroupSharedKey, E2EEChannel.encryptV1, E2EEChannel.encryptV2, E2EEChannel.decryptV1, and E2EEChannel.decryptV2; recovery runs under the caller's already-held r.mu lock and converts panics to errors.
  • Route LoginUnwrapKeyChain, ChannelUnwrapGroupSharedKey, ChannelEncryptV1, ChannelEncryptV2, ChannelDecryptV1, and ChannelDecryptV2 through the new wrappers so panics on either send or receive (or login keychain unwrap) no longer crash the bridge.
  • Add e2eeChunkLengths / groupDecryptLogContext helpers in pkg/connector/handle_message.go to standardize group-decrypt failure logs with msg_id, chat_mid, from/to, to_type, op_type, content_type, chunk metadata, optional e2ee_version, and decoded sender_key_id/group_key_id.
  • Emit a new Warn log when DecryptGroupMessage still fails after the group-key refresh retry (previously silent).
  • Merge main and thread opType through decryptMessageBody so the new group-decrypt log context compiles in the post-merge layout; the backfill path in FetchMessages derives opType from msg.From == lc.Mid (matching the existing pattern in backfillRecentMessages).

Issues

All clear! No issues remaining. 🎉

4 issues already resolved
  • The group-decrypt failure logs add Int("key_id", gkID/keyID) at the call site and then groupDecryptLogContext adds Int("group_key_id", ...) from the same msg.Chunks[len-1], so each failure log carries the same value under two field names. Drop one or the other for cleaner logs. (fixed by commit 3d67fcc)
  • Panic recovery is decrypt-only: ChannelEncryptV1 (pkg/runner.go:531) and ChannelEncryptV2 (pkg/runner.go:561) still invoke r.rt.E2EEChannel* directly, so the same class of WASM fault on the outbound path will continue to crash the bridge. Consider wrapping the encrypt fallbacks in matching *PanicSafe helpers. (fixed by commit 3d67fcc)
  • LoginUnwrapKeyChain at pkg/runner.go:355 still calls r.rt.E2EEKeyExportKey(keyPtr) directly, so a WASM panic during keychain export on login can still crash the bridge. Route it through the new exportE2EEKeyPanicSafe wrapper for consistent coverage. (fixed by commit 3d67fcc)
  • Storing goKeys from a WASM-unwrapped group shared key contradicts the Runner struct comment (pkg/runner.go:30-34) that says WASM-unwrapped keys do not have raw private keys due to SKB; if that comment is still accurate, the 32-byte export will silently build an incorrect pure-Go channel in ChannelCreate and produce wrong plaintexts. Either update the comment to reflect that ChannelUnwrapGroupSharedKey now populates goKeys, or drop the new export-and-store branch. (fixed by commit 3d67fcc)

CI Checks

The pull_request CI run (which builds the PR merged against main) fails because main has refactored queueIncomingMessage since this branch forked — the decryption block was extracted into a new decryptMessageBody(msg, portalIDStr) function that does not receive opType. When merged, this PR's calls to groupDecryptLogContext(..., opType) land inside decryptMessageBody, where opType is no longer in scope, producing four undefined: opType errors at pkg/connector/handle_message.go:186/196/200/205. The push CI for the same SHA passes because it builds the branch in isolation. Rebasing on main and threading opType through decryptMessageBody (or moving the new log calls) will resolve all three failing checks.

Failing Build 1.25→ Autofix
  • go build -v ./... fails after the PR is merged onto main with four undefined: opType errors in pkg/connector/handle_message.go. Main extracted decryption logic into decryptMessageBody(msg, portalIDStr) which has no opType parameter, so the PR's groupDecryptLogContext(..., opType) calls no longer compile after the merge.
Failing Lint with 1.25→ Autofix
  • Same root cause as Build 1.25 — the pre-commit Go hooks (go vet, staticcheck) cannot run on a package that fails to compile due to the undefined: opType errors introduced by the merge with main.
Failing build-docker→ Autofix
  • docker build runs go build -o matrix-line ./cmd/matrix-line inside the Alpine builder stage and fails with the same four undefined: opType errors in pkg/connector/handle_message.go for the same merge-conflict reason.

⚡ Autofix All CI Failures

@highesttt highesttt requested a review from Fizzadar June 3, 2026 06:27
@coderabbitai

coderabbitai Bot commented Jun 3, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: f71e4d8b-5fc4-4c10-9824-1bcf11c6cc1d

📥 Commits

Reviewing files that changed from the base of the PR and between 3d67fcc and 64f2bc4.

📒 Files selected for processing (2)
  • pkg/connector/handle_message.go
  • pkg/connector/sync.go
📜 Recent review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: build-docker
  • GitHub Check: Lint with 1.25
  • GitHub Check: build-docker
  • GitHub Check: Lint with 1.25
🧰 Additional context used
📓 Path-based instructions (2)
**/*.go

📄 CodeRabbit inference engine (AGENTS.md)

**/*.go: Use go fmt for code formatting across all Go files
Use goimports with -local "github.com/highesttt/matrix-line-messenger" flag to group project-local imports correctly
Use zerolog for logging throughout the codebase
Do not use Msgf in logging; use Msg with structured fields instead
Use Stringer interface where applicable in Go code

Files:

  • pkg/connector/sync.go
  • pkg/connector/handle_message.go
**/!(ltsm)/**/*.go

📄 CodeRabbit inference engine (AGENTS.md)

**/!(ltsm)/**/*.go: Run staticcheck on all Go files excluding pkg/ltsm package (transpiled WASM code)
Run go vet on all Go files excluding pkg/ltsm package (transpiled WASM code)

Files:

  • pkg/connector/sync.go
  • pkg/connector/handle_message.go
🔇 Additional comments (4)
pkg/connector/handle_message.go (2)

38-75: LGTM!


165-262: LGTM!

pkg/connector/sync.go (2)

186-210: LGTM!


143-185: 💤 Low value

chatMID matches the portal MID expected by decryptMessageBody

  • makePortalID is an identity conversion (networkid.PortalID(userID)), so chatMID := string(params.Portal.PortalKey.ID) matches the LINE MID value used as the portalIDStr input in the live path (portalMIDForMessage in pkg/connector/handle_message.go).

📝 Walkthrough

Summary by CodeRabbit

  • Bug Fixes

    • Improved stability and crash-resilience for encrypted group message operations by converting internal panics into handled errors and updating fallback paths; decryption now considers message direction during backfill.
  • Chores

    • Standardized and enriched diagnostic logging for group decryption, including chunk/metadata summaries and conditional key identifiers to aid troubleshooting.

Walkthrough

Adds panic-safe wrappers around LTSM/WASM E2EE operations and standardizes structured zerolog context for group decryption error logs; replaces ad-hoc logs with a single helper while preserving existing control flow.

Changes

E2EE Group Decryption Safety and Observability

Layer / File(s) Summary
Panic-safe wrapper infrastructure
pkg/runner.go
Internal panic-recovery helpers convert LTSM panics into returned errors for export, unwrap, and V1/V2 encrypt/decrypt operations.
Runner call-site updates to use panic-safe wrappers
pkg/runner.go
LoginUnwrapKeyChain, ChannelUnwrapGroupSharedKey, and WASM fallback paths for ChannelEncryptV1/V2 and ChannelDecryptV1/V2 call panic-safe wrappers instead of invoking LTSM functions directly.
E2EE group decryption logging helpers
pkg/connector/handle_message.go
Adds e2eeChunkLengths and groupDecryptLogContext to compute chunk lengths and build consistent structured log fields (message/chat/op/content, optional e2ee_version, decoded key IDs or decode errors).
Standardized error logging in decryption flow
pkg/connector/handle_message.go
Replaces ad-hoc structured logs with groupDecryptLogContext at prefetch, initial decrypt failure, key fetch/unwrap failure, retry, and post-refresh failure points.

🎯 4 (Complex) | ⏱️ ~45 minutes

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title 'fix: 🐛 panic on unknown keys' directly addresses the main objective of fixing a panic on receiving unknown keys, which is a core part of the changeset.
Description check ✅ Passed The description states the PR adds extra logs and fixes a panic on unknown keys, which aligns with the changes adding logging helpers and panic-recovery wrappers in the codebase.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch 168-bug-failed-to-decrypt-the-data-data-authentication-failure

Comment @coderabbitai help to get the list of available commands and usage tips.

Comment thread pkg/runner.go Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (2)
pkg/connector/handle_message.go (2)

46-75: ⚡ Quick win

Consider adding a godoc comment.

While the function is well-structured and follows zerolog best practices, a brief godoc comment would improve maintainability by documenting its purpose and expected usage pattern.

📝 Suggested godoc addition
+// groupDecryptLogContext enriches a zerolog event with structured fields for E2EE group decryption logging.
+// It includes message metadata, chunk information, and decoded sender/group key IDs when available.
+// Decoding errors are captured as *_error fields rather than omitted.
 func groupDecryptLogContext(evt *zerolog.Event, msg *line.Message, chatMID string, opType int) *zerolog.Event {
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pkg/connector/handle_message.go` around lines 46 - 75, Add a short godoc
comment above the groupDecryptLogContext function that explains its purpose
(building a zerolog event with metadata for group E2EE message decryption
logging), the expected inputs (evt *zerolog.Event, msg *line.Message, chatMID
string, opType int) and key behaviors (which fields are added, when e2ee_version
is included, and that sender/group key IDs are decoded from the last two chunks
if present). Keep it one or two sentences and use the standard Go godoc style
starting with the function name.

134-135: 💤 Low value

Consider consolidating redundant key ID fields.

Each logging call adds Int("key_id", ...) explicitly, and then groupDecryptLogContext also decodes and adds Int("group_key_id", ...) from the message chunks. In normal operation these values should be identical, creating field redundancy in the logs.

While not harmful (and potentially useful for detecting mismatches), you could simplify by either:

  1. Removing the explicit Int("key_id", ...) and relying on the helper's group_key_id field, or
  2. Passing the key ID to the helper and having it use a consistent field name
♻️ Example: Remove explicit key_id field
-groupDecryptLogContext(lc.UserLogin.Bridge.Log.Debug().Err(errFetch).Int("key_id", gkID), msg, portalIDStr, opType).
+groupDecryptLogContext(lc.UserLogin.Bridge.Log.Debug().Err(errFetch), msg, portalIDStr, opType).
     Msg("Prefetch group key before decrypt failed")

Apply similarly to lines 144, 148, and 153. The group_key_id field from the helper provides the same information.

Also applies to: 144-145, 148-149, 153-154

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pkg/connector/handle_message.go` around lines 134 - 135, The logs currently
duplicate the key id by calling Int("key_id", gkID) before invoking
groupDecryptLogContext which itself adds Int("group_key_id", ...) from the
message chunks; remove the explicit Int("key_id", gkID) occurrences (the
Debug().Err(errFetch).Int("key_id", gkID) calls) and rely on
groupDecryptLogContext's group_key_id field for consistency (apply the same
change to the other similar sites noted), or alternatively refactor
groupDecryptLogContext to accept gkID and emit a single canonical field name
(e.g., group_key_id) so only one key-id field appears in logs.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@pkg/runner.go`:
- Around line 148-156: The LoginUnwrapKeyChain flow still calls
r.rt.E2EEKeyExportKey(keyPtr) directly and can panic; update LoginUnwrapKeyChain
to call the existing exportE2EEKeyPanicSafe(keyPtr) helper (the same one used by
ChannelUnwrapGroupSharedKey) instead of calling r.rt.E2EEKeyExportKey directly,
propagate its (exported, err) return values and handle the error as
LoginUnwrapKeyChain currently expects so any panic from E2EEKeyExportKey is
converted to an error rather than crashing.

---

Nitpick comments:
In `@pkg/connector/handle_message.go`:
- Around line 46-75: Add a short godoc comment above the groupDecryptLogContext
function that explains its purpose (building a zerolog event with metadata for
group E2EE message decryption logging), the expected inputs (evt *zerolog.Event,
msg *line.Message, chatMID string, opType int) and key behaviors (which fields
are added, when e2ee_version is included, and that sender/group key IDs are
decoded from the last two chunks if present). Keep it one or two sentences and
use the standard Go godoc style starting with the function name.
- Around line 134-135: The logs currently duplicate the key id by calling
Int("key_id", gkID) before invoking groupDecryptLogContext which itself adds
Int("group_key_id", ...) from the message chunks; remove the explicit
Int("key_id", gkID) occurrences (the Debug().Err(errFetch).Int("key_id", gkID)
calls) and rely on groupDecryptLogContext's group_key_id field for consistency
(apply the same change to the other similar sites noted), or alternatively
refactor groupDecryptLogContext to accept gkID and emit a single canonical field
name (e.g., group_key_id) so only one key-id field appears in logs.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 490424f1-eed9-46e9-a05b-9a67a5ca18d6

📥 Commits

Reviewing files that changed from the base of the PR and between 3142f0f and 5b07ae9.

📒 Files selected for processing (2)
  • pkg/connector/handle_message.go
  • pkg/runner.go
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: build-docker
🧰 Additional context used
📓 Path-based instructions (2)
**/*.go

📄 CodeRabbit inference engine (AGENTS.md)

**/*.go: Use go fmt for code formatting across all Go files
Use goimports with -local "github.com/highesttt/matrix-line-messenger" flag to group project-local imports correctly
Use zerolog for logging throughout the codebase
Do not use Msgf in logging; use Msg with structured fields instead
Use Stringer interface where applicable in Go code

Files:

  • pkg/runner.go
  • pkg/connector/handle_message.go
**/!(ltsm)/**/*.go

📄 CodeRabbit inference engine (AGENTS.md)

**/!(ltsm)/**/*.go: Run staticcheck on all Go files excluding pkg/ltsm package (transpiled WASM code)
Run go vet on all Go files excluding pkg/ltsm package (transpiled WASM code)

Files:

  • pkg/runner.go
  • pkg/connector/handle_message.go
🧠 Learnings (1)
📚 Learning: 2026-05-29T10:13:37.093Z
Learnt from: CR
Repo: beeper/matrix-line-messenger PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-05-29T10:13:37.093Z
Learning: Applies to pkg/ltsm/wbc_generated.go : Do not manually edit `pkg/ltsm/wbc_generated.go` as it is transpiled WASM code

Applied to files:

  • pkg/runner.go
🔇 Additional comments (3)
pkg/connector/handle_message.go (2)

38-44: LGTM!


153-154: Excellent addition: logging decrypt failure after key refresh.

This new log statement provides valuable visibility when decryption fails even after successfully fetching and unwrapping a fresh group key, which helps diagnose persistent E2EE issues.

pkg/runner.go (1)

141-146: LGTM!

Also applies to: 158-186, 498-507, 596-599, 630-634

Comment thread pkg/runner.go
@highesttt highesttt merged commit 663cd34 into main Jun 3, 2026
10 checks passed
@highesttt highesttt deleted the 168-bug-failed-to-decrypt-the-data-data-authentication-failure branch June 3, 2026 19:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

bug: 🐛 Failed to decrypt the data: data authentication failure

1 participant