Nick: Why We Built an Open-Source macOS Security Suite with On-Device AI
macOS ships with solid built-in security — but signature-based defences miss behavioral threats, living-off-the-land attacks, and zero-day dropper sequences. Nick is the open-source answer: one app, six detection layers, and on-device CoreML behavioral scoring. Here's why we built it and how it works.
Introduction
macOS has a well-earned reputation for security. But there is a category of threat that Apple’s built-in stack was never designed to catch: behavioural attacks that use legitimate tools, live off the land, and leave no signature for XProtect to find.
After seeing too many developers get hit by reverse shells hidden inside developer tooling, LaunchAgents silently dropped by compromised installers, and unsigned binaries executing from /tmp after a rogue npm package ran post-install scripts — we decided to build something.
Nick is our answer: a free, open-source native macOS security suite with on-device AI behavioural scoring, six detection layers, and zero cloud dependency. Every line of code is public, auditable, and protected under AGPL-3.0.
What macOS already does well
Before explaining what Nick adds, it is worth being clear about what macOS already does right.
XProtect performs signature-based malware scanning automatically and silently. Every time you launch a downloaded app, XProtect checks it against Apple’s malware definition database. It has gotten substantially better in recent years with more frequent definition updates.
Gatekeeper enforces code signing requirements on first launch. A binary downloaded from the internet must be either App Store-distributed or notarized by a developer with an Apple Developer certificate. This eliminates entire categories of casual malware distribution.
System Integrity Protection (SIP) protects system files and directories from modification even by root. It prevents the kind of deep system compromise that plagued early macOS malware.
TCC (Transparency, Consent, and Control) gates access to sensitive APIs — camera, microphone, Full Disk Access, screen recording — behind explicit user consent prompts. This is why every app has to ask for permissions individually.
This is genuinely good security engineering. Most casual threats die here.
What it misses
The problem is that sophisticated attacks don’t need to bypass any of these mechanisms. They work around them.
Behavioural threats
A legitimately signed, notarised app that exfiltrates your keychain is invisible to Gatekeeper. Signatures verify that a binary was not tampered with after signing — they say nothing about what the binary does at runtime. An info-stealer that passed Apple’s notarisation review is indistinguishable from a legitimate app as far as Gatekeeper is concerned.
Living-off-the-land attacks
curl | bash, osascript with base64-encoded payloads, openssl s_client reverse connections. These attacks use Apple’s own binaries to execute malicious code. No signature is needed. No untrusted binary ever runs. XProtect sees nothing to flag.
Persistence
Most malware’s first move after initial access is dropping a LaunchAgent or LaunchDaemon to survive a reboot. macOS has no native “something changed here” notification for persistence locations. XProtect will not alert on a new LaunchDaemon unless it matches a known-bad signature — and zero-day dropper sequences, by definition, do not match any known signature.
Tunnel detection
SSH port forwarding, SOCKS proxies, reverse shells. The Application Firewall sees an ssh process with a valid outbound connection and calls it fine. There is no native mechanism to flag that ssh is being used for lateral movement or C2 communication.
Zero-day correlation
A dropper sequence that individually looks borderline — a new process in /tmp, an unsigned binary executing, an outbound connection to an IP with no DNS resolution — looks like a critical incident when the three events are correlated within a 30-second window. No signature-based tool catches this because no individual event crosses any threshold.
Why not just use existing tools?
Paid and enterprise
Norton ($59/yr), Intego ($40–70/yr), CrowdStrike, SentinelOne. These work, but you are trusting a black box. Your behavioural data may leave your machine. You pay forever. And for individual developers and researchers, enterprise pricing is a non-starter.
Objective-See’s suite
Patrick Wardle’s tools are excellent and genuinely open-source. BlockBlock catches persistence, LuLu is a firewall, KnockKnock audits installed software, OverSight catches camera/mic access. But it is six separate apps, each requiring its own permissions, each with its own UI, each with no awareness of what the others are seeing.
There is no correlated view. No unified threat score. No AI correlation across events from different monitors. If a reverse shell opens while BlockBlock sees a new LaunchAgent and OverSight detects mic access — you get three separate notifications from three separate apps with no way to know they are related.
The gap
One app. Unified view. Open-source. With correlated AI scoring. That did not exist. Nick is that tool.
How Nick works
Six detection layers
System Integrity Audit is a security posture baseline. On demand, it checks SIP status, FileVault encryption, Gatekeeper configuration, Application Firewall rules and stealth mode, XProtect definition currency, TCC database integrity, and sudo configuration. Think of it as a structured checklist with actionable recommendations for each finding.
Persistence Monitor uses FSEvents to watch every known macOS persistence location in real time: /Library/LaunchDaemons, /Library/LaunchAgents, ~/Library/LaunchAgents, Login Items, cron jobs, periodic scripts, System Extensions, and browser extension directories for Safari, Chrome, Firefox, and Arc. When a new file appears in any of these locations, Nick parses the plist, validates the code signature of the referenced executable, and diffs against a baseline snapshot created on first run. A new file in a LaunchDaemon directory emits a .high signal immediately.
Network Watchdog maps every active connection to its owning process by combining NWPathMonitor, sysctl output, and lsof -i parsing. It detects reverse shells by identifying shell processes (bash, zsh, sh, python) with active outbound TCP connections. It identifies SSH tunnels by inspecting ssh process arguments for -L, -R, and -D flags. It flags connections from shell processes to raw IP addresses (no DNS resolution is a strong indicator of C2 traffic), and alerts on connections to known malicious domains loaded from the rules directory.
Process Auditor polls running processes via sysctl and proc_info every 5 seconds. It flags unsigned or ad-hoc signed binaries, execution from /tmp, /var/tmp, or hidden directories, LOLBin patterns (curl piping to sh, osascript with base64-encoded payloads, openssl s_client connections), and suspicious parent-child chains — for example, a web browser spawning bash which spawns curl.
YARA Scanner wraps the libyara C library in a Swift interface via C interop. Rules are compiled at app launch and cached. It ships with a curated set of macOS-specific YARA rules and supports community-contributed rules via the Rules/community/ directory. Scanning modes include quick scan (critical directories, roughly 30 seconds), full scan, targeted scan (user-initiated drag-and-drop), and real-time scan triggered by FSEvents on new files in monitored directories. Heuristic analysis includes entropy scoring, Mach-O header inspection, and embedded URL and IP address extraction.
Camera and Microphone Sentinel monitors all CoreMediaIO video devices and CoreAudio input devices for unexpected activation. It attributes each activation to the most-recently-launched non-system process and escalates to .high severity when an unsigned binary is found with media hardware access. A baseline-delta approach means only new activations trigger alerts — a video call you already approved keeps running silently.
The AI layer: behavioral scoring
This is where Nick differs from every other tool in this space.
Individual signals are inherently noisy. An unsigned binary executing could be a developer build. A new outbound connection could be a software update. A new LaunchAgent could be legitimate software installing a background service.
Correlation is what makes signals actionable.
Nick’s ThreatCorrelator maintains a 30-second sliding window across all monitor outputs. It applies rule-based correlation first — hand-written rules for known-bad patterns:
IF ProcessMonitor.unsigned_binary_executing
AND FileSystemWatcher.new_file_in_tmp (same path, within 10s)
AND NetworkAnalyzer.outbound_connection (same PID, within 30s)
THEN score: 0.92 — "Dropper behavior detected"
IF NetworkAnalyzer.shell_with_outbound_connection
AND ProcessMonitor.parent_not_terminal
THEN score: 0.95 — "Possible reverse shell"
Then it feeds a ~40-feature vector to a CoreML behavioral model for a continuous 0.0–1.0 threat probability. Feature categories include process attributes (signing status, location, parent chain depth), network attributes (connection count, destination type, port), filesystem attributes (file entropy, location, creation recency), and temporal attributes (time between events).
Alert thresholds:
| Score | Action | |---|---| | < 0.3 | Logged silently | | 0.3–0.6 | Low-priority notification | | 0.6–0.8 | Medium notification with context | | > 0.8 | High-priority alert with recommended action |
On macOS 26, alert explanations are generated on-device via Foundation Models — plain English, no cloud call: “A process at /tmp/update downloaded by Safari opened an outbound connection to 185.x.x.x:443. This matches a dropper pattern. Review recommended.”
No data ever leaves your Mac.
What was hard to build
LOLBin detection without false positives
curl and osascript run legitimately millions of times per day. The signal is in the combination: osascript plus a base64-decoded payload plus an unsigned parent process. Tuning the correlation rules to flag the dangerous combination without alerting on normal developer usage required running against diverse Mac configurations — developer machines, clean macOS installs, production environments with unusual software.
XPC security hardening
The privileged helper is the highest-risk component of the codebase. Getting code-signature validation right on both sides of the XPC connection, handling edge cases where the signing identity changes during development, and ensuring the helper exposes zero unnecessary surface took significant iteration. The helper is intentionally read-only — no write operations, no shell execution, all checks via Foundation APIs or direct syscalls.
YARA C interop in Swift 6
libyara is a C library with complex memory management. Bridging it safely into Swift’s strict concurrency model — actors, structured concurrency, typed throws — while avoiding double-frees and data races across concurrent scan sessions required careful design. The Swift 6 strict concurrency checker was simultaneously helpful (it caught genuine races) and demanding (every boundary between the C layer and Swift actors needed explicit isolation).
CoreML training pipeline
The behavioral model needs labeled data: known-good macOS activity and known-bad malware behavior. Bootstrapping this training set before there are real Nick users required synthetic data generation from documented malware TTPs (Tactics, Techniques, and Procedures) in the macOS threat research corpus — MITRE ATT&CK for macOS, documented malware analyses, and the Objective-See blog archive.
FSEvents reliability
FSEvents misses events under high I/O load and coalesces rapid file creation into batch events. The persistence watcher needed a fallback polling mechanism to catch dropped events during intensive installs. Getting the balance right between event-driven responsiveness and polling-based reliability took several iterations.
Why AGPL and why open source
Security tools ask for deep trust. Full Disk Access. Network monitoring. Camera and microphone access. A privileged helper with elevated permissions. For a closed-source tool, you are trusting the vendor’s word that these permissions are used only as advertised. For Nick, you can read every line that runs with those permissions. Audit the helper. Verify the signatures. Check the XPC protocol yourself.
AGPL-3.0 was chosen deliberately over MIT or Apache. AGPL’s copyleft ensures that if a company forks Nick and runs a modified version as a hosted service — a “cloud security scanner powered by Nick” — they must release their changes. The detection logic stays open to the security community permanently. This is the same reason the Linux kernel uses GPL.
Transparency also acts as a quality forcing function. Public code invites scrutiny. A privileged helper with a questionable XPC implementation will get flagged by the community. That pressure produces a more secure tool.
Roadmap
v0.1 — Foundation ✅
System integrity audit, LaunchAgent/Daemon monitoring, process auditor, network connection viewer, SwiftUI menu bar app.
v0.5 — Active Detection ✅
FSEvents watcher, YARA engine integration, heuristic analysis, real-time notification system, privileged helper.
v0.9 — AI Behavioral Scoring ✅
ThreatCorrelator, CoreML behavioral scoring pipeline, Foundation Models alert explanations, camera and microphone sentinel, threat log with forensic detail.
v1.0 — Public Release ✅ Released
Third-party security audit of privileged helper and detection engine, false-positive tuning across diverse Mac configurations, performance target <1% CPU and <50MB RAM, Homebrew cask, comprehensive documentation.
Future
DNS-over-HTTPS tunnel detection, community rule marketplace, Endpoint Security framework integration (pending Apple entitlement), Network Extension for blocking capability, enterprise MDM deployment support.
Conclusion
Nick is a bet that the macOS security community deserves a tool that is both capable and trustworthy — not because a vendor says so, but because the code is right there.
If you are a developer, security researcher, or someone who wants to actually understand what is running on your Mac, Nick was built for you.
Download the latest release, build from source, or contribute a YARA rule. The code is at github.com/EhsanAzish80/Nick.