Skip to content
hideouts

Type to search every app and research write-up.

macOS22 min readPublished Updated

The Unofficial skywalkctl Field Guide

Apple’s kernel networking subsystem, one command at a time.

A hands-on guide to macOS skywalkctl built from 175 sanitized, read-only invocations on macOS 26.4, with a safety map, full command reference, and expanded man page.

On this page

Key findings

  1. Built from 175 elevated, read-only runs of Apple’s /usr/sbin/skywalkctl on macOS 26.4 (25E246), with identifying output sanitized.
  2. The Skywalk runtime held 37 providers, 31 nexus instances, and 25 channels.
  3. Retained flow rows are not the same as established sockets.
  4. Several commands misbehave on this build: JSON flow output has duplicate keys, protons rejects filters it advertises, and status reads a missing sysctl, so its “disabled” result is unreliable.
  5. Commands that change state were not run, and nothing in the results independently demonstrated compromise.

Summary written for this site. Each point is covered, with its evidence, in the write-up below.

skywalkctl is Apple’s diagnostic command for inspecting the Skywalk networking subsystem used by macOS. It can show the kernel’s network providers, runtime nexus objects, channels, flows, interface counters, protocol statistics, memory allocators, and port reservations.

This is a hands-on guide built from 175 recorded, elevated, read-only invocations of the Apple-signed /usr/sbin/skywalkctl included with macOS 26.4 build 25E246. Results below are real but sanitized: hostnames, usernames, real IP addresses, identifying ports, PIDs, UUIDs, timestamps, and application inventory have been replaced or omitted.

skywalkctl is a debugging interface, not a stable public API. Commands and output can change between macOS releases. Always check the help emitted by the binary installed on your Mac.

The main README is a guided walkthrough for learning how Skywalk objects fit together and how to interpret representative output. Use REFERENCE.md as the exhaustive lookup document when you need:

  • every discovered top-level command, option, alias, and subcommand;
  • tested command variations and verified parser requirements;
  • observed stdout, stderr, and exit-status behavior;
  • build-specific limitations, compatibility paths, and unexpected results;
  • safe versus state-changing command classifications; and
  • detailed research findings that would interrupt the flow of this tutorial.

In short: read this README to learn skywalkctl; open the command reference when you need to look up exact behavior.

  • A guided tour of every top-level command.
  • Representative sanitized output from the test run.
  • A plain-English explanation immediately after each result.
  • Every documented option and subcommand.
  • Clear warnings for commands that change the computer.
  • Read-only collection scripts that preserve command lines, output, errors, timestamps, and exit status.
  • A full command reference and an expanded skywalkctl(8) man page.
Learning goalCommands covered
Understand the object modelshow, provider, list-providers, tree
See process attachmentschannel, channel-stats
Investigate flowsflow, flow-adv, flow-owner, flow-route, tcpinfo
Read protocol and namespace statenetstat, flowidns, netns, protons
Read datapath and allocator countersinterface, flow-switch, memory
Understand logging and legacy controlslog, status, enable
Understand steering and redirectiontraffic-rule, redirect
Check platform-specific pathsaop, print-banner

Use the ten-minute survey for a first pass, the command-by-command guide for interpretation, and REFERENCE.md when you need the complete option matrix and parser research.

The following commands are safe to use as read-only diagnostics:

text
channel          flow              flow-adv          flow-owner
flow-route       flow-switch       interface         memory
netns            protons           netstat           provider
show             tree              log show          log list
status           tcpinfo           flowidns          traffic-rule show
aop              print-banner      channel-stats      list-providers

These forms change live or persistent state and were not executed:

CommandEffect
`skywalkctl enable 01`
skywalkctl log SK_VERB_*Changes kernel Skywalk logging verbosity.
skywalkctl log 0Resets the kernel Skywalk verbosity mask.
skywalkctl traffic-rule addAdds a live traffic-steering rule.
skywalkctl traffic-rule removeRemoves a live traffic-steering rule.
skywalkctl redirect createCreates a redirect interface.
skywalkctl redirect setChanges redirect-interface delegation.
skywalkctl redirect destroyDestroys a redirect interface.
text
provider definition
└── nexus instance
    ├── channel endpoint → process/file descriptor
    └── flow-switch or pipe resources

