Bit of a wordy title, but since macOS 26.4 the rebranding options in both Jamf Auto Update and Notifier have stopped working, at least as far as the icons being shown in Notification Center for notifications.
This post’s header comic nods to the fact that I’m not 100% sure that the way I have been using NSWorkspace’s setIcon to update an application’s icon (and then its notifications), is an Apple approved workflow or just a happy accident.
Below, the method and madness are detailed, along with what’s broken and the ID of the feedback I logged with Apple.
Workflow
The below is the workflow in action, across different macOS releases:
What’s happening in the above is:
- An image is parsed, and its contents are returned as an NSImage.
- This is passed to NSWorkspace’s setIcon method, which in turn creates a hidden file in the root of the application bundle named:
Icon?(sort of, more below). - Notification Center is restarted. This is the step shown in the gifs where the notifications are seemingly reposted, but with a different icon.
That’s it! Pretty simple.
Doesn’t that break code signing and/or notarization?
Nope.
Despite the icon file being added to the root of the application bundle, the .app’s code signing and notarization stays intact, (the below examples show the Notifier.app and helper apps icons set to: /System/Library/CoreServices/CoreTypes.bundle/Contents/Resources/ErasingIcon.icns)


Things do get funkier with helper applications within app bundles, and this is why, with Notifier 3.0, the Notifier - Alerts.app and Notifier - Notifications.app helper applications were moved from being within: Notifier.app/Contents/Resources/ to Notifier.app/Contents/Helpers/.
This in turn led to a PR for Munki, which made similar changes (and mutated into this PR, and eventually led to an early version of what is now installhelper).
As per the below, changing the icons of the Helper applications within Munki without the above changes did indeed lead to code signing issues:
/usr/bin/codesign --verify --deep --verbose=4 /Applications/Managed\ Software\ Center.app
--prepared:/Applications/Managed Software Center.app/Contents/PlugIns/MSCDockTilePlugin.docktileplugin
--validated:/Applications/Managed Software Center.app/Contents/PlugIns/MSCDockTilePlugin.docktileplugin
--prepared:/Applications/Managed Software Center.app/Contents/Frameworks/libswiftCoreImage.dylib
--validated:/Applications/Managed Software Center.app/Contents/Frameworks/libswiftCoreImage.dylib
--prepared:/Applications/Managed Software Center.app/Contents/Frameworks/libswiftAppKit.dylib
--validated:/Applications/Managed Software Center.app/Contents/Frameworks/libswiftAppKit.dylib
--prepared:/Applications/Managed Software Center.app/Contents/Frameworks/libswiftCoreGraphics.dylib
--validated:/Applications/Managed Software Center.app/Contents/Frameworks/libswiftCoreGraphics.dylib
--prepared:/Applications/Managed Software Center.app/Contents/Frameworks/libswiftObjectiveC.dylib
--validated:/Applications/Managed Software Center.app/Contents/Frameworks/libswiftObjectiveC.dylib
--prepared:/Applications/Managed Software Center.app/Contents/Frameworks/libswiftXPC.dylib
--validated:/Applications/Managed Software Center.app/Contents/Frameworks/libswiftXPC.dylib
--prepared:/Applications/Managed Software Center.app/Contents/Frameworks/libswiftCoreData.dylib
--validated:/Applications/Managed Software Center.app/Contents/Frameworks/libswiftCoreData.dylib
--prepared:/Applications/Managed Software Center.app/Contents/Frameworks/libswiftMetal.dylib
--validated:/Applications/Managed Software Center.app/Contents/Frameworks/libswiftMetal.dylib
--prepared:/Applications/Managed Software Center.app/Contents/Frameworks/libswiftos.dylib
--validated:/Applications/Managed Software Center.app/Contents/Frameworks/libswiftos.dylib
--prepared:/Applications/Managed Software Center.app/Contents/Frameworks/libswiftIOKit.dylib
--validated:/Applications/Managed Software Center.app/Contents/Frameworks/libswiftIOKit.dylib
--prepared:/Applications/Managed Software Center.app/Contents/Frameworks/libswiftQuartzCore.dylib
--validated:/Applications/Managed Software Center.app/Contents/Frameworks/libswiftQuartzCore.dylib
--prepared:/Applications/Managed Software Center.app/Contents/Frameworks/libswiftCoreFoundation.dylib
--validated:/Applications/Managed Software Center.app/Contents/Frameworks/libswiftCoreFoundation.dylib
--prepared:/Applications/Managed Software Center.app/Contents/Frameworks/libswiftDarwin.dylib
--validated:/Applications/Managed Software Center.app/Contents/Frameworks/libswiftDarwin.dylib
--prepared:/Applications/Managed Software Center.app/Contents/Frameworks/libswiftDispatch.dylib
--validated:/Applications/Managed Software Center.app/Contents/Frameworks/libswiftDispatch.dylib
--prepared:/Applications/Managed Software Center.app/Contents/Frameworks/libswiftCore.dylib
--validated:/Applications/Managed Software Center.app/Contents/Frameworks/libswiftCore.dylib
--prepared:/Applications/Managed Software Center.app/Contents/Frameworks/libswiftFoundation.dylib
--validated:/Applications/Managed Software Center.app/Contents/Frameworks/libswiftFoundation.dylib
/Applications/Managed Software Center.app: a sealed resource is missing or invalid
file added: /Applications/Managed Software Center.app/Contents/Resources/munki-notifier.app/Icon
file added: /Applications/Managed Software Center.app/Contents/Resources/MunkiStatus.app/Icon
But once the munki-notifier.app and MunkiStatus.app were moved from: /Contents/Resources to: /Contents/Helpers (the same as the Notifier.app helper applications), we could apply a new icon without invalidating code signing and/or notarization.
What is this “Icon?” file?
This file is a bit interesting, it’s an empty file with a hidden flag set.
/bin/ls -lO /Applications/Utilities/Notifier.app/Icon?
-rw-r--r--@ 1 root wheel hidden 0 16 Oct 17:42 /Applications/Utilities/Notifier.app/Icon?
The path itself is somewhat interesting too, as multiple can be used in Terminal, both Icon? and Icon$'\r'
/bin/ls /Applications/Utilities/Notifier.app/Icon$'\r'
/Applications/Utilities/Notifier.app/Icon?
And if you check the name with mdls, you get a slightly different name:
/usr/bin/mdls -name kMDItemFSName /Applications/Utilities/Notifier.app/Icon?
kMDItemFSName = "Icon "
And as mentioned, the file itself is empty.. so what is macOS looking at?
Well, if you open the file in ResForge (the icon alone will bring some nostalgia), you’ll see that the file is empty but the resource fork contains the icon that we want set via NSWorkspace’s setIcon, (again the example icon being: /System/Library/CoreServices/CoreTypes.bundle/Contents/Resources/ErasingIcon.icns).

