The FireAI Security Blog

By FireAI Security & Research Team · Published

Audit What Your Mac Sends in 10 Minutes, From the Terminal

Audit What Your Mac Sends in 10 Minutes, From the Terminal

You do not need to install anything to get a real, current picture of what your Mac is talking to. Every tool in this lab ships with macOS. None of them requires you to trust a third party with your traffic, and all six together take about ten minutes to run through once you know the commands. What they will not do, and this matters, is tell you which of those connections are fine and which are not — for that you still need context, and at the end we will be honest about where these tools stop.

1. lsof — every open connection, right now

On Unix, a network socket is a file, and lsof (list open files) lists them. The macOS man page describes -i as selecting files whose internet address matches a given specification — with none given, every internet socket. Add -n to skip resolving addresses to hostnames and -P to skip resolving ports to service names; both make the command faster and the output exact rather than approximate.

Terminal — every open network socket
sudo lsof -i -n -P
# example output, trimmed to a few representative lines
COMMAND   PID   USER   FD   TYPE  DEVICE SIZE/OFF NODE NAME
Mail      612   alice   9u  IPv4  0x...      0t0  TCP 192.168.1.10:54321->17.57.145.13:993 (ESTABLISHED)
Slack     980   alice  22u  IPv4  0x...      0t0  TCP 192.168.1.10:54400->35.186.224.25:443 (ESTABLISHED)
mDNSResp   88   root    4u  IPv4  0x...      0t0  UDP *:5353

Read it left to right: process name and PID, the local address and port, -> and the remote address and port, and the connection state. ESTABLISHED means an active, two-way connection right now. Run without sudo you will still see your own processes; root-owned ones need it. What this cannot tell you: lsof is a snapshot of the instant you pressed Enter. A connection that opened, sent a few kilobytes and closed half a second before you ran the command simply is not there — you need to run it repeatedly, or move to the next tool, to catch that.

2. nettop — the same view, but live

nettop is the live version of the same idea. Its man page describes it as displaying "a list of sockets or routes" with periodically updated statistics. -m route switches it from listing sockets to listing the routing table view; -m tcp or -m udp restrict it to one protocol.

Terminal — live connections, refreshing every second
nettop -m route
# interactive; press q to quit, or use -l N to print N samples and exit
# example output, trimmed
  time                     interface  state       bytes_in  bytes_out
23:41:02.123 Mail.612      en0        Established     4.2K      1.1K
23:41:02.123 Slack.980     en0        Established    18.6K      6.4K

Add -l 5 to grab five samples and exit instead of holding an interactive session, useful if you want to pipe the output somewhere. nettop fixes lsof’s snapshot problem — you can watch a connection appear, transfer data and close — but it inherits the same ceiling: a process name and a PID, nothing about who signed the binary, and no memory once you close the terminal.

3. log stream — what the system itself is saying about the network

macOS keeps a unified, structured log of what every process is doing, and log stream lets you watch it live, filtered. The man page describes --predicate as filtering entries using NSPredicate-style clauses against subsystem, category, process and message content.

Terminal — streaming network-related log entries
log stream --predicate 'eventMessage contains "network" or subsystem == "com.apple.network"' --info
# live stream; Ctrl-C to stop. Example line, trimmed:
2026-09-14 23:41:05.001 process=nesessionmanager subsystem=com.apple.network "TCP Connection ... state changed to Ready"

This is the least approachable of the six tools — the volume is high and the predicate syntax has a learning curve — but it is also the only one that surfaces system-level network state changes and connection lifecycle events as they happen, in plain(ish) English, tagged by the responsible subsystem. Treat it as something to grep, not read line by line: pipe it through grep for a process name you care about, or a keyword like "Wi-Fi" or "VPN".

4. scutil --dns and dig — what your Mac is actually resolving

Before a connection happens, there is usually a DNS lookup. scutil --dns, per its man page, "reports the current DNS configuration": which resolvers are configured, which is the default, and which apply only to specific domains (split DNS, common on VPNs).

Terminal — current DNS resolver configuration
scutil --dns
# example output, trimmed
DNS configuration
resolver #1
  nameserver[0] : 192.168.1.1
  if_index : 12 (en0)
  flags    : Request A records, Request AAAA records
  reach    : 0x00020002 (Reachable,Directly Reachable Address)

dig answers a single question directly: what does this name resolve to, right now. Its man page calls it "a flexible tool for interrogating DNS name servers" valued for "flexibility, ease of use and clarity of output."

Terminal — resolving a single hostname
dig example.com +short
# example output
93.184.216.34

