A display name matching an emoji or channel id corrupts Discord markup, which is not prose either #479

Closed
opened 2026-08-13 14:18:30 +00:00 by coilyco-ops · 0 comments
Member

Residual of #465, found while writing a duplicate fix for it. Demonstrated, not predicted.

mentionSpans treats a URL as opaque and rewrites everywhere else. Discord markup is also not prose, and it also contains name-shaped text.

Reproduction, against merged main

name=trophy                in : nice work <:trophy:1234567890>
                           out: nice work <:<@999>:1234567890>

name=1499488069269590262   in : ask in <#1499488069269590262>
                           out: ask in <#<@999>>

A custom emoji becomes a broken mention inside a broken emoji. A channel reference becomes a user mention nested in a channel reference.

Why it is worth fixing rather than shrugging at

The collision is less likely than 465's — that one needed a member called eco or main, and this needs one called trophy, wave, tada, or a display name that is a snowflake. But emoji names are exactly the kind of thing people call themselves, and the failure is the same shape: the harness rewrites inside a structure whose components are not people.

The existing [^\w<@] prefix guard catches <@ specifically, which is why a user mention survives. It does not catch <:, <#, or <@&.

Scope

Treat Discord markup spans as opaque, the same way mentionSpans already treats links. One more alternation in the span splitter.

Acceptance

  • The two reproductions above come back byte-identical.
  • A name beside markup still resolves, so this bounds where it looks rather than switching the feature off.
  • 465's URL corpus still passes.
**Residual of** https://forgejo.coilysiren.me/coilyco-gaming/sirens-echo/issues/465, found while writing a duplicate fix for it. Demonstrated, not predicted. `mentionSpans` treats a URL as opaque and rewrites everywhere else. **Discord markup is also not prose**, and it also contains name-shaped text. ## Reproduction, against merged `main` ``` name=trophy in : nice work <:trophy:1234567890> out: nice work <:<@999>:1234567890> name=1499488069269590262 in : ask in <#1499488069269590262> out: ask in <#<@999>> ``` A custom emoji becomes a broken mention inside a broken emoji. A channel reference becomes a user mention nested in a channel reference. ## Why it is worth fixing rather than shrugging at The collision is less likely than 465's — that one needed a member called `eco` or `main`, and this needs one called `trophy`, `wave`, `tada`, or a display name that is a snowflake. **But emoji names are exactly the kind of thing people call themselves**, and the failure is the same shape: the harness rewrites inside a structure whose components are not people. The existing `[^\w<@]` prefix guard catches `<@` specifically, which is why a user mention survives. It does not catch `<:`, `<#`, or `<@&`. ## Scope Treat Discord markup spans as opaque, the same way `mentionSpans` already treats links. One more alternation in the span splitter. ## Acceptance - The two reproductions above come back byte-identical. - A name beside markup still resolves, so this bounds where it looks rather than switching the feature off. - 465's URL corpus still passes.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
coilyco-gaming/sirens-echo#479
No description provided.