promotional bannermobile promotional banner

SpeakinSpell: Reeee

You can say things in chat when casting any spell or ability. Configurable.

File Details

SpeakinSpell Reeee 2.0.7.zip

  • R
  • Apr 27, 2026
  • 704.54 KB
  • 23
  • 12.0.5+2
  • Retail

File Name

SpeakinSpell Reeee 2.0.7.zip

Supported Versions

  • 12.0.5
  • 12.0.1
  • 12.0.0

Complete: 2.0.7 Kutjara.Wiya.Tiapanpa


Concern grouping: [OPS] = structure & organisation · [BACKEND] = speech.lua, wowevents.lua, data.lua, utils.lua, network.lua, spellbookManager.lua, SpeakinSpell.lua, loader.lua · [GUI] = SpeakinSpell_GUI/ module · [CONTENT] = locale strings, default speeches, i18n · [DEFAULTS] = SpeakinSpell_Defaults/ module · [PATCH] = SpeakinSpell_Patches/ module


[BACKEND] Aura Detection Framework Rewrite

-- The previous CLEU-based aura detection approach was deprecated for this use case. A new framework was written to detect player auras via UNIT_AURA directly in loader.lua, supplementing CLEU which is suppressed inside instances.

  • [x] TODO(02_high-backend-refactor-proficient+lua+wow): Replace deprecated COMBAT_LOG_EVENT_UNFILTERED aura detection with a UNIT_AURA framework in loader.lua. Implement full-update (isFullUpdate) and incremental (addedAuras / removedAuraInstanceIDs) paths with PlayerAuraCache as the backing store.
  • [x] TODO(02_high-backend-bug-proficient+lua+wow): Gate CLEUFrame initialisation with SpeakinSpell.PlayerInCombat = false and SpeakinSpell.PlayerAuraCache = SpeakinSpell.PlayerAuraCache or {} before SetScript registration to prevent uninitialised state on first event.
  • [x] TODO(02_high-backend-bug-proficient+lua+wow): Add post-combat delay to PlayerInCombat flag clear. PLAYER_REGEN_ENABLED fires before the server finishes resolving obfuscation; defer flag clear by one tick via C_Timer.After(0, ...) to give the API time to settle.
  • [ ] TODO(03_medium-backend-refactor-routine+lua+wow): Migrate CLEUFrame event registration from loader.lua to wowevents.lua to consolidate event registration in the correct module. Currently blocked by an undiagnosed break that occurs when the call is moved.

Status: Aura detection framework complete and tested. CLEU migration deferred pending investigation of break-on-move.


[BACKEND] Secret String Hardening — pcall Sanitisation Deprecation

-- Empirical testing confirmed that pcall does not intercept secret string taints. Secret strings pass through pcall silently and only throw when actually used (compared, concatenated, passed to tostring). The GetSafeString / GetSafeUnitName pattern has been removed throughout and replaced with flag-based gating.

  • [x] TODO(01_critical-security-bug-proficient+lua+wow): Remove GetSafeString and GetSafeUnitName pcall wrappers from loader.lua. These helpers provide false confidence — secret strings pass through pcall silently and remain tainted. Replace all usage sites with the PlayerInCombat or IsInInstance() flag gate.
  • [x] TODO(01_critical-security-bug-proficient+lua+wow): Remove GetSafeString(spellInfo.name) from CacheAuras and addedAuras blocks in loader.lua. C_Spell.GetSpellInfo reads from the client spell database and is not server-sourced; its return value is constitutionally safe. Use spellInfo.name directly after a C_Spell.GetSpellInfo call with no further sanitisation.
  • [x] TODO(01_critical-security-bug-proficient+lua+wow): Remove sourceUnit from the PlayerAuraCache entry structure. It was only ever populated via GetSafeString(aura.sourceUnit), which is now confirmed ineffective, and no downstream path uses the cached value.

Status: Complete. pcall sanitisation pattern fully removed and replaced with flag gating throughout.


[BACKEND] Secret String Hardening — Instance and Combat Gating

