Nick: The macOS Security Suite That Catches What Signatures Miss
Six detection layers. On-device CoreML behavioral scoring. Natural-language alert explanations via Foundation Models. Free, open source, zero cloud dependency.
Platform
macOS 26+
Price
Free · AGPL-3.0
Detection Layers
6 monitors
Cloud
Zero

Context
Developers, security researchers, and technical Mac users who want to understand what is running on their machine at the system level — not trusting a closed-source vendor to tell them, but actually seeing the signals themselves. The audience is people who read the Objective-See blog, run lsof in Terminal, and care about what their LaunchAgents are doing.
After seeing too many developers get hit by reverse shells hidden in developer tooling, persistence dropped by compromised npm packages, and living-off-the-land attacks that generated no signature anywhere, we decided to build the tool we would have wanted to have running.
Problem
macOS ships with solid built-in defences: XProtect performs signature-based malware scanning, Gatekeeper enforces notarisation and code signing, SIP protects system files even from root, and TCC gates sensitive API access behind explicit consent. This is genuinely good security engineering and stops the vast majority of unsophisticated threats.
But sophisticated attacks do not need to bypass any of this. They work around it. A legitimately notarised app can quietly drain your keychain. curl | bash uses Apple's own binary — no signature to flag. A new LaunchAgent dropped by a compromised installer is invisible to XProtect unless it matches a known-bad signature. And a zero-day dropper sequence that looks borderline on each individual signal looks critical when the three events are correlated within 30 seconds.
The four attack categories Apple's stack misses
Behavioral threats
Signed, notarised apps doing malicious things at runtime. Signatures verify provenance — they say nothing about behavior.
Living-off-the-land
curl, osascript, openssl s_client. Apple's own binaries used for reverse shells and payload delivery. No untrusted binary ever runs.
Persistence backdoors
LaunchAgents/Daemons dropped silently by compromised software. No native alert on new persistence unless XProtect has a signature.
Zero-day correlation
Three borderline signals that are individually fine but collectively critical when correlated within a 30-second window.
Existing solutions fell into three buckets: paid/enterprise tools you cannot audit (Norton, Intego, CrowdStrike), Objective-See's excellent but fragmented suite of six separate apps with no correlated view, or cloud-dependent tools that exfiltrate your behavioural data to a vendor server. The gap was one open-source app, zero cloud, with AI correlation.
Constraints
- —Zero cloud dependency. All detection logic, all inference, all alert generation must run on-device. No API keys, no server costs, no data leaving the Mac — ever.
- —Minimal supply chain. Every dependency is an attack surface in a security tool. Nick uses only Apple frameworks plus one vendored C library (libyara). No Swift Package Manager dependencies beyond Apple's own.
- —Privileged helper isolation. Elevated operations must be isolated behind a read-only XPC protocol with code-signature validation on both sides. No shell execution inside the helper.
- —Swift 6 strict concurrency. The codebase must compile under Swift 6 strict concurrency checking — no data races, all shared state behind actors. This includes the C interop layer for libyara.
- —Under 1% CPU, under 50MB RAM. A security tool that degrades system performance is worse than no security tool. All detection monitors must use event-driven APIs, not polling loops, wherever the OS supports it.
- —AGPL-3.0, not MIT. Copyleft ensures the detection logic stays permanently open to the security community regardless of who forks the project in the future.
Architecture
Nick.app (SwiftUI + MenuBar)
└── SecurityEngine (@Observable)
└── MonitorCoordinator
├── ProcessMonitor (sysctl / proc_info)
├── PersistenceWatcher (FSEvents → LaunchAgents/Daemons/LoginItems/extensions)
├── NetworkAnalyzer (NWPathMonitor / sysctl / lsof -i)
├── FileSystemWatcher (FSEvents → monitored directories)
├── YARAEngine (libyara C interop → Swift actor)
├── AVCaptureMonitor (CoreMediaIO / CoreAudio)
└── SystemAudit (csrutil / fdesetup / spctl / TCC / sudo)
│
└── ThreatCorrelator (30-second sliding window)
└── BehavioralScorer (CoreML .mlmodelc)
└── Foundation Models (on-device alert explanations, macOS 26+)
NickHelper.xpc (SMAppService)
└── Read-only elevated checks (codesign validation on both XPC sides)Six Detection Layers
| Layer | OS API | What It Catches |
|---|---|---|
| System Integrity Audit | csrutil, fdesetup, spctl, pfctl | SIP off, FileVault off, Gatekeeper disabled, firewall gaps, outdated XProtect, TCC anomalies, sudo misconfiguration |
| Persistence Monitor | FSEvents | New LaunchAgents/Daemons, Login Item changes, cron jobs, browser extension installs — diffed against a baseline snapshot |
| Network Watchdog | NWPathMonitor, sysctl, lsof -i | Reverse shells (shell process + outbound TCP), SSH tunnels (-L/-R/-D flags), raw IP connections (no DNS), known malicious domains |
| Process Auditor | sysctl, proc_info | Unsigned binaries, /tmp execution, LOLBin patterns (curl→bash, osascript+base64), suspicious parent→child chains |
| YARA Scanner | libyara C interop | Mach-O shellcode patterns, embedded raw IPs, base64-encoded payloads, community-contributed macOS rule sets |
| Camera & Mic Sentinel | CoreMediaIO, CoreAudio | Unexpected activation attributed to non-system processes, unsigned binary with media hardware access |
ThreatCorrelator: The AI Layer
Individual signals are noisy. A curl download to /tmp could be a legitimate install script. An unsigned binary could be a developer build. The correlation window is what makes signals actionable.
// Rule-based correlation (fires before CoreML scoring) 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 a ~40-feature vector is fed to the CoreML behavioral model for a continuous 0.0–1.0 threat probability. Alert thresholds: <0.3 silent log, 0.3–0.6 low notification, 0.6–0.8 medium with context, >0.8 high-priority alert with recommended action. On macOS 26, plain-English explanations are generated on-device via Foundation Models — no cloud call, no account required.
XPC Privileged Helper
NickHelper.xpc is registered via SMAppService and holds the elevated entitlements needed for full system inspection. The helper validates the calling app's code signature before responding to any request and exposes a strictly read-only protocol — no shell execution, no file writes, no network calls. All checks are implemented using Foundation APIs or direct syscalls. This isolation means a vulnerability in the main app UI cannot escalate to privileged execution.
YARA C Interop in Swift 6
libyara is a C library with complex manual memory management. Bridging it safely into Swift 6's strict concurrency model — actors, structured concurrency, typed throws — while avoiding double-frees and data races across concurrent scan sessions required explicit isolation at every C-to-Swift boundary. Rules are compiled at launch and cached as a read-only inference artifact. Malformed community rules cannot crash the engine because the rule loader validates syntax before compilation.
In Practice