network flow
├── local and remote endpoint
├── protocol and interface
├── packet/byte accounting
└── effective process attribution
  • A provider defines a Skywalk service such as a netif, flow switch, user pipe, or kernel pipe.
  • A nexus is a runtime instance of a provider.
  • A channel is an endpoint attached to a nexus port.
  • A flow is a Skywalk flow record. It may remain visible after the application socket has closed.
  • A flow switch classifies and moves packets for an interface.
  • A netif is Skywalk’s representation of a network interface.

Jonathan Levin's Darwin networking research describes Skywalk as an undocumented XNU networking subsystem whose public-source coverage is intentionally limited. The same research identifies utun, IPSec, and bridge-related paths as useful places to correlate Skywalk objects with visible macOS networking behavior. It also explains why tree, provider, and channel are important: Skywalk exports provider and channel data through private sysctl interfaces, and skywalkctl is one of the Apple-signed tools able to decode that data into a human-readable form.

That research also gives useful constraints for this guide:

  • Nexus providers commonly fall into user pipes, kernel pipes, network interfaces, and flow switches.
  • A VPN or tunnel can appear as both a netif provider and a multi-stack flow switch, so seeing utun in Skywalk output is expected on many systems.
  • Nexus registration and broad observation are entitlement-gated operations. This is one reason third-party tools should treat Skywalk as an observed subsystem, not as a supported extension point.
  • Channel details can be associated with file descriptors, UUIDs, ports, and flags, which explains why channel output is useful when mapping runtime objects back to processes.

The Apple Internals glossary gives a shorter operational description: Skywalk connects networking technologies and virtual paths such as Bluetooth, Wi-Fi, Thunderbolt, interfaces, and tunnels. It also records the relevant vocabulary: nexus objects represent conduits, agent objects represent endpoints or policy participants, DriverKit network drivers are associated with this layer, and skywalkctl is the command-line inspection tool.

The Korean macOS interface write-up is useful for field work because it starts from the names users actually see in ifconfig. It calls out llw0 as a low-latency WLAN interface tied to Skywalk, awdl0 as the Apple Wireless Direct Link interface used by features such as AirDrop and Continuity, and utun# as a user tunneling interface commonly used by VPN clients. Those names are normal macOS networking artifacts and should be correlated with skywalkctl output before drawing security conclusions.

Start here: a ten-minute read-only survey

Link to section: Start here: a ten-minute read-only survey

Run these commands in order:

Terminal
sudo /usr/sbin/skywalkctl show -v
sudo /usr/sbin/skywalkctl provider -D
sudo /usr/sbin/skywalkctl tree
sudo /usr/sbin/skywalkctl channel
sudo /usr/sbin/skywalkctl flow -n
sudo /usr/sbin/skywalkctl interface
sudo /usr/sbin/skywalkctl flow-switch -G -v
sudo /usr/sbin/skywalkctl memory -a
sudo /usr/sbin/skywalkctl netns -a
sudo /usr/sbin/skywalkctl netstat -a -n

This sequence answers:

  1. What Skywalk objects exist?
  2. Which providers and instances created them?
  3. Which processes have channels?
  4. Which flow records are retained?
  5. What are the interface and flow-switch counters?
  6. How much memory is represented by Skywalk allocators?
  7. Which TCP/UDP ports are reserved?

Root is not necessary for every command, but it was required for complete results on the tested Mac. Operation not permitted means incomplete coverage, not an empty system.


Each section answers four questions:

  1. What does the command do?
  2. What should I run?
  3. What did the tested Mac return?
  4. What does that result mean?

show is the fastest way to see active Skywalk instances. The verbose form also associates applicable pipes with attached processes and nexus ports.

Terminal
sudo /usr/sbin/skywalkctl show -v

Options:

  • -h, --help: print usage.
  • -v, --verbose: add attached channel/process information.
text
flowswitch <NEXUS_UUID> com.apple.flowswitch.en0
flowswitch <NEXUS_UUID> com.apple.flowswitch.awdl0
flowswitch <NEXUS_UUID> com.apple.flowswitch.utun<N>
kernel-pipe <NEXUS_UUID> IOSkywalkBSDClient
user-pipe <NEXUS_UUID> <APPLE_SERVICE_PIPE>
        [ 0] <PROCESS>.<PID>
        [ 1] <PROCESS>.<PID>

The system had active flow switches for physical, peer-to-peer, and tunnel interfaces, plus kernel and user pipes. A flow-switch or pipe name is an inventory item—not proof that traffic is currently passing through it and not evidence of compromise.

Use provider -D for configuration details and tree for hierarchy.

2. provider — list provider definitions and instances

Link to section: 2. provider — list provider definitions and instances

provider lists Skywalk provider definitions and their child nexus instances.