-- UnitName and related unit-query API calls return secret (obfuscated) strings inside instances regardless of combat state. The existing PlayerInCombat flag was insufficient alone; all affected sites now gate on PlayerInCombat or IsInInstance(). IsInInstance() is a pure client-side call with no taint risk.

  • [x] TODO(01_critical-security-bug-proficient+lua+wow): Gate GetDefaultTarget (data.lua) on PlayerInCombat or IsInInstance(). This is the root call site for all UnitName("target"), UnitName("focus"), and UnitName("mouseover") fallback queries; gating here covers all callers regardless of trigger path.
  • [x] TODO(01_critical-security-bug-proficient+lua+wow): Gate UnitName("target") in OnSlashCommand (slashcommands.lua) on PlayerInCombat or IsInInstance() before assignment to de.target. This was the entry point for the initial reported crash — macro with targeting substitution fired from action bar during combat in an instance.
  • [x] TODO(01_critical-security-bug-proficient+lua+wow): Gate ParentDetectedEvent.target inheritance in ProcessRecursiveUserMacro (slashcommands.lua) on PlayerInCombat or IsInInstance(). Even with OnSlashCommand patched, the parent event's first CreateDetectedEvent pass may have already written a tainted value via GetDefaultTarget; inheritance must be gated separately to prevent propagation into the recursive call.
  • [x] TODO(01_critical-security-bug-proficient+lua+wow): Gate SearchOrder[3] (substitutions.lua) on PlayerInCombat or IsInInstance(). This is the generic UnitName(sk.key) fallback covering all unit-ID substitution tokens: <party1–5>, <raid1–40>, <arena1–5>, <partypet1–5>, <mouseover>, <focus>, <pet>, <playertarget>, <playertargettarget>, and hyphenated name-target chains.
  • [x] TODO(01_critical-security-bug-proficient+lua+wow): Gate SubstitutionFunctions["selected"] (substitutions.lua) on PlayerInCombat or IsInInstance(). Direct UnitName("target") call; same vulnerability class as the original crash.
  • [x] TODO(02_high-security-bug-proficient+lua+wow): Gate NameToUnitID (utils.lua) on PlayerInCombat or IsInInstance(). Function iterates the full NameToUnitIDSearchList calling UnitName on every entry; used by targetclass, targetrace, and SubstituteGender. All callers handle nil gracefully.
  • [x] TODO(02_high-security-bug-proficient+lua+wow): Gate UnitName(de.target) NPC detection check in targetclass (substitutions.lua) on PlayerInCombat or IsInInstance(). If unsafe, skip the NPC check and return the class directly; a missed NPC tag is a cosmetic loss rather than a taint error.
  • [x] TODO(02_high-security-bug-proficient+lua+wow): Gate SubstituteGender (substitutions.lua) unit sex query block on PlayerInCombat or IsInInstance(). UnitSex returns an integer and cannot produce a secret string, but passing a tainted argument to any API call in a restricted frame propagates taint to subsequent calls. Return false (unknown gender) to let the caller use the ungendered fallback form.
  • [x] TODO(01_critical-security-bug-proficient+lua+wow): Gate CacheAuras full-update path (loader.lua) on PlayerInCombat or IsInInstance(). Full update fires on zone entry including entering instances; the cache must be cleared on full update but repopulation must be deferred until outside a restricted context.

Status: Complete. All identified UnitName and unit-query call sites gated. IsInInstance() confirmed to cover the out-of-combat-but-instanced case that PlayerInCombat alone misses.


[BACKEND] Secret String Hardening — Player Name Cache

-- UnitName("player") is safe at login but calling it during tainted execution frames can propagate taint to subsequent API calls in the same tick even if the return value itself is clean. Cached at login and used throughout in place of live calls.

  • [x] TODO(02_high-security-refactor-competent+lua+wow): Cache UnitName("player") at login to SpeakinSpell.RuntimeData.PlayerName. Replace all UnitName("player") calls in wowevents.lua and loader.lua stub targets with SpeakinSpell.RuntimeData.PlayerName or UnitName("player"). The or fallback covers the narrow pre-load window before OnVariablesLoaded completes, at which point no restricted context exists.
  • [x] TODO(02_high-security-refactor-competent+lua+wow): Replace SubstitutionFunctions["caster"] (substitutions.lua) live UnitName("player") call with SpeakinSpell.RuntimeData.PlayerName cache lookup.

Status: Complete. All UnitName("player") call sites in event stubs replaced.


[GUI] ChannelTable — Nil Guard on Channel Select

-- ChannelTable is built during OnVariablesLoaded. If the GUI fires a channel selection event before that completes, CurrentMessagesGUI_OnChannelSelect would attempt to index a nil table.

  • [x] TODO(02_high-gui-bug-competent+lua+wow): Add lazy-init nil guard to CurrentMessagesGUI_OnChannelSelect (currentmessages.lua) before self.ChannelTable is indexed. If ChannelTable is nil, call CreateChannelTable() immediately as a fallback rather than moving or duplicating the deferred initialisation, since the deferral in OnVariablesLoaded is intentional.

Status: Complete.


[BUG] Minimap Icon — Missing (Unresolved — Carried to 2.0.8)

-- The minimap icon ceased rendering during this cycle. Cause has not been identified; no correlation with any specific patch has been established.

  • [ ] TODO(02_high-ui-bug-competent+lua+wow): Investigate missing minimap icon. Confirm minimapbutton.lua registration is completing correctly and that LibDBIcon-1.0 is receiving the broker object. Check whether the loader.lua framework changes affected load order or frame creation timing. Failing that, assess need for exorcism.

Status: Unresolved. Carried forward to 2.0.8.