Verify what the binary does

Version 1 · 19 September 2026 · Companion to the Permissions page

The Permissions page says what WideSplit asks for and what it never does. This page is how you check those statements yourself — not by reading our description, but by measuring the copy running on your Mac with tools that ship with macOS or are public and tiny. Nothing here needs our cooperation, a developer account, or any permission granted to WideSplit.

1. What we promise, how you check it, what you should see

We promiseHow you checkExpected result
Our event taps listen to the mouse only — never to the keyboardtap-list, a 60-line program built on the public CGGetEventTapList API, run while a split is onWideSplitCompositor mask=0xe4000fe, WideSplitWindowLayout mask=0x46, both keyboard=no
The renderer has no network codenm -u on the rendererno NSURLSession, no CFNetwork, no sockets — only two file-path symbols
Only the licence tool and the update check talk to the networknm -u on dm-license and on the menu bar app; a firewallNSURLSession lives in dm-license and in the menu bar app’s update framework, nowhere else; during the beta only our website in the firewall
No entitlement exceptionscodesign -d --entitlements -empty
Frames never touch the diskfs_usage on the renderer for a minute of splittext telemetry in its own log folder, no image files
Your copy is the one we publishedcodesign, spctl, shasum against the release manifestvalues equal to the manifest of your version

The two helper programs live inside the app bundle. The commands below use these paths:

APP=$(ls -d /Applications/WideSplit.app /Applications/DisplayMode.app 2>/dev/null | head -1)
R=$(ls "$APP"/Contents/Helpers/*Compositor.app/Contents/MacOS/*Compositor)
W=$(ls "$APP"/Contents/Helpers/*Win*.app/Contents/MacOS/*Win*)
L=$(ls "$APP"/Contents/Helpers/*Compositor.app/Contents/MacOS/dm-license)
U="$APP/Contents/Frameworks/Sparkle.framework/Sparkle"

The first line finds the app under whichever name your copy carries: builds from the beta onwards are called WideSplit, earlier ones DisplayMode. Every command below uses it, so you can paste them as they are.

2. The event taps

macOS keeps a list of every event tap in your login session: which process opened it, which event types it subscribed to, whether it is active. CGGetEventTapList is the public Core Graphics function that reads that list, and it needs no permission at all. The mask it reports is the truth about the running program — it cannot be edited after the fact and it does not depend on anything we say.

Download tap-list.c (MIT licence, independent of WideSplit — it only reads the list and opens no tap of its own), build it and run it while a split is on:

cc -framework ApplicationServices -o tap-list tap-list.c
./tap-list

Among the taps of other applications (accessibility helpers, dictation tools and the like — many of them do subscribe to the keyboard, that is what keyboard=YES marks), the WideSplit lines must read:

pid=…  WideSplitCompositor    mask=0xe4000fe  options=0 enabled=1 keyboard=no
pid=…  WideSplitWindowLayout  mask=0x46       options=0 enabled=1 keyboard=no

The keyboard event types are bits 10, 11 and 12 of the mask — key down, key up and modifier flags changed — together 0x1c00. Neither of our masks has any of them: 0xe4000fe & 0x1c00 = 0 and 0x46 & 0x1c00 = 0. The compositor line is there only while a multi-zone split is running; the window manager line while its daemon is running — which is whenever drag-to-snap or drag-onto-a-full-screen-desktop is on, and both are settings you can switch off (drag-to-snap also steps aside by itself when another window manager is active). Its mask is the same either way: mouse only. A one-zone layout does not start the compositor, so only the window manager line can appear then.

The two source files that decide those masks are published as they are compiled: InputTap.h (the renderer) and WindowLayoutTap.h (the window manager). Each names the event types it subscribes to and nothing else; you can add up the bits yourself and compare with what tap-list prints. Keyboard shortcuts use the system hotkey API instead, which is why nm -u "$R" | grep -i 'EventTapCreate\|RegisterEventHotKey' lists both _CGEventTapCreate and _RegisterEventHotKey.

3. Network

nm -u lists the symbols a program imports from the system. A program that never links a networking class cannot use it.

nm -u "$R" | grep -i 'url\|cfnetwork\|socket\|connect'

On a release copy this prints exactly two lines, both about file paths (the diagnostic screenshot you can ask for by hand is written with an image API that takes a file URL):

_CGImageDestinationCreateWithURL
_OBJC_CLASS_$_NSURL

The same command on the window manager, nm -u "$W" | grep -i 'url\|cfnetwork\|socket', prints nothing. Two programs are supposed to have networking classes: the licence tool and the update framework inside the menu bar app. On the licence tool:

nm -u "$L" | grep -i url
_OBJC_CLASS_$_NSHTTPURLResponse
_OBJC_CLASS_$_NSMutableURLRequest
_OBJC_CLASS_$_NSURL
_OBJC_CLASS_$_NSURLSession
_OBJC_CLASS_$_NSURLSessionConfiguration

And on the update framework, nm -u "$U" | grep -i urlsession, which lists _OBJC_CLASS_$_NSURLSession among others. Beta builds do not use the licence tool’s network code — a beta checks only the end date built into it, on your Mac.

4. Entitlements

codesign -d --entitlements - "$R"
codesign -d --entitlements - "$W"

Each prints its Executable= line and nothing after it. No disable-library-validation, no allow-jit, no allow-dyld-environment-variables, no network entitlement of any kind. Release builds add the hardened runtime, and with it nothing can be loaded into a WideSplit process to borrow its permissions; beta builds do not have the hardened runtime yet.

5. Watching it live

Connections. With a firewall such as Little Snitch or LuLu running, the complete list of WideSplit connections during the beta is the menu bar app to our website — widesplit.app, and displaymode.pages.dev, its earlier address that forwards there — once a day (a download only after you click). Released versions add dm-license to the licence host. The renderer and the window manager never appear. lsof -i -p "$(ps -axo pid=,args= | awk '/WideSplitCompositor [0-9]/ && !/--standby/ {print $1; exit}')" prints nothing while a split is on.

Disk. fs_usage shows every file operation of a process (it needs administrator rights, because it watches the whole system):

sudo fs_usage -w -f filesys -p "$(ps -axo pid=,args= | awk '/WideSplitCompositor [0-9]/ && !/--standby/ {print $1; exit}')"

Leave it running for a minute of split, move the mouse, switch windows. You will see the renderer writing text telemetry to its own log under ~/Library/Application Support/WideSplitTriple/ and reading its settings. You will not see an image file, a frame buffer or anything outside that folder — the only image ever written is the diagnostic screenshot you request by hand, to the path you choose.

6. Identity of the copy

The checks above say what the program does. The Permissions page, section 8 says how to confirm it is the program we published: codesign -dv --verbose=4 for the signature and Team ID, spctl -a -vv for notarization, shasum -a 256 against the release manifest of your version, which lists the checksum of the download and of every executable inside the bundle.

The Team ID printed in those examples is <TEAMID>: it becomes a real value with the first Developer ID release and will be published in the manifests from that build on. Builds handed to testers before then are signed with a local certificate and carry no Team ID; their manifests say so.

7. If something does not match

A different mask, a networking symbol in the renderer, a non-empty entitlement list or a checksum that is not in the manifest means the copy is not what we published. Do not run it: delete it, download again from this site, and tell us at [email protected] what you saw and where the copy came from.