#39186·wazuh

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

Author: RebitsCreated Sep 11, 2026Updated Sep 17, 2026
Labelstype/bugreporter/qalevel/task

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.

cpp
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                          35

The 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:

cpp
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, id 006, macOS 26.5.1 (build 25F80), arm64, Parallels VM on MacStadium host macstadium_arm_4, 486 processes inventoried.
  • Agent package wazuh-agent-5.0.0-latest.arm64.pkg from nightly-backup/2026-09-09, receipt com.wazuh.pkg.wazuh-agent version 5.0.0.
  • VERSION.json: {"version": "5.0.0", "stage": "rc1", "commit": "2161e69"} on manager and agent.
  • Source read from the 5.0.0 branch of wazuh/wazuh: getProcessInfo() in src/data_provider/src/sysInfoMac.cpp. Buffer size from Apple's sys/proc_info.h and sys/param.h.
  • Comparison agents: 001 ubuntu-26-arm64 (143 processes, 96 names at the 15-character cap), 005 windows-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

  1. Enroll a 5.0.0 macOS agent and let a syscollector evaluation complete.
  2. Pull every process document with its name and executable path:
bash
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"]}'
  1. Flag any document whose process.name is a strict prefix of the basename of process.command_line. Every such row is a truncation, and every one of them has a name of exactly 31 characters.

  2. Confirm the collision directly:

bash
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.

  1. On the host, ps -Ao pid,comm shows the same truncation, while ps -Ao pid,args and /usr/bin/proc_pidpath equivalents 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().