Hourly DetectX Swift scans and MunkiReport

This week I began rolling out DetectX Swift (DTXS) with a Management License across our fleet. I first learned of DTXS earlier this year thanks to Zack McCauley and his DetectX Module for MunkiReport.

McCauley covers one option for automatic scans in his excellent Deploying DetectX Swift with Munki article using Outset and a boot-every script. He also helpfully included a sample LaunchDaemon in the module repo, however neither scans as frequently as I’d like. Read on for how I decided to handle automatic hourly scans and reporting.

First, what is DetectX Swift? Developed by Phil Stokes, DTXS detects “Potentially destabilizing software (PDS), Potentially unwanted software (PUS), Adware (ADW) and Malware.” It does that very quickly and for a very affordable price. Stokes will be quick to tell you that MacAdmins who only interact with DTXS via the command line are missing out on a lot of features the program has to offer.

After testing DTXS and hanging out in the MacAdmins Slack #detectx channel for a while I decided that at only $299 for every computer we own, purchasing DTXS was a no brainer.

Deploying DTXS with Munki is very straightforward. As McCauley covers in his article, all that is needed is a postinstall script to register the application and as a bonus run a full disk scan with results reported to MunkiReport right away. Unlike Zack I’m installing directly into /Applications/ (for better user visibility) so my postinstall looks like this:

"/Applications/DetectX Swift.app/Contents/MacOS/DetectX Swift" register -key "XXXXX-XXXXX-XXXXX-XXXXX-XXXXX-XXXXX-XXXXX-XXXXX-XXXXX-XXXXX-XXXXX-XXXXX-XXXXX-XXXXX-XXXX" -email "email@example.com"

"/Applications/DetectX Swift.app/Contents/MacOS/DetectX Swift" search -aj "/usr/local/munkireport/scripts/cache/detectx.json"

However since I spend a lot of time in MunkiReport I want more current results and don’t want to rely on users rebooting for a scan to happen. The sample LaunchDaemon also only runs at load.

I decided on hourly scans to somewhat correspond with Munki’s hourly runs. However I’m using a LaunchDaemon instead of tying the scan into Munki’s process to avoid any possible slowdowns there. This means at worst, results in MunkiReport should never be more then two hours old.

I also decided to use a separate script to run the scan instead of embedding it into the LaunchDaemon. This allows me to easily run it from the command line as well as edit it later if needed without having to touch the LaunchDaemon.

I packaged them both up and deploy them via Munki set as an update_for DTXS.


<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">



## When run as root, this script will invoke DetectX Swift to scan the entire disk, including all user homes, and export the results as a JSON file that will be displayed in MunkiReport the next time "postflight" runs (approximately every hour).

"/Applications/DetectX Swift.app/Contents/MacOS/DetectX Swift" search -aj "/usr/local/munkireport/scripts/cache/detectx.json"

The package’s postinstall simply loads the LaunchDaemon after installing it:

/bin/launchctl load /Library/LaunchDaemons/com.galvnews.DetectX.search.plist

I’m very happy with the results so far. The rollout has been smooth and essentially transparent to the user base. DTXS detected five computers with “Issues” immediately, something that might have taken me months to notice in the past.

The only things missing now are automated removals by DTXS via the command line and email notifications from MunkiReport. Hopefully those options will arrive in good time.

UPDATE: Alan Siu just shared his method for hourly scans by integrating more directly with Munki. As a bonus he has auto removal of issues functioning as well. Check it out!

UPDATE 10/15/20: The code above was updated to reflect the change in location to write the search results JSON file needed for MunkiReport 5.

Leave a Reply

Your email address will not be published. Required fields are marked *