Skip to content

fix(imessage): normalize leading echo-cache corruption bytes#73985

Closed
openclaw-clownfish[bot] wants to merge 1 commit into
mainfrom
clownfish/ghcrawl-191459-agentic-merge
Closed

fix(imessage): normalize leading echo-cache corruption bytes#73985
openclaw-clownfish[bot] wants to merge 1 commit into
mainfrom
clownfish/ghcrawl-191459-agentic-merge

Conversation

@openclaw-clownfish

Copy link
Copy Markdown
Contributor

Summary

  • Strip only known leading iMessage attributedBody corruption markers from echo-cache text keys before comparison.
  • Preserve interior tabs, line breaks, U+FFFD text, and other user content so text-only echo matching does not become lossy.
  • Add focused regression coverage for delayed reflected inbound iMessage text with leading corruption bytes.

Canonical issue: #41330. Related issue: #59973. Source credit: @maguilar631697 via #62191. Preflight also mentions replacement #73891, but it must be hydrated before reuse or merge.

Validation: pnpm test extensions/imessage/src/monitor/monitor-provider.echo-cache.test.ts; pnpm check:changed.

ProjectClownfish replacement details:

@openclaw-clownfish openclaw-clownfish Bot added the clawsweeper Tracked by ClawSweeper automation label Apr 29, 2026
@aisle-research-bot

aisle-research-bot Bot commented Apr 29, 2026

Copy link
Copy Markdown

🔒 Aisle Security Analysis

We found 1 potential security issue(s) in this PR:

# Severity Title
1 🔵 Low Over-permissive echo-cache text normalization can drop attacker-crafted inbound iMessages (echo suppression collision)
1. 🔵 Over-permissive echo-cache text normalization can drop attacker-crafted inbound iMessages (echo suppression collision)
Property Value
Severity Low
CWE CWE-180
Location extensions/imessage/src/monitor/echo-cache.ts:45-50

Description

normalizeEchoTextKey() strips a broad class of leading characters (all C0/C1 control codes, DEL, and U+FFFD/U+FFFE/U+FFFF) before trimming and using the result as the echo-deduplication key.

This key is used by SentMessageCache.has() to decide whether to drop an inbound message as an echo (see resolveIMessageInboundDecision() returning { kind: "drop", reason: "echo" }).

Impact:

  • A remote sender who can transmit messages beginning with any stripped codepoint (notably U+FFFD ("�"), which is commonly copy/pasteable) can craft an inbound message whose normalized text matches a recently-sent outbound agent message.
  • If sent within the echo TTL window (4 seconds), the inbound message will be treated as a reflected echo and ignored/dropped, causing message suppression (logic/DoS).
  • In group chats, the echo scope is per-chat (not per-sender), so any participant can trigger suppression of their own inbound message when it normalizes to a recent outbound message in that chat.

Vulnerable code:

function normalizeEchoTextKey(text: string | undefined): string | null {
  if (!text) {
    return null;
  }
  const normalized = stripLeadingIMessageEchoCorruption(text.replace(/\r\n?/g, "\n")).trim();
  return normalized ? normalized : null;
}

While the intent is to handle an iMessage echo corruption artifact, applying this stripping universally to all inbound message text expands canonicalization and introduces collision/suppression risk (CWE-180).

Recommendation

Tighten the normalization to reduce attacker-controlled collisions:

  • Prefer stripping only the specific, observed echo artifact(s) and only in the contexts where they occur (e.g., only for is_from_me self-echo handling, or only when the message originates from the local Messages DB fields known to include the corruption).
  • Avoid stripping printable characters like U+FFFD when the message is not a confirmed echo candidate.

Example approach (gating the stripping behind an explicit flag):