Neither tool tells you which app triggered the lookup or what happened after — DNS only gets you the address an app is about to (or already did) connect to; the connection itself is what lsof, nettop or a firewall log show you.

5. tcpdump — the ground truth, and the one that needs sudo

Everything above reads state the operating system already keeps. tcpdump is different: it captures packets directly off an interface, which is why its own documentation is direct about the requirement — "Reading packets from a network interface may require that you have special privileges" — in practice, sudo on macOS. Use -i to pick the interface, -n to keep addresses numeric, and a filter expression like port 53 to isolate DNS traffic:

Terminal — watching DNS queries leave the machine
sudo tcpdump -i en0 -n port 53
# example output, trimmed
23:41:10.221331 IP 192.168.1.10.54812 > 192.168.1.1.53: 41213+ A? example.com. (30)
23:41:10.244109 IP 192.168.1.1.53 > 192.168.1.10.54812: 41213 1/0/0 A 93.184.216.34 (46)

The pattern to notice: a query going out on port 53 immediately followed by an answer coming back. If you run dig in one terminal while tcpdump runs in another, you can watch the exact query and response your own command produced — a good way to actually believe what the man pages say rather than take them on faith.

A free seventh tool: Activity Monitor

It is worth naming the one graphical option in this list, since not everything needs a terminal. Activity Monitor’s Network tab gives you totals — data sent and received per process, and a live throughput graph — which is the right first stop for "something is chewing through bandwidth and I don’t know what." It is also the clearest illustration of the ceiling every tool in this article shares: it can tell you a helper process moved two gigabytes overnight, and it has no column for where those two gigabytes went. Volume and destination are two different questions, and macOS answers them with two different tools.

Putting the ten minutes together

  1. sudo lsof -i -n -P — get the current list of open sockets, one pass, thirty seconds.
  2. nettop -m route -l 5 — grab a few live samples to catch anything lsof’s snapshot missed.
  3. scutil --dns — confirm which resolver you are actually using, especially if you are on a VPN or public Wi-Fi.
  4. dig <name> +short, on anything unfamiliar from step 1, to see what it currently resolves to.
  5. sudo tcpdump -i en0 -n port 53, for sixty seconds, to watch DNS traffic in the raw as apps go about their business.
  6. log stream --predicate with a keyword grep, if something above raised a question the previous five did not answer.

A worked example

Say step 1 turns up a process called helperd holding an open connection to an address you do not recognize. Do not stop there. Run dig -x <the address> for a reverse lookup — it will not always resolve to something readable, but when it does, a hostname like ads.example-cdn.net tells you more in five seconds than the raw IP ever will. Run nettop -m tcp -l 3 and watch whether that same connection is still open a few seconds later, and whether bytes are actually moving across it or it is sitting idle. If it is idle and reopens on a fixed interval, that is the shape of a periodic check-in rather than a one-off transfer — worth remembering, not automatically worth worrying about, since ordinary update checkers behave the same way. Then check scutil --dns to confirm the resolver that produced whatever address helperd connected to was the one you expected, especially if you are on someone else’s Wi-Fi. Five commands, one process, and you have gone from "I don’t recognize this" to "here is specifically what I know and don’t know about it" — which is the actual goal of an audit like this, more than a verdict of good or bad.

What none of these tools will tell you

Run through all six and you still have three real gaps. First, identity beyond a process name: nothing here checks whether the binary called "Mail" is Apple’s Mail or something that renamed itself, or whether it is signed at all — that is a separate lookup with codesign and spctl. Second, memory: once the terminal window closes, so does everything you learned; there is no log of "what my Mac connected to last Tuesday" unless you build one yourself. Third, judgment: none of these tools has an opinion about whether a connection is expected. A note-taking app connecting to an address it has never used before looks exactly the same in lsof as one connecting to its usual sync server — telling those two apart is pattern recognition you have to bring yourself, or a tool has to bring for you.

How FireAI and HisnLabs fit in

Everything in this lab is free and built into macOS, and none of it names the process behind a connection or remembers it after the terminal closes — which is the specific, narrow gap FireAI’s per-app rules and connection history are built to close.

FireAI is HisnLabs’ own product: an on-device AI firewall for Mac. It shows every connection your apps make, in plain language, and lets you decide what leaves your Mac — its AI runs locally, so your traffic is never sent to us or anyone else. HisnLabs’ security research team is the group that keeps that decision-making accurate: cataloguing which domains are ordinary telemetry versus a real product, tracking the country and network behind a connection, and training the on-device model (its Autopilot feature) on real traffic patterns, all without any of it leaving your Mac.

You can read the technical decisions behind it, or try FireAI for 17 days, at FireAI, by HisnLabs.

Sources