Introducing my new macOS Security Tool: Mergen.

Samet Sazak
7 min readApr 23, 2023

--

Mergen is an open-source, native macOS application for auditing and checking the security of your MacOS.

It’s been a while since I have been working on my new open-source project, and today I want to give some information about my tool.

In the beginning, the idea I had in mind was to create a tool that follows CIS Benchmark, addresses my privacy concerns, and improves the security of my MacOS devices. The CIS Benchmark is an excellent resource offering comprehensive guidelines for securing various systems, including Mac devices developed by a community of cybersecurity experts…

So, I decided to start writing some simple scripts to run a few tasks:

a. Run a terminal command associated with a specific security issue.
b. Check the command output to determine the issue’s status

Such as:

Ensure Gatekeeper Is Enabled

spctl --status
assessments enabled

or SIP status or iCloud is enabled or not.

Here is an example check() function:

    override func check() {
let task = Process()
task.executableURL = URL(fileURLWithPath: "/bin/launchctl")
task.arguments = ["print-disabled", "system"]

do {
let outputPipe = Pipe()
task.standardOutput = outputPipe
try task.run()
task.waitUntilExit()

if task.terminationStatus == 0 {
let outputData = outputPipe.fileHandleForReading.readDataToEndOfFile()
let outputString = String(data: outputData, encoding: .utf8)

if let outputString = outputString, outputString.contains("\"com.apple.AEServer\" => disabled") {
status = "Remote Apple Events is Disabled"
checkstatus = "Green"
} else {
status = "Remote Apple Events is Enabled"
checkstatus = "Red"
}
} else {
status = "Error checking Remote Apple Events status"
checkstatus = "Yellow"
}
} catch let e {
print("Error checking \(name): \(e)")
checkstatus = "Yellow"
status = "Error checking Remote Apple Events status"
self.error = e
print(e)
}
}

RemoteAppleEventsDisabledCheck, which inherits from a base class called Vulnerability.

This base class contains properties like name, description, category, and severity. It also has a check() function, which we will override to implement our custom logic.

The Check Function

The primary goal of this check() function is to verify if Remote Apple Events are disabled on the system. We’ll use the launchctl command to achieve this, which manages system services like daemons, agents, and XPC services.

  • Create a Process instance called task. This will allow us to run a system command.
  • Define command arguments: Set the arguments property of task to [“print-disabled”, “system”]. This tells launchctl to display a list of disabled system services.
  • Output redirection: Create a Pipe instance named outputPipe and assign it to the standardOutput property of task. This lets us capture the output of the launchctl command.
  • Wait for task completion: Use the waitUntilExit() method to wait until the task has finished executing.
  • Check termination status: If the terminationStatus of task is 0, the command ran successfully. Otherwise, an error occurred, and we should update the status and check status accordingly.
  • Process command output: If the command executed successfully, read the data from outputPipe and convert it to a UTF-8 encoded string named outputString.
  • Determine Remote Apple Events status: Look for the string “”com.apple.AEServer” => disabled” in outputString. If found, Remote Apple Events are disabled, and we should update the status and check status accordingly. If not found, Remote Apple Events are enabled.

I started writing all the scripts like this in Python, but it became difficult to manage as the number of scripts increased. I wanted to combine them with a simple command-line interface but then gave up, and I created a GUI for easier use. This was the challenging part. I tried a few GUI applications with PyQT and Tkinter, but I was not satisfied with the output at all (Adding some terrible GUI examples).

Old version

Since this app isn’t that complicated, I thought I could build it with Swift and make it a native Mac app with a beautiful GUI. + The idea of learning something new sounded pretty cool to me. After struggling with Python, Tkinter, and QT, I installed Xcode and jumped into it.

My first steps with Swift were asking hundreds of “How to do XXX in Swift” questions in Google, and I created my initial scripts and app structure and then converted my previously written scripts into Swift.

I also thought adding some vulnerability checks would be fine… but that’s another case...

You can find the GitHub repository:

Installation and Usage

Mergen is an open-source project, and you can download the latest release binary from the GitHub repository or build it yourself.

git clone https://github.com/sametsazak/mergen.git

Open the Mergen.xcworkspace file in Xcode.

Build and run the project in Xcode.

Feature checklist:

Mergen provides the following features to help you secure your Mac:

