Summary
TaskMaster/Ribbon/RibbonController.Intelligence.cs contains ribbon-callback-reachable code paths that dereference Globals without a guard. Before SetGlobals has run, Globals is unassigned, so each site raises a NullReferenceException out of an async void Office handler, where it is neither reported nor observable by the user.
This is the same defect class as #518, but at different call sites. #518 was scoped to the ten Controller.Engines.<member> sites in RibbonViewer.EngineCommands.cs; these sites are in the controller partial and were explicitly held out of that scope (that file is a protected zero-line-diff path in the #505/#506/#518 delivery).
Discovered during the research phase of the bundled #505/#506/#518 delivery (research section 10, item 2).
Environment
- OS/version: Windows 11, Outlook desktop (VSTO add-in host)
- Runtime: .NET Framework 4.8.1, TaskMaster VSTO add-in
- Command/flags used: Outlook Explorer ribbon, Spam Manager and QuickFiler settings menus
- Data source or fixture: Live Outlook profile during add-in startup
Steps to Reproduce
- Reload the TaskMaster add-in so the ribbon is constructed before the controller's
Globals is assigned.
- Invoke a ribbon callback that reaches
RibbonController.Intelligence.cs - for example the Spam Manager "Clear Spam Manager" command, or any of the QuickFiler settings toggles.
- Observe a
NullReferenceException raised inside the controller partial.
Expected Behavior
No ribbon callback raises a NullReferenceException when invoked before initialization completes. Each site degrades gracefully, consistent with the seam pattern established by #503 and extended by #505: host-neutral, unit-tested decision logic behind an injected accessor, with the COM-touching glue left in the [ExcludeFromCodeCoverage] shim.
Actual Behavior
Every listed site dereferences Globals immediately with no guard. Verified against origin/main at f910ff2f:
| Line |
Member |
Expression |
| 220 |
ClearSpamManagerAsync |
Globals.AF... |
| 230 |
ClearSpamManagerAsync |
Globals.Engines.RestartEngineAsync(...) |
| 29-58 |
QuickFiler-settings toggle callbacks |
Globals... |
The list is indicative rather than exhaustive. The fix should begin with a full enumeration of Globals dereferences in that file that are reachable from a ribbon callback.
Logs / Screenshots
Impact / Severity
Same narrow reachable window as #507 and #518: the callback must run before SetGlobals.
Source
From: docs/features/potential/2026-08-08-ribbon-controller-intelligence-unguarded-globals-deref.md
Summary
TaskMaster/Ribbon/RibbonController.Intelligence.cscontains ribbon-callback-reachable code paths that dereferenceGlobalswithout a guard. BeforeSetGlobalshas run,Globalsis unassigned, so each site raises aNullReferenceExceptionout of anasync voidOffice handler, where it is neither reported nor observable by the user.This is the same defect class as #518, but at different call sites. #518 was scoped to the ten
Controller.Engines.<member>sites inRibbonViewer.EngineCommands.cs; these sites are in the controller partial and were explicitly held out of that scope (that file is a protected zero-line-diff path in the #505/#506/#518 delivery).Discovered during the research phase of the bundled #505/#506/#518 delivery (research section 10, item 2).
Environment
Steps to Reproduce
Globalsis assigned.RibbonController.Intelligence.cs- for example the Spam Manager "Clear Spam Manager" command, or any of the QuickFiler settings toggles.NullReferenceExceptionraised inside the controller partial.Expected Behavior
No ribbon callback raises a
NullReferenceExceptionwhen invoked before initialization completes. Each site degrades gracefully, consistent with the seam pattern established by #503 and extended by #505: host-neutral, unit-tested decision logic behind an injected accessor, with the COM-touching glue left in the[ExcludeFromCodeCoverage]shim.Actual Behavior
Every listed site dereferences
Globalsimmediately with no guard. Verified againstorigin/mainatf910ff2f:ClearSpamManagerAsyncGlobals.AF...ClearSpamManagerAsyncGlobals.Engines.RestartEngineAsync(...)Globals...The list is indicative rather than exhaustive. The fix should begin with a full enumeration of
Globalsdereferences in that file that are reachable from a ribbon callback.Logs / Screenshots
async voidhandler unobserved.Impact / Severity
Same narrow reachable window as #507 and #518: the callback must run before
SetGlobals.Source
From: docs/features/potential/2026-08-08-ribbon-controller-intelligence-unguarded-globals-deref.md