Terminal
sudo /usr/sbin/skywalkctl provider -D

Options:

  • -h, --help: print usage.
  • -D, --detail: show ring counts, slot counts, buffer size, metadata size, memory hints, and child instances.
text
flow-switch com.apple.flowswitch.en0 <PROVIDER_UUID>
        rings: tx 1 rx 1 slots: tx 256 rx 1024
        bufsize 2048 metasize 256 mhints 0
        instance <NEXUS_UUID>

net-if AppleBCMWLANSkywalkInterface.en0 <PROVIDER_UUID>
        rings: tx 1 rx 1 slots: tx 2 rx 2
        bufsize 2048 metasize 256 mhints 0
        instance <NEXUS_UUID>

Provider counts from the complete snapshot:

text
net-if       15
flow-switch   7
user-pipe    10
kernel-pipe   5
total        37

The provider line describes a service definition. rings and slots describe configured queue capacity. bufsize and metasize describe packet-buffer and metadata sizing. instance is the runtime nexus created from that provider.

The four provider types are normal Skywalk building blocks. Their presence alone says nothing about authorization or maliciousness.

3. list-providers — provider compatibility alias

Link to section: 3. list-providers — provider compatibility alias

list-providers is a compatibility alias for provider.

Terminal
sudo /usr/sbin/skywalkctl list-providers -D

The output matched provider -D byte-for-byte in the same snapshot.

Use either spelling on the tested build. provider is shorter and is the name described by the installed manual page.

4. tree — show the provider/nexus/channel hierarchy

Link to section: 4. tree — show the provider/nexus/channel hierarchy

tree emits Skywalk’s object hierarchy as JSON.

Terminal
sudo /usr/sbin/skywalkctl tree > tree.json
jq -e . tree.json >/dev/null

To select one object:

Terminal
sudo /usr/sbin/skywalkctl tree -U <PROVIDER_OR_NEXUS_UUID>

Options:

  • -h, --help: print usage.
  • -U, --uuid=UUID: start the tree at one UUID.
JSON
{
  "uuid": "<PROVIDER_UUID>",
  "type": "nexus_provider",
  "name": "com.apple.flowswitch.en0",
  "provider_type": "flow-switch",
  "tx_rings": 1,
  "rx_rings": 1,
  "tx_slots": 256,
  "rx_slots": 1024,
  "children": [
    {
      "uuid": "<NEXUS_UUID>",
      "type": "nexus",
      "children": []
    }
  ]
}

Complete tree counts:

text
root             1
nexus_provider  37
nexus           31
channel         25

The provider owns a child nexus instance. Ring/slot fields describe topology and capacity, not traffic volume. The full output parsed successfully as JSON. UUIDs are useful for correlating tree, provider, flow-switch -U, and netstat -s -U.

5. channel — show nexus channel endpoints

Link to section: 5. channel — show nexus channel endpoints

channel lists channels attached to nexus ports and, when available, the owning process and file descriptor.

Terminal
sudo /usr/sbin/skywalkctl channel
sudo /usr/sbin/skywalkctl channel -C kernel_task

Options:

  • -h, --help: print usage.
  • -C, --command=CMD: filter by command.
  • -w, --wait=SECONDS: repeat until interrupted.
text
Instances: 31
<INDEX> <NEXUS_UUID>
        Port[ 0] kernel_task.0 (fd -1)
<INDEX> <NEXUS_UUID>
        Port[ 1] <PROCESS>.<PID> (fd <FD>) flags=10<DEFUNCT_OK>
  • Instances: 31 is the reported instance count.
  • The UUID identifies the nexus.
  • Port[0] is a nexus port, not a TCP/UDP port.
  • fd -1 is expected for a kernel-owned endpoint.
  • DEFUNCT_OK is a channel flag allowing a defunct state; it is not a claim that the process is malicious.

The -C kernel_task filter retained kernel-owned endpoints. -w 1 repeated indefinitely, so the collector imposed an external two-second boundary.

6. channel-stats — channel compatibility alias

Link to section: 6. channel-stats — channel compatibility alias

channel-stats exposes the same channel view and options as channel.

Terminal
sudo /usr/sbin/skywalkctl channel-stats

It produced output identical to channel in the same snapshot.

This is another compatibility command. It does not expose a different statistics schema on the tested build.

7. flow — inspect retained flow records

Link to section: 7. flow — inspect retained flow records

flow displays Skywalk flow records, endpoint information, packet/byte counters, service class, flags, state, interface, and process attribution.

