Skip to content

feat(chat)!: restrict minimessage tags in chat by permission - #136

Merged
TheMeinerLP merged 9 commits into
mainfrom
feat/chat-tag-permissions
Oct 5, 2026
Merged

TheMeinerLP merged 9 commits into
mainfrom
feat/chat-tag-permissions

Conversation

@TheMeinerLP

Copy link
Copy Markdown
Contributor

Summary

  • Chat messages are parsed with only the MiniMessage tags the sender has butterfly.chat.tag.<type> for. butterfly.chat.tag.* grants all types (resolved by LuckPerms).
  • Types: color, decoration, gradient, rainbow, transition, pride, shadow, font, reset, newline, click, hover, insertion, keybind, translatable, selector, score, nbt, sprite, head.
  • Tags the sender may not use stay in the message as literal text. Prefix and name formatting are unaffected.
  • Paper and Minestom share one code path: ChatMessageParser plus LuckPermsAPI.hasPermission in api.
  • Paper parses once per message instead of once per viewer.
  • Closes the hole that let any player send click, hover, selector or nbt tags.

Notes:

  • The spec row shadow_color was renamed to shadow, because MiniMessage 5.2 only has <shadow>.
  • <head> is StandardTags.sequentialHead().
  • README documents all nodes and the migration.

Tests

  • 49 new tests in api (tag factory coverage, permission check, parser scenarios, enum) and 4 new Minestom chat tests.
  • ./gradlew build and ./gradlew :minestom:smokeTest are green.

Before merge

  • Manual Paper test via ./gradlew :bukkit:runServer with LuckPerms: a player without nodes sees <red>x literally; after lp group default permission set butterfly.chat.tag.color true the same message is red; <click:run_command:/help>x</click> has no click event without butterfly.chat.tag.click (report result here).

BREAKING CHANGE

Chat formatting now requires butterfly.chat.tag.<type> permissions. Run lp group default permission set butterfly.chat.tag.* true to restore the old behaviour.

https://claude.ai/code/session_01Wt7kcAoVtZTEALDSX4CxWF

<shadow_color> is not a tag in adventure 5.2.0, only <shadow>; that sample is left out.

Claude-Session: https://claude.ai/code/session_01Wt7kcAoVtZTEALDSX4CxWF
Both platforms parse chat messages with ChatMessageParser, which only
interprets tags the sender has butterfly.chat.tag.<type> for. Disallowed
tags stay literal. Paper parses once per message instead of per viewer.

BREAKING CHANGE: chat formatting now requires butterfly.chat.tag.<type> permissions; grant butterfly.chat.tag.* to the default group to restore the old behaviour.

Claude-Session: https://claude.ai/code/session_01Wt7kcAoVtZTEALDSX4CxWF
@TheMeinerLP
TheMeinerLP requested a review from a team as a code owner October 5, 2026 19:03
@github-actions

github-actions Bot commented Oct 5, 2026

Copy link
Copy Markdown
Contributor

Test results

 51 files   51 suites   35s ⏱️
128 tests 128 ✅ 0 💤 0 ❌
384 runs  384 ✅ 0 💤 0 ❌

Results for commit 6ef4ef3.

@TheMeinerLP
TheMeinerLP merged commit 09e3e9f into main Oct 5, 2026
8 checks passed
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