function normalizeEchoTextKey(text: string | undefined, opts?: { stripLeadingCorruption?: boolean }): string | null {
  if (!text) return null;
  const lf = text.replace(/\r\n?/g, "\n");
  const maybeStripped = opts?.stripLeadingCorruption ? stripLeadingIMessageEchoCorruption(lf) : lf;
  const normalized = maybeStripped.trim();
  return normalized ? normalized : null;
}

Then call with stripLeadingCorruption: true only when handling known local echo-corruption cases, keeping inbound-from-others matching strict.


Analyzed PR: #73985 at commit febe43f

Last updated on: 2026-04-29T02:45:08Z

@openclaw-barnacle openclaw-barnacle Bot added channel: imessage Channel integration: imessage size: S r: too-many-prs Auto-close: author has more than twenty active PRs. labels Apr 29, 2026
@openclaw-barnacle

Copy link
Copy Markdown

Closing this PR because the author has more than 10 active PRs in this repo. Please reduce the active PR queue and reopen or resubmit once it is back under the limit. You can close your own PRs to get back under the limit.

@vincentkoc vincentkoc reopened this Apr 29, 2026
@openclaw-barnacle openclaw-barnacle Bot added r: too-many-prs Auto-close: author has more than twenty active PRs. and removed r: too-many-prs Auto-close: author has more than twenty active PRs. labels Apr 29, 2026
@greptile-apps

greptile-apps Bot commented Apr 29, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR fixes iMessage echo-cache deduplication failures caused by leading attributedBody corruption bytes (control characters, C1 characters, and Unicode noncharacters) that iMessage prepends to reflected inbound text but not to the originally-sent text. The fix adds a leading-only stripping pass in normalizeEchoTextKey so both the stored and lookup keys normalize to the same value, restoring echo suppression without discarding interior replacement characters or line-structure content.

Confidence Score: 5/5

Safe to merge — the fix is well-scoped, symmetric across store and lookup paths, and backed by focused regression tests.

The logic is correct: normalization is applied identically to both remember and has paths so no false positives can be introduced. The corruption-code predicate correctly excludes mid-message content (emoji, interior U+FFFD, tabs, newlines after the leading position). Tests cover the primary regression scenario and the interior-preservation invariant. No security surface is affected.

No files require special attention.

Reviews (1): Last reviewed commit: "fix(imessage): normalize leading echo-ca..." | Re-trigger Greptile

@clawsweeper

clawsweeper Bot commented Apr 29, 2026

Copy link
Copy Markdown
Contributor

Codex review: keeping this open for maintainer follow-up; there is still a little grit to resolve.

Keep this PR open. Current main and the latest release still lack leading iMessage attributedBody corruption-marker normalization in the sent-message echo cache, so the PR is not obsolete or implemented. It should be reviewed or consolidated with the overlapping open Clownfish PR, and the security review should address the non-injective text normalization risk for group echo scopes.

Best possible solution:

Keep the PR open for maintainer review, preferably as the current candidate or after consolidating with #73891. The best fix should keep the normalization narrowly scoped to proven leading iMessage attributedBody artifacts, add regression tests for corrupted-prefix echoes and preserved interior content, and either address or explicitly bound the group-scope false-positive risk. Any TTL change for #59973 should be decided separately or covered by a narrower follow-up.

What I checked:

Likely related people:

Remaining risk / open question:

Codex review notes: model gpt-5.5, reasoning high; reviewed against 180033eeaedd.

@vincentkoc

Copy link
Copy Markdown
Member

Thanks for pushing this. We merged the narrower canonical fix in #73942: #73942, merge be445dd. This broader control-byte variant had a real group-scope false-positive risk called out in review; #73942 avoids that by keeping normalization leading-marker-only and preserving tabs, line breaks, and interior markers. Testbox proof: tbx_01kqbp2m7s1mn1nd4fhgnp74wk focused iMessage tests plus check:changed passed. Closing this overlap.

@vincentkoc vincentkoc closed this Apr 29, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

channel: imessage Channel integration: imessage clawsweeper Tracked by ClawSweeper automation size: S

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant