Practical "Secure-ish" Developer Mac Setup
Let’s be honest: most developers run their Mac wide open. We curl scripts from the internet, pip install random packages, clone repos from strangers, and run Docker containers that could be doing anything. We know better, but security always feels like it’s in the way.
This guide is my attempt at a realistic security setup for a developer Mac. Not paranoid, not enterprise-grade, not “you need a SIEM and a SOC team.” Just practical layers that put you well above most professional developer setups without making your daily workflow miserable.
The Core Insight: Egress Control
On macOS, the single biggest improvement against supply-chain compromise is egress control: limiting what apps can talk to the internet and where they can connect.
A malicious dependency, npm package, poisoned update, or trojanized binary becomes far less useful if it:
- Cannot reach C2 (command & control)
- Cannot exfiltrate tokens
- Cannot laterally move
- Cannot download second-stage payloads
macOS ships with a fairly weak outbound firewall model by default. The built-in firewall only handles inbound connections. That’s half the story. You need to know what’s going out.
The Full Stack
| Layer | Tool | Why |
|---|---|---|
| Outbound firewall | Little Snitch / LuLu | Know what phones home |
| Dev tooling lockdown | Per-app domain rules | Block unexpected outbound from npm/pip/cargo |
| Persistence monitoring | KnockKnock + BlockBlock | Catch malware persistence |
| DNS filtering | NextDNS / Control D | Block trackers & malicious domains |
| Secrets management | 1Password + YubiKey + Touch ID | No plaintext secrets, ever |
| SSH agent hardening | Per-org keys + lifetime limits | Prevent key theft |
| Dev isolation | Separate macOS user | Contain the blast radius |
| High-risk code | VM / container | Sandbox untrusted stuff |
| Endpoint scanning | Loki-RS | Detect indicators of compromise |
| Browser hygiene | Separate profiles per trust zone | Compartmentalize browsing |
Let’s dive into each layer.
1. Outbound Application Firewall
Little Snitch
Little Snitch is the most mature macOS-native option. Excellent for:
- Per-app outbound filtering
- Domain-level rules
- Temporary rules (allow for 1 hour, then block again)
- Live connection inspection
- Detecting weird dev-tool behavior
What you’ll catch:
nodesuddenly talks to185.x.x.x, a malicious npm package phoning home- A VSCode extension connects to a random VPS
- A Python wheel downloads a payload from GitHub raw
- Hidden updaters and unexpected telemetry
You’ll see it immediately.
Pro tip: Set Little Snitch to "Silent Mode - Deny" for a few hours
and check what breaks. You'll learn a lot about your system.
LuLu
LuLu is the free/open-source alternative from Patrick Wardle’s Objective-See. It’s lightweight, privacy-focused, and has solid defaults. Less polished than Little Snitch, but excellent value if you don’t want to pay.
2. Block by Default for Developer Tooling
This matters more than most people realize. Your dev tools are the primary attack surface now.
Common high-risk binaries that most developers give unrestricted internet access:
node npm pnpm bun
python pip uv
cargo go java
docker kubectl terraform
Instead of allowing them unrestricted outbound access, allow only specific domains:
| Tool | Allowed Domains |
|---|---|
| npm | registry.npmjs.org |
| pip / uv | pypi.org, files.pythonhosted.org |
| cargo | crates.io, static.crates.io |
| go | proxy.golang.org |
| docker | Trusted registries only |
| brew | homebrew.bintray.com, ghcr.io |
A malicious dependency that tries to call evil-server.xyz during install? Blocked immediately. The package fails, you investigate, crisis averted.
In Little Snitch, create rules per binary:
node→ allowregistry.npmjs.org→ deny everything elsepython→ allowpypi.org→ deny everything else
This single practice kills the majority of supply-chain attacks dead.
3. Persistence Monitoring: KnockKnock + BlockBlock
These are two free tools from Objective-See, the gold standard for macOS security:
KnockKnock scans your Mac for persistently installed software: things that survive a reboot. Launch agents, login items, kernel extensions, browser plugins, cron jobs. Run it periodically and look for anything you don’t recognize.
BlockBlock is the real-time version: it monitors persistence locations and alerts you the moment something tries to install itself permanently. If malware lands on your Mac, it almost certainly needs persistence. BlockBlock catches that moment.
brew install --cask knockknock
brew install --cask blockblock
Supply-chain malware often installs:
- LaunchAgents / LaunchDaemons
- Login items
- Browser extensions
- Cron jobs
BlockBlock watches all of these locations.
4. DNS Filtering: NextDNS
NextDNS is like Pi-hole in the cloud. Configure it once, point your Mac’s DNS at it, and it blocks:
- Known malware domains
- Phishing infrastructure
- Tracking & analytics domains
- Newly registered domains (often malicious)
- Cryptomining domains
Supply-chain malware often dies here because it can’t resolve the C2 domain, so it can’t phone home.
brew install nextdns
sudo nextdns install -config YOUR_CONFIG_ID
sudo nextdns activate
The free tier gives you 300,000 queries/month. The real power is in the logs: you can see exactly what every app on your system is resolving. Control D is another excellent option with more customization.
5. Secrets: 1Password + YubiKey + Touch ID
Developer credentials are the primary target of modern supply-chain attacks:
- AWS creds
- Database credentials
- npm tokens
- GitHub PATs
- API keys
These are what attackers want. Lock them down:
Use 1Password CLI to inject secrets at runtime:
# Instead of plaintext .env files
export AWS_ACCESS_KEY_ID=$(op read "op://Dev/AWS/access-key-id")
export AWS_SECRET_ACCESS_KEY=$(op read "op://Dev/AWS/secret-access-key")
Add hardware-backed auth with a YubiKey for critical accounts (GitHub, AWS, Google). Even if someone steals your password, they can’t log in without the physical key.
Prefer short-lived credentials:
- AWS IAM Identity Center / SSO instead of long-lived access keys
- GitHub fine-grained tokens with expiration
- OAuth flows instead of permanent API keys
Avoid at all costs:
- Plaintext
.envfiles in repos - Long-lived AWS access keys
- Permanent GitHub PATs
- Secrets in shell history
6. SSH Agent Hardening
Huge overlooked risk. Malicious build tools increasingly target:
SSH_AUTH_SOCK- GitHub auth
- Signing keys
A compromised npm package can access your SSH agent and authenticate to your servers. Recommendations:
Use separate SSH keys per org/project:
~/.ssh/id_ed25519_work
~/.ssh/id_ed25519_personal
~/.ssh/id_ed25519_client_x
Require Touch ID / YubiKey confirmation for key usage:
# Generate a hardware-backed SSH key
ssh-keygen -t ed25519-sk -O resident -O verify-required
This key lives on the YubiKey. You physically touch the key for every SSH connection.
Use agent lifetime limits:
# Key is only available for 1 hour
ssh-add -t 1h ~/.ssh/id_ed25519_work
Configure per-host in ~/.ssh/config:
Host github.com-work
HostName github.com
User git
IdentityFile ~/.ssh/id_ed25519_work
AddKeysToAgent yes
UseKeychain yes
Host github.com-personal
HostName github.com
User git
IdentityFile ~/.ssh/id_ed25519_personal
7. Dev Isolation: Separate macOS Users
This one is massively underrated. Most supply-chain attacks assume:
- Same browser session
- Same SSH agent
- Same token store
- Same password manager session
Create separate macOS user accounts:
| Activity | Environment |
|---|---|
| Banking / personal | Main macOS user |
| Development | Separate dev user |
| High-risk reversing | VM |
| Random GitHub repos | Disposable VM/container |
If a malicious npm package runs code during install, it can access everything in your user directory. With a separate dev user, the blast radius shrinks dramatically. Your personal files, browser sessions, and banking credentials are in a different account entirely.
Fast User Switching makes bouncing between accounts painless.
8. VMs and Containers for Unknown Code
Very important for:
- Random GitHub repos you want to try
- PoCs and prototypes
- AI-generated code (you don’t know what it does)
- Malware analysis
- npm experiments with unknown packages
Good isolation options:
- Docker Desktop / OrbStack: fast containers on Apple Silicon
- Lima: lightweight Linux VMs
- UTM: full VM emulation
- Parallels: commercial option
For quick isolation:
# Run untrusted code in a disposable container with no network!
docker run --rm -it -v $(pwd):/code --network none python:3.12 bash
The --network none flag is key: the code can’t call home.
For truly sketchy repos, use a disposable Linux VM with:
- No mounted secrets
- No host SSH agent forwarding
- No password manager access
- No shared clipboard (if you’re paranoid)
# OrbStack: create, use, destroy
orb create ubuntu:22.04 sandbox
orb shell sandbox
# do your sketchy stuff
orb delete sandbox # gone
9. Browser Hygiene: Profiles per Trust Zone
Your browser is the biggest attack surface on your machine. Use separate profiles:
- Personal: email, banking, social media (strict extensions)
- Work: company tools, Slack, Jira
- Dev/Research: GitHub, Stack Overflow, docs
- Throwaway: random links from chat, sketchy downloads (no logged-in accounts)
In Chrome/Firefox, profiles are completely isolated: different cookies, extensions, history. A compromised session in one profile can’t access another.
Firefox tip: Use Firefox Multi-Account Containers for even more
granular isolation within a single profile.
The “I Don’t Have Time” Minimum
If you only do three things from this list:
- Install Little Snitch + block dev tools by default: this kills most supply-chain attacks
- Use 1Password for secrets: stop putting keys in .env files
- Separate browser profiles: don’t browse sketchy links where you’re logged into AWS
That alone puts you ahead of 90% of developers.
The Mindset Shift
The most effective change isn’t a tool. It’s a mindset:
Treat developer tooling as untrusted internet-facing software.
Because modern attacks target:
- Package managers
- CI/CD pipelines
- IDE extensions
- Browser sessions
- Tokens and credentials
…not the kernel. The attack surface has moved up the stack. Your security should too.
Further Reading
- Apple Platform Security: Protecting Against Malware: Apple’s official documentation on XProtect, Gatekeeper, Notarization, and the layered malware defense built into macOS.
- Objective-See: Free macOS Security Tools: Patrick Wardle’s full collection of free, open-source macOS security tools including LuLu, BlockBlock, KnockKnock, and more.
Stay safe out there. 🔐