Terminal
sudo /usr/sbin/skywalkctl flow -n
sudo /usr/sbin/skywalkctl flow -n -I en0
sudo /usr/sbin/skywalkctl flow -n -p tcp
sudo /usr/sbin/skywalkctl flow -n -J > flows.json

Options:

OptionPurpose
-C CMDFilter by effective command.
-I IFFilter by interface.
-nKeep addresses and services numeric.
-JEmit JSON.
-p PROTOFilter by protocol.
-P PIDFilter by PID.
-w SECONDSRepeat until interrupted.
text
Proto Local Address      Remote Address       InBytes OutBytes InPkts/InSPkts ... NetIf Port Adv Flags             Process.PID
tcp4 192.0.2.10.53000    198.51.100.20.443    58100   0        193/165         ... en0   1    -   -c-q------------_  kernel_task.0(<APP>.<PID>)

The filtered JSON snapshot contained:

text
flow records:                 38
protocol:                     TCP
interface:                    en0
distinct effective processes: 10
retained parsed state:        CLOSED
  • tcp4 means TCP over IPv4.
  • The address columns contain endpoint and transport port.
  • Port later in the row is a nexus port, not the TCP port.
  • BE is the best-effort service class.
  • The parenthesized process is Skywalk’s effective-process attribution even when the kernel-side owner appears as kernel_task.0.
  • A retained CLOSED flow is not a live established socket.

The JSON was valid syntax but repeated the localTrackState key twice per flow and omitted remoteTrackState. Preserve raw JSON because parsers normally retain only the last duplicate value.

Flow flag legend:

FlagMeaningFlagMeaning
ttrackedcconnected
llistenerqQoS marking
wwait-closeeclose notification
AabortedNnonviable
WwithdrawnTtorn down
DdestroyedRlingering
Llow latencyPparent
CchildSdo not wake from sleep

8. flow-adv — show flow advisories

Link to section: 8. flow-adv — show flow advisories

flow-adv displays flow-advisory records. Advisories are separate from the main flow table.

Terminal
sudo /usr/sbin/skywalkctl flow-adv
sudo /usr/sbin/skywalkctl flow-adv -I en0
sudo /usr/sbin/skywalkctl flow-adv -P 0
sudo /usr/sbin/skywalkctl flow-adv -C kernel_task

Options: -C CMD, -I IF, and -P PID filter by command, interface, and PID.

text
<no output>
exit status: 0

The command completed successfully, but no advisory record matched at collection time. It does not prove that advisories have never existed.

flow-owner maps owner properties to interface, nexus port, bucket, and process.

Terminal
sudo /usr/sbin/skywalkctl flow-owner
sudo /usr/sbin/skywalkctl flow-owner -I en0

Options: -C CMD, -I IF, and -P PID filter by command, interface, and PID.

text
NetIf  Port  Property  Bkt  Process
en0    1               0    kernel_task(0)
utun<N> 1              0    kernel_task(0)

The active Wi-Fi and a tunnel datapath had kernel-side ownership entries on nexus port 1. This is ownership metadata, not proof that kernel_task independently initiated every associated application connection.

10. flow-route — inspect flow-route entries

Link to section: 10. flow-route — inspect flow-route entries

flow-route displays Skywalk-specific flow-route entries.

Terminal
sudo /usr/sbin/skywalkctl flow-route -n
  • -n: do not resolve service names.
text
<no output>
exit status: 0

No flow-route entry was returned at that instant. The empty result is not the same thing as the system having no BSD routing table; this command queries a specific Skywalk structure.

11. netstat — flow and protocol-statistics views

Link to section: 11. netstat — flow and protocol-statistics views

This is the skywalkctl netstat subcommand, not /usr/sbin/netstat. It has two primary modes:

  • -a: flow view.
  • -s: protocol-statistics view.
Terminal
sudo /usr/sbin/skywalkctl netstat -a -n
sudo /usr/sbin/skywalkctl netstat -s
sudo /usr/sbin/skywalkctl netstat -s -G
sudo /usr/sbin/skywalkctl netstat -s -U <NEXUS_UUID> -v

Full grammar:

text
skywalkctl netstat -a [-C command | -I interface | -P pid | -U uuid]
                    [-p protocol] [-n] [-v]
skywalkctl netstat -s [-C command | -I interface | -P pid | -U uuid]
                    [-p protocol] [-G] [-o] [-n] [-v] [-z]
