Skip to content

fix: escape relying party text in locally built consent messages - #895

Draft
AntonioVentilii wants to merge 1 commit into
mainfrom
escape-relying-party-text-in-fallback-consent-message
Draft

fix: escape relying party text in locally built consent messages#895
AntonioVentilii wants to merge 1 commit into
mainfrom
escape-relying-party-text-in-fallback-consent-message

Conversation

@AntonioVentilii

@AntonioVentilii AntonioVentilii commented Aug 13, 2026

Copy link
Copy Markdown
Collaborator

Motivation

When a targeted ledger does not implement ICRC-21, the library builds the consent message itself, and values the relying party controls were interpolated in that Markdown as they are. The ICRC-1 memo is arbitrary bytes decoded to UTF-8, so it can carry Markdown formatting or HTML markup into the message a wallet renders for approval. A payload as short as <button style=zoom:99> fits in the 32 byte memo every conforming ledger accepts, and in a wallet rendering the message as HTML it becomes a control on the approval screen. The token symbol, read from the canister the relying party asks to call, is chosen by it too.

Escaping the angle brackets alone would not be enough: Markdown misleads on its own with headings, links, emphasis, or a line impersonating a field the wallet displays.

Changes

  • New src/utils/markdown.utils.ts. inlineCode renders a text as an inline code span, delimited by more backticks than the longest run it contains so it cannot close its own span. escapeMarkdown backslash escapes the characters Markdown gives a meaning to, angle brackets included. Both replace control characters, line breaks and invisible formatting characters with a space.
  • The memo, hex fallback included, becomes inline code in buildMemo, shared by the icrc1_transfer, icrc2_approve and icrc2_transfer_from builders.
  • Those builders escape the token symbol, keeping the amount lines readable.

Amounts, dates and accounts come from decoded numbers or encodeIcrcAccount, so they cannot carry syntax. Still possible: the memo is displayed, so it can hold misleading wording, look alike glyphs or a plain text URL, and bounding its length stays a wallet concern.

Tests

Unit tests for both helpers, and per builder a memo with markup, one with Markdown, one impersonating a section, and a symbol with markup. Plain text memos display as before. Ran format, lint, test and build, all passing.

The memo is rendered as an inline code span and the token symbol is Markdown escaped, so that neither can carry formatting or markup into the message a wallet displays for approval.
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