Introduction
blackice is an application firewall for macOS, run from the command line. It sees every new outbound connection, from any app, and treats it by mode:
accept-alllets everything through and logs it.askholds a connection that no rule covers until you or an agent answers. No answer in time means it is dropped.block-alllets through only what your rules allow.
blackice 1.0.7 has run on one Mac, with macOS 27.0.1; macOS 14 and 15 are not tested yet. A blackice.toml that works in 1.0 keeps working in every 1.x.
Install has the steps.
Ask mode
Rules, the built-in list of macOS services and current approvals are checked first, so only new destinations wait. You answer with blackice approve or blackice deny, or from the menu bar, with Touch ID. An agent answers through a hook: the daemon runs it and reads its last line, approve 1h or deny. An approval covers one app and one host, and expires. A deny is remembered for 10 minutes.
The parts
- Blackice.app, in
/Applications, holds the network extension and theblackicecommand, which is also the menu bar app. - The extension sees each new connection, and allows, holds or drops it.
- The daemon runs the hooks, as a LaunchAgent for your user. It takes them from the configuration saved with Touch ID, never from a file, and answers with the event's one-time token, which the hook never sees.
Limits
- Any program running as you can steer a hook: rewrite the event file while the agent reads it, or the rules and sign-in in the agent's home, and so get its own connection approved. An approval still covers only the event's app and host, for at most 24 hours.
- Host and app names come from whoever opens the connection, and they reach the agent's prompt. The only answers taken are
denyandapprovewith a duration, for the event's app and host. - A program running as you can stop the daemon. Connections then wait and are dropped at their timeout.
- A tool that connects to an address, such as
curl, fails on its first try when the answer takes longer than the server waits, and gets through on the retry. Apps that connect by name wait for the answer. - A
runhook's program is not checked. Aprogramhook starts only when its signature matches, and with SIP off macOS does not check that before it runs.