skywalkctl netstat -a -s [compatible modifiers]
text
Proto Local Address      Remote Address       InBytes OutBytes ... UUID        Process.PID
tcp4 192.0.2.10.53000    198.51.100.20.443    58100   0        ... <FLOW_UUID> kernel_task.0(<APP>.<PID>)

The later numeric parser-matrix snapshot returned 68 data rows. Counts differ from the earlier 38-flow snapshot because network state changed between commands.

text
<Closed Port Stats>
Nexus UUID: <NEXUS_UUID>
Netif     : en0
ip:
ip6:
tcp:
udp:
quic:

With -z or -v, those protocol headings expanded into many counters, including received/sent packets, checksum outcomes, fragments, retransmission events, connection events, and allocation failures.

-a is the flow table; -s is per-protocol statistics. Filters by interface, protocol, PID, command, and UUID worked when paired with a primary mode. Filters or modifiers alone exited 64 because no primary mode was selected.

Verified parser rules:

FormResult
no options or only -n, -G, -o, -zExit 64, usage.
-a -nNumeric flow view.
-sStatistics view.
-a -sBoth views.
-s -GFolded global statistics.
-s -G -I en0Invalid: global conflicts with object filters.
-s -oAOP lookup attempted; unsupported on tested hardware.

Always use -n for evidence. The nonnumeric -a form spent substantial time resolving names and services.

12. tcpinfo — query one exact TCP tuple

Link to section: 12. tcpinfo — query one exact TCP tuple

tcpinfo queries Skywalk’s information for an exact local/remote TCP four-tuple.

Terminal
sudo /usr/sbin/skywalkctl tcpinfo \
  <LOCAL_IP> <LOCAL_PORT> <REMOTE_IP> <REMOTE_PORT>
text
ifindex <INTERFACE_INDEX>
seq     0
ack     0
wnd     0
wscale  0

An earlier tuple selected too far in advance returned:

text
flow not found
exit status: 64

The successful query matched a tuple and reported the interface index plus sequence, acknowledgement, window, and window-scale values exposed by this diagnostic. Zero values do not mean that the socket carried no data. The failed query demonstrates that tuples can disappear before tcpinfo reaches them.

13. flowidns — inspect flow-ID namespaces

Link to section: 13. flowidns — inspect flow-ID namespaces

flowidns shows allocation statistics and mappings for internal flow IDs.

Terminal
sudo /usr/sbin/skywalkctl flowidns -v
sudo /usr/sbin/skywalkctl flowidns -v -d inpcb
sudo /usr/sbin/skywalkctl flowidns -f <HEX_FLOW_ID>

Options:

  • -v: include records.
  • -d DOMAIN: select PF, IPSec, flowswitch, or inpcb.
  • -f HEX_ID: select one flow ID.
text
Flow ID statistics for inpcb domain
num allocs:     9779
num releases:   9703
num collisions: 0
num flowids:    76

flowID: <HEX_FLOW_ID>
        IP addresses: 192.0.2.10 <-> 198.51.100.20
        IP Protocol: 17
        Ports: <LOCAL_PORT> <-> <REMOTE_PORT>
        Domain: inpcb

Other tested domains:

text
PF:         0 current flow IDs
IPSec:      0 current flow IDs
flowswitch: 0 current flow IDs

The inpcb domain was actively allocating and releasing identifiers and had no recorded collisions. Protocol 17 is UDP. inpcb refers to the Internet protocol control-block domain. A flow ID is an internal correlation value, not a user identity or authentication secret.

14. interface — inspect netif counters and queues

Link to section: 14. interface — inspect netif counters and queues

interface displays Skywalk network-interface counters, logical links, queue sets, and queue statistics.

Terminal
sudo /usr/sbin/skywalkctl interface -I en0
sudo /usr/sbin/skywalkctl interface -I en0 -L
sudo /usr/sbin/skywalkctl interface -I en0 -Q

Options:

  • -G: fold counters globally.
  • -I IF: select an interface.
  • -L: show logical links.
  • -Q: show queue statistics.
  • -W SECONDS: repeat until interrupted.
text
netif:
en0
<NEXUS_UUID>
        TxCopyMbuf   : 357836
        GSOSegments  : 50150
        GSOPackets   : 5893
        IfAdvUpdRecv : 1515
        LLinkAdd     : 1
Link to section: Observed logical-link and queue output
text
states: initialized(0x1)
flags: default(0x1)
qset_cnt: 1
        flags: default,AQM,ext_inited
        num_rx_queues: 1
        num_tx_queues: 4