1. Check Gatekeeper Status
2. Check Secure Kernel Extension Loading
3. Guest Login Status Check
4. iCloud Drive Status Check
5. Check If SSH Is Enabled
6. Check Firewall Status
7. Check FileVault Status
8. Check All Apple-Provided Software Is Updated In Last 30 Days
9. Check Auto Update Is Enabled
10. Check 'Install Application Updates from the App Store' Is Enabled
11. Check Install Security Responses and System Files Is Enabled
12. Check 'Install system data files and security updates' Is Enabled
13. Check Firewall Stealth Mode Is Enabled
14. Check AirDrop Is Disabled
15. Check AirPlay Receiver Is Disabled
16. Check 'Set Time and Date Automatically' Is Enabled
17. Check Time Is Set Within Appropriate Limits
18. Check DVD or CD Sharing Is Disabled
19. Check Screen Sharing Is Disabled
20. Check File Sharing Is Disabled
21. Check Printer Sharing Is Disabled
22. Check Remote Login Is Disabled
23. Check Remote Management(ARDagent) Is Disabled
24. Check Remote Apple Events Is Disabled
25. Check Internet Sharing Is Disabled
26. Check Content Caching Is Disabled
27. Check Media Sharing Is Disabled
28. Check Bluetooth Sharing Is Disabled
29. Check Backup Automatically is Enabled If Time Machine Is Enabled
30. Check that Time Machine is Enabled
31. Check Time Machine Volumes Are Encrypted If Time Machine Is Enabled
32. Check Show Wi-Fi status in Menu Bar Is Enabled
33. Check Show Bluetooth Status in Menu Bar Is Enabled
34. Check Location Services Is Enabled
35. Check Location Services Is in the Menu Bar
36. Check Personalized Ads Status
37. Check Screen Saver Corners Are Secure
38. Check Universal Control is Disabled
39. Check Wake for Network Access is Disabled
40. Check an Inactivity Interval of 20 Minutes or Less for the Screen Saver Is Enabled
41. Check a Password is Required to Wake the Computer from Sleep or Screen Saver
42. Check Security Auditing Is Enabled
43. Check System Integrity Protection (SIP) Status
44. Check XProtect Status
45. Check Certificate Trust Settings
46. Check Siri Status
47. Check Sending Diagnostic and Usage Data to Apple Status
48. Check Java 6 Default Runtime Status
49. Check EFI Version is Valid and Regularly Checked
50. Check Bonjour Advertising Service Status
51. Check HTTP Server Status
52. Check NFS Server Status
53. Check 'Show Password Hints' Status
54. Check 'Allow guests to connect to shared folders' Status
55. Check Filename Extension Status
56. Check Automatic Run of Safe Files in Safari
57. Check Safari Disable Internet Plugins for Global Use
58. Check Fast User Switching Status

Challenges!

Developing this application was a fun but challenging experience. Here’s a rundown of the main problems I faced along the way:

Learning Swift and SwiftUI on the Fly
- As a Python-savvy guy, I had to learn Swift and SwiftUI while simultaneously developing Mergen. This learning curve was a unique challenge, as I had to familiarize myself with new programming languages. However, I overcame some problems and created a simple version of my idea.

No Admin Rights?
Mergen’s all about security, so it needed access to system settings and configs. But getting admin rights or using sudo in a macOS app wasn’t an option, which made some security checks a bit tricky. To work around this, I focused on checks that could run with just user rights, even if it meant sacrificing a few features.

Keeping the Code Simple and User-Friendly
To make Mergen as accessible as possible for users and contributors. This goal presented a challenge, as macOS has numerous versions, and not every module could be tested on each one. As a result, user feedback is vital for identifying and addressing any compatibility issues or limitations that may arise due to the differences in macOS versions. This feedback-driven approach allows Mergen to continuously improve and adapt to different environments.

How To Contribute?

I’m not an expert Swift developer, and I know the code might have some issues. Still, we welcome contributions from anyone interested in improving the security of MacOS.

If you are interested in contributing to the project, please follow these steps:

Fork the repository and clone it to your local machine.

Create a new branch for your changes.

Make your changes and write tests it.

Commit your changes and push them to your forked repository.

Open a pull request and describe your changes in detail.

If you’re interested in using Mergen, contributing to its development, or providing feedback, please visit the GitHub repository (https://github.com/sametsazak/mergen) and don’t hesitate to share your feedback and ideas for improvement.

--

--