So, any workarounds?
Not really. The issue does seem to be that while the file exists and the resource fork contains the icon that we want to set and the icon is changed in Finder. It’s just that notifications posted via the applications on macOS 26.4+ no longer respect the icon set via NSWorkspace’s setIcon.
If we step away from the NSWorkspace setIcon method, we can look to replace the application icon on disk. But it gets terrible pretty fast.
The simplest way is to configure the application to use a precomposed icns file (rather than asset catalog), but this does indeed break code signing and notarization.
Neither code signing nor notarization is needed for an application to post notifications.. so the applications could still post notifications or you could then ad-hoc sign the applications after changing the icon, but these are some serious security trade offs and not something I’m seriously looking to implement in Notifier (yet).
And additionally, icons set this way become susceptible to squircle jail (see below), which is something that icons that are set via NSWorkspace’s setIcon seem to avoid.

Feedback
I have filed feedback with Apple, and the ID is: FB22387725
I’m going to link to this blog, in the hope it explains the issue more clearly and hoping that by posting this others can also raise feedback too.
A fix would be great, or at least a: “Please use this method…”.
However, as I said at the start of this post: I’m not 100% sure that the way I have been using NSWorkspace’s setIcon to update an application’s icon (and then its notifications), is an Apple approved workflow or just a happy accident.