Queue   bits/s  Pkts/s  Min Avg Max  SVC
RX[0]     0.00    0.00    0   0   0   BE
TX[0]     0.00    0.00    0   0   0   BE
TX[1]     0.00    0.00    0   0   0   BK
TX[2]     0.00    0.00    0   0   0   VI
TX[3]     0.00    0.00    0   0   0   VO

The interface had one initialized logical link and one queue set using active queue management (AQM). Service classes were best effort (BE), background (BK), video (VI), and voice (VO). Zero rates describe only that sampling instant; cumulative counters show the interface had processed traffic earlier.

15. flow-switch — inspect datapath counters

Link to section: 15. flow-switch — inspect datapath counters

flow-switch displays counters from Skywalk flow-switch datapaths.

Terminal
sudo /usr/sbin/skywalkctl flow-switch -I en0 -v
sudo /usr/sbin/skywalkctl flow-switch -G -v
sudo /usr/sbin/skywalkctl flow-switch -U <NEXUS_UUID> -v

Options:

  • -G: fold globally.
  • -I IF: select an interface.
  • -U UUID: select a nexus.
  • -v: expand counters.
text
738234 total Rx packet
178506 dropped, flow lookup failure
     0 Rx rings stalled
     0 Incorrect TCP/IP checksum
     0 total Tx packets
     0 total dropped
     0 errors injected

These are cumulative internal datapath events, not a packet-capture summary. flow lookup failure is a reason-specific classification result; it should not be translated directly into 178,506 user-visible lost packets. Neighboring counters showed no ring stalls, checksum failures, injected errors, or summary drops in that section.

To assess a rate, capture two snapshots over a known interval and subtract the same counters.

16. memory — inspect Skywalk allocator state

Link to section: 16. memory — inspect Skywalk allocator state

memory shows Skywalk arenas, regions, caches, and per-process memory grouping.

Terminal
sudo /usr/sbin/skywalkctl memory -a
sudo /usr/sbin/skywalkctl memory -a -J > memory.json
sudo /usr/sbin/skywalkctl memory -g

Options:

OptionResult section
-aAll available allocator information.
-AArenas.
-RRegions.
-CCaches.
-gGroup by process.
-JJSON output.
-I IFInterface filter.
-P PIDPID filter.
JSON
{
  "arenaCount": 40,
  "regionCount": 196,
  "cacheCount": 155,
  "totalRegionMemory": 66051760,
  "wiredRegionMemory": 16580608
}

Observed grouped total in a later snapshot:

text
TOTAL: 15.78 MB memory, 15.78 MB wired
  • Arenas associate clients with region types.
  • Regions describe segments, object geometry, and memory totals.
  • Caches describe slabs, magazines, allocations, frees, failures, and utilization.

Five caches had nonzero cumulative slab-allocation-failure counters in the full snapshot. Without a time baseline, repeated growth, or an associated symptom, that is not proof of a memory leak or exhaustion event.

17. netns — inspect port reservations

Link to section: 17. netns — inspect port reservations

netns displays TCP and UDP port reservations for network namespaces.

Terminal
sudo /usr/sbin/skywalkctl netns -a
sudo /usr/sbin/skywalkctl netns -i 127.0.0.1 -p tcp
sudo /usr/sbin/skywalkctl netns -i ::1 -p tcp

Verified grammar:

text
skywalkctl netns -a
skywalkctl netns -i IP -p {tcp|udp}

Without -a, both IP and protocol are required.

text
tcp port reservations for 127.0.0.1
    PORT(S)    SKYWALK        BSD   LISTENER
       <PORT>          0          1          0

This sample says that BSD had one reservation for the port, while Skywalk and listener counts were zero. A reservation is not automatically an accepting listener and does not identify the process.

Parser results:

InputResult
no optionsExit 22: asks for -a or an IP.
only -p tcpExit 22: missing IP.
only -i 127.0.0.1Exit 22: missing protocol.
valid IP and protocolTable or silent exit 2 when no namespace matched.
-a plus other filtersOther filters ignored with a warning.

18. protons — show protocol reference counts

Link to section: 18. protons — show protocol reference counts

protons lists numeric IP protocol/IPv6 next-header values and reference counts.

Terminal
sudo /usr/sbin/skywalkctl protons
text
Proto RefCnt Pid ePid
0     3      0   0
1     2      0   0
6     2      0   0
17    2      0   0
41    3      0   0
58    2      0   0

