macOS process names are truncated at 31 characters, collapsing distinct system services onto identical names, while the full name sits in the executable path the same function already reads
Description
process.name on the macOS agent is taken from the short name field of the BSD process info structure, which is a fixed 32-byte buffer, so any process whose name is longer than 31 characters is silently cut off at 31.
jsProcessInfo["name"] = taskInfo.pbsd.pbi_name;pbi_name is declared char pbi_name[2 * MAXCOMLEN] in sys/proc_info.h, and MAXCOMLEN is 16, so 32 bytes including the terminator and 31 usable characters.
Of the 486 processes the agent inventories, 22 report a name of exactly 31 characters, and 19 of those are provably truncated: the reported name is a strict prefix of the basename of the executable path in the same document.
pid process.name (31 chars) actual executable basename len
471 com.apple.MobileSoftwareUpdate. com.apple.MobileSoftwareUpdate.CleanupPreparePathService 56
45140 com.apple.MobileSoftwareUpdate. com.apple.MobileSoftwareUpdate.UpdateBrainService 49
234 com.apple.MobileAsset.DownloadS com.apple.MobileAsset.DownloadService.Builtin 45
225 com.apple.DriverKit-IOUserDockC com.apple.DriverKit-IOUserDockChannelSerial 43
478 PerfPowerTelemetryClientRegistr PerfPowerTelemetryClientRegistrationService 43
770 com.apple.accessibility.mediaac com.apple.accessibility.mediaaccessibilityd 43
269 com.apple.cmio.videodriverkitho com.apple.cmio.videodriverkithostextension 42
714 com.apple.StreamingUnzipService com.apple.StreamingUnzipService.privileged 42
589 com.apple.FaceTime.FTConversati com.apple.FaceTime.FTConversationService 40
65032 Managed Background Assets Helpe Managed Background Assets Helper Service 40
159 com.apple.cmio.registerassistan com.apple.cmio.registerassistantservice 39
422 com.apple.quicklook.ThumbnailsA com.apple.quicklook.ThumbnailsAgent 35The damage is not only cosmetic, because macOS service names are reverse-DNS identifiers whose distinguishing part is at the end. The first two rows above are two different system services, CleanupPreparePathService and UpdateBrainService, and both are reported under the identical name com.apple.MobileSoftwareUpdate.. Anything that groups or counts by process.name, or any rule that matches on it, cannot tell them apart. The truncation point falls in exactly the wrong place for this naming convention: the shared vendor prefix survives and the part that identifies the process is discarded.
The full name is already available in the same function, at no additional cost. getProcessInfo() calls proc_pidpath() a few lines later and stores the result:
char pathBuffer[PROC_PIDPATHINFO_MAXSIZE] = {0};
const auto pathLen { proc_pidpath(pid, pathBuffer, sizeof(pathBuffer)) };
jsProcessInfo["command_line"] = pathLen > 0 ? std::string(pathBuffer) : "";PROC_PIDPATHINFO_MAXSIZE is 4096, so the path is not truncated, and its basename is the untruncated name. That is precisely how the table above was built: by comparing the stored name against the basename of the stored path, using nothing the agent did not already report. Taking the name from the path when it is available, and falling back to pbi_name only when proc_pidpath fails, would fix every one of these rows without another syscall.
I want to set the scope honestly, because this is not a macOS-only phenomenon and should not be triaged as a macOS regression.
The Linux agents are affected worse. process.name there comes from /proc/<pid>/comm, which is capped at 15 characters, and on agent 001 96 of 143 process names are exactly 15 characters long with 6 provably truncated by the same prefix test. The Windows agent is unaffected: its longest name is 23 characters and none is truncated.
I am filing this against macOS rather than as a single cross-platform report because the two are different code paths with different fixes and different fallbacks available: macOS has proc_pidpath sitting in the same function, Linux would need /proc/<pid>/cmdline or the executable link, and neither change helps the other platform. Whoever picks this up should be aware the Linux side exists and may want to open a companion issue rather than assume fixing macOS covers it.
Environment
- Agent under test:
demo-env-macos-agent, id006, macOS 26.5.1 (build 25F80), arm64, Parallels VM on MacStadium hostmacstadium_arm_4, 486 processes inventoried. - Agent package
wazuh-agent-5.0.0-latest.arm64.pkgfromnightly-backup/2026-09-09, receiptcom.wazuh.pkg.wazuh-agentversion 5.0.0. VERSION.json:{"version": "5.0.0", "stage": "rc1", "commit": "2161e69"}on manager and agent.- Source read from the
5.0.0branch ofwazuh/wazuh:getProcessInfo()insrc/data_provider/src/sysInfoMac.cpp. Buffer size from Apple'ssys/proc_info.handsys/param.h. - Comparison agents:
001ubuntu-26-arm64 (143 processes, 96 names at the 15-character cap),005windows-11-amd64 (78 processes, none truncated). - QA demo environment
wqa-prod-58-demo-environment. Not a container deployment, so there are no image digests to record.
Steps to reproduce
- Enroll a 5.0.0 macOS agent and let a syscollector evaluation complete.
- Pull every process document with its name and executable path:
curl -sk --cert admin.pem --key admin-key.pem \
"https://<indexer>:9200/wazuh-states-inventory-processes/_search?size=600" \
-H 'Content-Type: application/json' \
-d '{"query":{"term":{"wazuh.agent.id":"006"}},
"_source":["process.name","process.command_line","process.pid"]}'Flag any document whose
process.nameis a strict prefix of the basename ofprocess.command_line. Every such row is a truncation, and every one of them has a name of exactly 31 characters.Confirm the collision directly:
curl -sk --cert admin.pem --key admin-key.pem \
"https://<indexer>:9200/wazuh-states-inventory-processes/_search?size=10" \
-H 'Content-Type: application/json' \
-d '{"query":{"bool":{"filter":[{"term":{"wazuh.agent.id":"006"}},
{"term":{"process.name":"com.apple.MobileSoftwareUpdate."}}]}},
"_source":["process.pid","process.name","process.command_line"]}'Two processes come back with the same name and different executables.
- On the host,
ps -Ao pid,commshows the same truncation, whileps -Ao pid,argsand/usr/bin/proc_pidpathequivalents show the full path.
Expected
process.name carries the process's actual name. Two distinct services do not share a name, and a name is not cut at a fixed width when the untruncated value is already being collected in the same pass.
Actual
The name is copied from pbi_name, a 32-byte field, so it is cut at 31 characters. 22 of 486 processes on the agent hit the cap, 19 are demonstrably truncated, and at least one pair of unrelated Apple system services collapses onto a single identical name, while the full name is present in the command_line value stored beside it.
Not a duplicate of
qa-known-issues.py check found no cache match against 784 open bugs, the live search for executable characters collector truncated because already returned nothing, and the tool concluded "no known issue looks like this one".
Related but distinct: wazuh/wazuh#39141 and wazuh/wazuh#39169 concern other fields dropped by this same function, command-line arguments and CPU time respectively. Neither concerns the name field, and all three could be addressed in one pass over getProcessInfo().
Source: wazuh/wazuh