Environment
- WoW retail 12.x ("Midnight"), Interface 120001
- BugGrabber capture cluster 2026-08-19 (session with ~3,900 chat-pipeline secret errors attributed to BetterFriendlist)
- BetterFriendlist v2.8.4/2.8.5 — verified against current
main
Remaining unguarded hook in the already-gated family
v2.8.4/2.8.5 correctly gates most hooks that run inside Blizzard's chat pipeline on secret-value clients (e.g. PanelTemplates_TabResize at BetterFriendlist.lua:289, PanelTemplates_SelectTab/DeselectTab in ElvUISkin.lua:558-572, the C_FriendList.RemoveFriendByIndex replacement gated via GlobalSync.lua:154). One member of that family is still installed unconditionally:
-- Utils/ClassicCompat.lua, InstallGuildMOTDChatHooks()
if not guildMOTDChatUtilHookInstalled and ChatFrameUtil and ChatFrameUtil.DisplayGMOTD then
local ok = pcall(hooksecurefunc, ChatFrameUtil, "DisplayGMOTD", CacheGuildMOTDFromChatFrame)
...
end
if not guildMOTDChatGlobalHookInstalled and type(ChatFrame_DisplayGMOTD) == "function" then
pcall(hooksecurefunc, "ChatFrame_DisplayGMOTD", CacheGuildMOTDFromChatFrame)
...
end
These callbacks execute inside Blizzard's chat-frame code path; on 12.x they taint the rest of the dispatch, after which later Blizzard steps fail with exactly the documented signature (ChatHistory_GetToken strlower → "attempt to perform string conversion on a secret string value", ChatHistory_GetAccessID forbidden-table index, edit-box SetText of secret text — ×71/x2729/x1100 in the captured session).
Proposed remediation (validated locally, +8 lines, behavior-neutral)
Apply the same gate the sibling hooks already use:
local function InstallGuildMOTDChatHooks()
if not hooksecurefunc then
return
end
-- Secret-value clients: these hooks run inside Blizzard's chat pipeline and
-- their callbacks taint the execution context, so later steps in the same
-- chain (ChatHistory_GetToken/GetAccessID during message dispatch) fail with
-- "secret string conversion"/"index forbidden table" errors. The GUILD_MOTD
-- event callback below already caches the MOTD without hooking chat.
if BFL.HasSecretValues or issecretvalue then
return
end
... existing hook installs ...
MOTD caching continues unchanged via the existing GUILD_MOTD event callback, so no feature is lost.
Environment
mainRemaining unguarded hook in the already-gated family
v2.8.4/2.8.5 correctly gates most hooks that run inside Blizzard's chat pipeline on secret-value clients (e.g.
PanelTemplates_TabResizeat BetterFriendlist.lua:289,PanelTemplates_SelectTab/DeselectTabin ElvUISkin.lua:558-572, theC_FriendList.RemoveFriendByIndexreplacement gated viaGlobalSync.lua:154). One member of that family is still installed unconditionally:These callbacks execute inside Blizzard's chat-frame code path; on 12.x they taint the rest of the dispatch, after which later Blizzard steps fail with exactly the documented signature (
ChatHistory_GetTokenstrlower → "attempt to perform string conversion on a secret string value",ChatHistory_GetAccessIDforbidden-table index, edit-boxSetTextof secret text — ×71/x2729/x1100 in the captured session).Proposed remediation (validated locally, +8 lines, behavior-neutral)
Apply the same gate the sibling hooks already use:
MOTD caching continues unchanged via the existing
GUILD_MOTDevent callback, so no feature is lost.