Proto uses the IANA protocol-number registry: for example, 1 is ICMP, 6 is TCP, 17 is UDP, 41 is IPv6 encapsulation, and 58 is IPv6 ICMP. RefCnt is the reported reference count. PID 0 indicates kernel attribution in this view.

The binary advertised -a, -i, and -p, but all three were rejected with exit 64. Only the no-option form worked on the tested build.

19. log — inspect or change Skywalk logging

Link to section: 19. log — inspect or change Skywalk logging
Terminal
sudo /usr/sbin/skywalkctl log show
sudo /usr/sbin/skywalkctl log list

Observed results:

text
log show: exit 0, no named active flag printed
log list: exit 0, 64 bit positions enumerated

log list printed names such as SK_VERB_FLOW, SK_VERB_NETIF, SK_VERB_DROP, and reserved entries with their hexadecimal masks.

State-changing subcommands — do not run casually

Link to section: State-changing subcommands — do not run casually
text
skywalkctl log SK_VERB_NAME   # sets kernel verbosity
skywalkctl log 0              # resets the verbosity mask

show and list are safe inventory operations. The other forms change kernel logging and can generate a large volume of logs. They were not executed.

20. status — check a legacy enable setting

Link to section: 20. status — check a legacy enable setting

status checks a Skywalk-related boot/sysctl setting.

Terminal
sudo /usr/sbin/skywalkctl status
text
sysctlbyname failed: No such file or directory
skywalkctl: sysctl net.link.generic.system.if_attach_nx failed: No such file or directory
Skywalk is NOT enabled currently
exit status: 71

The utility queried a sysctl that does not exist on the tested kernel. The printed “NOT enabled” conclusion is unreliable on this build because provider, tree, channel, flow, and interface simultaneously returned populated Skywalk state.

Treat status as a legacy boot-setting probe, not a definitive runtime-presence test.

21. enable — change Skywalk boot arguments

Link to section: 21. enable — change Skywalk boot arguments
text
skywalkctl enable 1   # enable through boot arguments
skywalkctl enable 0   # disable through boot arguments

Not executed. The syntax was documented from installed usage text only.

This root-only command edits NVRAM boot-args, persists across boots, and may require a reboot. It is not an information-gathering command.

22. traffic-rule — inspect or change traffic steering

Link to section: 22. traffic-rule — inspect or change traffic steering
Terminal
sudo /usr/sbin/skywalkctl traffic-rule show

Observed result:

text
<no output>
exit status: 0

No traffic-steering rule was returned at collection time.

text
skywalkctl traffic-rule add -t inet -p {tcp|udp} \
  [-l local-address] [-r remote-address] \
  [-L local-port] [-R remote-port] \
  -q queue-set [-i interface]

skywalkctl traffic-rule add -t eth \
  [-e {eap|wai}] [-m remote-mac] \
  -q queue-set [-i interface]

skywalkctl traffic-rule remove -u RULE_UUID
  • -t: rule type, inet or eth.
  • -p: TCP or UDP for inet rules.
  • -l, -r: local and remote addresses.
  • -L, -R: local and remote ports.
  • -e: Ethernet type (eap or wai).
  • -m: remote MAC address.
  • -q: destination queue-set ID.
  • -i: interface.
  • -u: UUID of a rule to remove.

add and remove were not executed because they change live traffic steering.

23. redirect — manage redirect interfaces

Link to section: 23. redirect — manage redirect interfaces
text
skywalkctl redirect create -t {ethernet|cellular} [-d delegate] INTERFACE
skywalkctl redirect set -d {delegate|none} INTERFACE
skywalkctl redirect destroy INTERFACE

No functional redirect subcommand was intentionally executed.

  • create: creates a redirect interface.
  • set: changes or clears its delegate interface.
  • destroy: destroys the named redirect interface.
text
skywalkctl redirect destroy -h

is not a help command on the tested build. The binary treated -h as an interface name and attempted SIOCIFDESTROY. It failed with Invalid argument, so nothing changed. Do not use this form to discover syntax.

24. aop — inspect AOP network statistics

Link to section: 24. aop — inspect AOP network statistics
Terminal
sudo /usr/sbin/skywalkctl aop
sudo /usr/sbin/skywalkctl aop -b
  • -b, --bitmap: request AOP activity bitmaps.
text
AOP:
skywalkctl: sysctlbyname with buffer for data failed: Operation not supported
exit status: 0

The bitmap form returned no output and exited 0.

The tested hardware/build did not expose the requested AOP statistics. Operation not supported is a platform coverage result, not evidence of corruption or tampering.