System Integrity Audit — full posture baseline with actionable recommendations

YARA Scanner — real-time scanning with rule compilation cache

Process Auditor — live process list with signing status, location, and parent-chain depth
Technical Decisions
- —CoreML over cloud AI. Running inference on-device means zero latency from network round-trips, works offline, and keeps behavioural data private. The model ships as a read-only .mlmodelc bundle that cannot be poisoned at runtime. On Apple Silicon, CoreML routes appropriate operations to the Neural Engine — inference on the 40-feature vector completes in microseconds.
- —FSEvents over polling. Polling persistence directories every N seconds is expensive and introduces latency. FSEvents delivers kernel-level file system change notifications immediately. The tradeoff is that FSEvents can drop events under very high I/O load, so the persistence watcher uses a fallback polling mechanism triggered when the event queue depth exceeds a threshold.
- —Zero third-party Swift dependencies. Every dependency is an attack surface in a security tool. A supply-chain attack against a popular Swift package could compromise the tool designed to detect supply-chain attacks. Nick's only non-Apple dependency is libyara, vendored directly from the upstream source and compiled locally — no package manager, no remote resolution.
- —Hardened runtime + library validation. Nick itself runs with Apple's hardened runtime and library validation enabled, preventing injection of dynamic libraries that haven't been signed with the app's certificate. This is especially important for a process that holds Full Disk Access.
- —AGPL-3.0 for permanent openness. MIT would allow a vendor to fork Nick, improve the behavioral scoring model, and ship a closed-source product without contributing back. AGPL's copyleft requirement on service operators ensures the detection logic stays auditable by the security community permanently. Security tools should be auditable.
What Was Hard to Build
LOLBin detection without false positives. curl and osascript run legitimately millions of times per day on developer machines. The signal is in the combination: osascript plus a base64-decoded payload plus an unsigned parent process. Tuning the correlation rules to catch the dangerous combination without firing on normal developer workflows required running against diverse Mac configurations across different developer environments.
XPC security hardening. The privileged helper is the highest-risk component — it holds elevated entitlements and must never execute attacker-controlled input. Getting code-signature validation right on both sides of the XPC connection, handling edge cases where the signing identity changes during development builds, and ensuring the helper exposes zero unnecessary surface took significant iteration. The validation logic was reviewed against Apple's XPC security documentation and cross-checked with known XPC privilege escalation CVEs.
CoreML training pipeline bootstrapping. The behavioral model needs labeled data: known-good macOS activity and known-bad malware behavior. Bootstrapping this training set before real users existed required synthetic data generation from documented malware TTPs — MITRE ATT&CK for macOS, the Objective-See blog archive, and published malware analyses from academic and industry security research.
Swift 6 strict concurrency with C interop. The libyara layer is fundamentally imperative and non-thread-safe by default. Wrapping it in a Swift actor, handling the lifetime of compiled rules and scan contexts across concurrent scan sessions, and satisfying the Swift 6 concurrency checker at every boundary required designing a careful ownership model for the C objects. The compiler found genuine races in early iterations.
Comparison
| Feature | Nick | Obj-See Suite | macOS Built-in | Intego |
|---|---|---|---|---|
| Behavioral AI scoring | ✅ | ❌ | ❌ | ❌ |
| Correlated threat detection | ✅ | ❌ | ❌ | ❌ |
| YARA scanning | ✅ | ❌ | ❌ | ✅ |
| Single unified app | ✅ | ❌ (6 apps) | ✅ | ✅ |
| Open source | ✅ | ✅ | ❌ | ❌ |
| No cloud dependency | ✅ | ✅ | ✅ | ❌ |
| Free forever | ✅ | ✅ | ✅ | ❌ ($40–70/yr) |
| Foundation Models explanations | ✅ | ❌ | ❌ | ❌ |
Outcome
6
detection layers
in one native SwiftUI app
<1%
CPU in steady state
event-driven, not polling
0
cloud dependencies
all inference on-device
Nick v1.0 ships as a notarised DMG from GitHub Releases and is available as a Homebrew cask. Every line of code is public at github.com/EhsanAzish80/Nick. The YARA rule set, CoreML model training pipeline, and XPC protocol are all included in the open-source repository — nothing is held back.
Frequently Asked
- Why does macOS need a third-party security tool if it has XProtect and Gatekeeper?
- XProtect and Gatekeeper are signature-based — they catch known-bad binaries. They cannot detect behavioral threats: a signed app draining your keychain, a reverse shell using Apple's own curl binary, or a zero-day dropper that correlates three borderline signals into a critical incident. Nick's behavioral scoring layer catches these patterns.
- How does Nick's CoreML behavioral scoring work?
- The ThreatCorrelator maintains a 30-second sliding window across all monitor outputs. Rule-based correlation fires first for known patterns. Then a ~40-feature vector is fed to a CoreML model for a 0.0–1.0 threat probability. All inference runs on-device — no data leaves the Mac.
- Why AGPL-3.0 instead of MIT?
- AGPL's copyleft ensures that if any company runs a modified version as a hosted service, they must release their source changes. This keeps the detection logic permanently open to the security community. MIT would allow a vendor to fork Nick and ship a closed-source product without contributing back.
- Does Nick replace an antivirus?
- Nick is complementary to, not a replacement for, signature-based tools. It adds behavioral and correlation-based detection that signature scanners miss — but it is not a replacement for XProtect's definition database for known malware families.
- What made YARA C interop in Swift 6 difficult?
- libyara has complex manual memory management. Bridging it into Swift 6's strict concurrency model — actors, structured concurrency, typed throws — while avoiding double-frees and data races across concurrent scan sessions required careful design at every C-to-Swift boundary. The Swift 6 compiler caught genuine races in early iterations.
More case studies: view all