25. print-banner — undocumented banner path

Link to section: 25. print-banner — undocumented banner path
Terminal
/usr/sbin/skywalkctl print-banner
text
<no output>
exit status: 0

This appears to be an internal or compatibility path. It performed no visible action on the tested build.


The authoritative evidence set contains:

text
base command sweep:          65 invocations
corrected option variations: 61 invocations
parser matrix:               49 invocations
total:                      175 invocations

Main findings:

  • The Skywalk runtime was populated with 37 providers, 31 nexus instances, and 25 channels.
  • The provider inventory contained 15 net-if, seven flow-switch, ten user-pipe, and five kernel-pipe providers.
  • Flow snapshots changed over time, as expected for live network state.
  • Retained flow rows were not equivalent to established sockets.
  • The JSON flow output had duplicate-key schema defects.
  • netns requires either -a or both IP and protocol.
  • skywalkctl netstat requires -a or -s as a primary mode.
  • protons advertised filters that its parser rejected.
  • status used a missing legacy sysctl and produced an unreliable disabled conclusion.
  • AOP statistics were unsupported on the tested platform.
  • The mutating commands were not executed.
  • Nothing in the results independently demonstrated compromise.

How to interpret empty output and errors

Link to section: How to interpret empty output and errors
ResultInterpretation
Exit 0, no stdout/stderrValid instantaneous empty result.
Operation not permittedPrivilege/coverage gap.
Operation not supportedHardware or build lacks that surface.
Missing sysctlInstalled utility queried a kernel key absent from this build.
flow not foundExact tuple disappeared or was not represented.
Exit 2 from valid netns pairNo matching namespace record on tested build.
Exit 22Invalid or incomplete netns arguments.
Exit 64 or 255Usage/parser result, not a network finding.
Exit 137 in saved wait capturesCollector intentionally terminated an unbounded wait mode.
Terminal
# Flows on one interface
sudo /usr/sbin/skywalkctl flow -n -I en0

# TCP flows only
sudo /usr/sbin/skywalkctl flow -n -p tcp

# Channels for one command
sudo /usr/sbin/skywalkctl channel -C process_name

# One flow-switch instance
sudo /usr/sbin/skywalkctl flow-switch -U <NEXUS_UUID> -v

# One tree subtree
sudo /usr/sbin/skywalkctl tree -U <UUID>

# One flow-ID domain
sudo /usr/sbin/skywalkctl flowidns -v -d inpcb

# One nexus's protocol statistics
sudo /usr/sbin/skywalkctl netstat -s -U <NEXUS_UUID> -v

Prefer numeric output (-n) during evidence collection. It prevents slow name/service resolution and avoids introducing unrelated DNS activity.

Three collectors are included:

ScriptPurpose
collect-read-only.zshEvery top-level command family and primary read-only view.
collect-variations.zshDocumented read-only options, filters, JSON views, and bounded waits.
test-parser-matrix.zshVerified netns and netstat grammar.

Run the base collector:

Terminal
output_directory="$PWD/evidence/$(date -u +%Y%m%dT%H%M%SZ)"

sudo ./scripts/collect-read-only.zsh \
  "$output_directory" "$(id -u)" "$(id -g)"

Each invocation produces:

text
<label>.command       exact shell-escaped command
<label>.stdout        standard output
<label>.stderr        standard error
<label>.exit-status   numeric exit status
<label>.started-utc   start time
<label>.ended-utc     end time

The output directory is mode 700. The collectors never invoke a settings-changing Skywalk command.

Raw skywalkctl output can fingerprint a Mac even when it contains no password or token. Before putting results on GitHub, redact:

  • host and user names;
  • real local and remote IP addresses;
  • identifying port combinations;
  • live PIDs;
  • runtime UUIDs;
  • precise timestamps;
  • application inventory.

Always remove material that could directly grant access:

  • passwords or password hashes;
  • API/session tokens;
  • cookies or authorization headers;
  • private keys;
  • Wi-Fi or VPN secrets;
  • recovery codes;
  • reusable signed URLs.

No access-bearing credential was found in the collected skywalkctl output.

This project is available under the permissive MIT License. Anyone may use, copy, modify, publish, distribute, sublicense, or sell copies, provided the copyright and license notice are retained.

Preview the included man page without installing it:

Terminal
mandoc -Tascii ./skywalkctl.8 | less

This guide documents observed diagnostic behavior. It is not an Apple API contract and should not be used to label unfamiliar networking objects as malicious without independent evidence.

More research