diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 18a884b..a61a41c 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -2,18 +2,18 @@ This project uses a Gitflow-like organization for code: -* The `master` branch represents a stable version of the project at any given time. -* Releases are tags on the `master` branch. -* All features and bug fixes are performed against the `develop` branch. -* New features are allocated their own branch based on the `develop` branch, and pull requests are made from the new feature branch to the `develop` branch. +* The [`master`](https://github.com/kristovatlas/osx-config-check/tree/master) branch represents a stable version of the project at any given time. +* Releases are tags on the [`master`](https://github.com/kristovatlas/osx-config-check/tree/master) branch. +* All features and bug fixes are performed against the [`develop`](https://github.com/kristovatlas/osx-config-check/tree/develop) branch. +* New features are allocated their own branch based on the [`develop`](https://github.com/kristovatlas/osx-config-check/tree/develop) branch, and pull requests are made from the new feature branch to the [`develop`](https://github.com/kristovatlas/osx-config-check/tree/develop) branch. Developers who wish to submit a pull request should perform the following protocol: 1. Fork the project on GitHub -2. Create a special-purpose branch from the `develop` branch, e.g. 'fix-filevault' or 'disable-apple-mail' +2. Create a special-purpose branch from the [`develop`](https://github.com/kristovatlas/osx-config-check/tree/develop) branch, e.g. 'fix-filevault' or 'disable-apple-mail' 3. Implement the changes in the branch 4. Follow the guidelines in the sections below depending on whether you are modifying configuration checks, Python code, or any combination therefore -5. Make a pull request from your feature branch to the `develop` branch. +5. Make a pull request from your feature branch to the [`develop`](https://github.com/kristovatlas/osx-config-check/tree/develop) branch. ## Modifying default configuration checks @@ -42,3 +42,18 @@ To "install" this pre-commit hook, copy it to the `.git/hooks` directory contain ## Modifying Python files You SHOULD use `pylint` on any Python files you modify before submitting your modifications. Please attempt to avoid lowering the `pylint` score of these files. + +## Versioning + +The osx-config-check project aims to use [Semantic Versioning 2.0.0](http://semver.org/spec/v2.0.0.html). + +1. A major version number is incremented when an incompatible change is made either to the Hjson syntax for a config check or when an incompatible change is made to api.sh functions (e.g. a function is removed or its prototype modified). +2. A minor version number is incremented when a feature is added that is backwards-compatible, including: + * A new element is added to the Hjson syntax that is compatible with existing config checks + * A new function is added to api.sh +3. A patch version number is incremented when a bug is fixed in a backward-compatible way, including: + * Changes to bash commands + * Changes to the contents of scripts + * Typos in code or documentation + +New versions are produced by merging stable changes from the [`develop`](https://github.com/kristovatlas/osx-config-check/tree/develop) branch to the [`master`](https://github.com/kristovatlas/osx-config-check/tree/master) branch, and by tagging them as a new release. diff --git a/README.md b/README.md index ddd444c..9353ccf 100644 --- a/README.md +++ b/README.md @@ -31,137 +31,285 @@ Next run the app as follows: python app.py ``` -This will take you through a series of interactive steps that checks your machine's configuration, and offers to fix mixconfigurations for you. +This will take you through a series of interactive steps that checks your machine's configuration, and offers to fix misconfigurations for you. + +Intermediate users and advanced users can also invoke various command-line arguments: +``` +Usage: python app.py [OPTIONS] +OPTIONS: + --debug-print Enables verbose output for debugging the tool. + --report-only Only reports on compliance and does not offer to fix broken configurations. + --disable-logs Refrain from creating a log file with the results. + --disable-prompt Refrain from prompting user before applying fixes. + --skip-sudo-checks Do not perform checks that require sudo privileges. + --help -h Print this usage information. +``` ## Sample Output ```bash $ python app.py -CHECK #1: The System Preferences application is currently closed.... PASSED! -CHECK #2: Current user is a non-admin account. (Create a new account if this fails!)... PASSED! -CHECK #3: The OSX application firewall is enabled (system-wide).... PASSED! -CHECK #4: The OSX application firewall is enabled (current user only).... PASSED! -CHECK #5: A password is required to wake the computer from sleep or screen saver (system-wide).... PASSED! -CHECK #6: A password is required to wake the computer from sleep or screen saver (current user only).... PASSED! -CHECK #7: There is no delay between starting the screen saver and locking the machine (system-wide).... PASSED! -CHECK #8: There is no delay between starting the screen saver and locking the machine (current user only).... PASSED! -CHECK #9: Logging is enabled for the operating system.... PASSED! -CHECK #10: Homebrew analytics are disabled. (NOTE: Fix requires you to login/logout.)... PASSED! -CHECK #11: Stealth mode is enabled for OSX: Computer does not respond to ICMP ping requests or connection attempts from a closed TCP/UDP port. (system-wide)... PASSED! -CHECK #12: Stealth mode is enabled for OSX: Computer does not respond to ICMP ping requests or connection attempts from a closed TCP/UDP port. (current user only)... PASSED! -CHECK #13: Automatic whitelisting of Apple-signed applications for firewall is disabled (system-wide).... PASSED! -CHECK #14: Automatic whitelisting of Apple-signed applications for firewall is disabled (current user only).... PASSED! -CHECK #15: Captive portal for connecting to new networks is disabled to prevent MITM attacks.... PASSED! -CHECK #16: OpenSSL is up-to-date.... PASSED! -CHECK #17: Hidden files are displayed in Finder.... PASSED! -CHECK #18: All application software is currently up to date.... PASSED! -The next configuration check requires elevated privileges; you may be prompted for your current OS X user's password below. The command to be executed is: 'sudo softwareupdate --schedule | grep 'Automatic check is on'' -CHECK #19: Automatic check for software updates is enabled.... PASSED! -CHECK #20: GateKeeper protection against untrusted applications is enabled.... PASSED! -The next configuration check requires elevated privileges; you may be prompted for your current OS X user's password below. The command to be executed is: 'sudo defaults read /Library/Preferences/com.apple.Bluetooth ControllerPowerState' -CHECK #21: Bluetooth is disabled.... FAILED! - Apply the following EXPERIMENTAL fix? This will execute this command: - 'defaults write /Library/Preferences/com.apple.Bluetooth ControllerPowerState -bool false; killall -HUP blued' [y/N] -CHECK #22: The infrared receiver is disabled.... PASSED! -CHECK #23: AirDrop file sharing is disabled.... PASSED! -CHECK #24: File sharing is disabled.... PASSED! -CHECK #25: Printer sharing is disabled.... PASSED! -The next configuration check requires elevated privileges; you may be prompted for your current OS X user's password below. The command to be executed is: 'sudo systemsetup -getremotelogin' -CHECK #26: Remote login is disabled.... PASSED! -CHECK #27: Remote Management is disabled.... PASSED! -The next configuration check requires elevated privileges; you may be prompted for your current OS X user's password below. The command to be executed is: 'sudo systemsetup -getremoteappleevents' -CHECK #28: Remote Apple events are disabled.... PASSED! -CHECK #29: Internet Sharing is disabled on all network interfaces.... PASSED! -The next configuration check requires elevated privileges; you may be prompted for your current OS X user's password below. The command to be executed is: 'sudo systemsetup getwakeonnetworkaccess' -CHECK #30: Wake on Network Access feature is disabled.... PASSED! -The next configuration check requires elevated privileges; you may be prompted for your current OS X user's password below. The command to be executed is: 'sudo systemsetup getusingnetworktime' -CHECK #31: Automatic setting of time and date is disabled.... PASSED! -CHECK #32: IPv6 is disabled on all network interfaces.... PASSED! -CHECK #33: An administrator password is required to change system-wide preferences.... PASSED! -CHECK #34: Documents are not stored to iCloud Drive by default. (May be mistaken if iCloud is disabled)... PASSED! -CHECK #35: The File Vault key is destroyed when going to standby mode.... PASSED! -CHECK #36: The system will store a copy of memory to persistent storage, and will remove power to memory.... PASSED! -CHECK #37: git is up to date or is not installed... PASSED! -CHECK #38: Apple Push Notifications are disabled.... PASSED! -CHECK #39: Google DNS servers are used by default on all network interfaces.... PASSED! -CHECK #40: The curl utility is up to date or absent from the system.... PASSED! -CHECK #41: FileVault file system encryption is enabled.... PASSED! -CHECK #42: FileVault file system encryption is enabled at the root directory.... PASSED! -CHECK #43: The idle timer for screen saver activation is set to 10 minutes or less.... PASSED! -CHECK #44: The Safari application is currently closed.... PASSED! -CHECK #45: Safari will not auto-fill credit card data.... PASSED! -CHECK #46: Safari will not auto-fill your contact data.... PASSED! -CHECK #47: Safari will not auto-fill miscellaneous forms.... PASSED! -CHECK #48: Safari will not auto-fill usernames or passwords.... PASSED! -CHECK #49: Files downloaded in Safari are not automatically opened.... PASSED! -CHECK #50: Cookies and local storage are always blocked in Safari.... PASSED! -CHECK #51: Safari extensions are disabled.... PASSED! -CHECK #52: The Safari web browser will warn when visiting known fraudulent websites.... PASSED! -CHECK #53: JavaScript disabled in the Safari web browser.... PASSED! -CHECK #54: JavaScript disabled in the Safari web browser (Legacy version).... PASSED! -CHECK #55: Pop-up windows are blocked in the Safari web browser.... PASSED! -CHECK #56: Pop-up windows are blocked in the Safari web browser (Legacy version).... PASSED! -CHECK #57: The WebGL plug-in is disabled in the Safari web browser.... PASSED! -CHECK #58: Plug-ins are disabled in the Safari web browser.... PASSED! -CHECK #59: Plug-ins are disabled in the Safari web browser (Legacy version).... PASSED! -CHECK #60: Plug-ins are blocked by default in the Safari web browser unless a site is explicitly added to a list of allowed sites.... PASSED! -CHECK #61: The Java plug-in for Safari web browser is blocked unless a site is explicitly added to a list of allowed sites.... PASSED! -CHECK #62: The Java plug-in is disabled in the Safari web browser.... PASSED! -CHECK #63: The Java plug-in is disabled in the Safari web browser (Legacy version).... PASSED! -CHECK #64: The Safari web browser is configured to treat SHA-1 certificates as insecure.... PASSED! -CHECK #65: The Safari web browser will not pre-load webpages that rank highly as search matches.... PASSED! -CHECK #66: The Safari web browser will not include search engine suggestions for text typed in the location bar.... PASSED! -CHECK #67: The Safari web browser's search suggestions are disabled.... PASSED! -CHECK #68: The Safari web browser uses the Do-Not-Track HTTP header.... PASSED! -CHECK #69: PDF viewing is disabled in the Safari web browser.... PASSED! -CHECK #70: Full website addresses are disabled in the location bar of the Safari web browser.... PASSED! -CHECK #71: The Mail application is currently closed.... PASSED! -CHECK #72: Apple Mail does not automatically load remote content in e-mails.... PASSED! -CHECK #73: Mail identified by Apple Mail as junk is sent to the Junk mailbox.... PASSED! -CHECK #74: New e-mails composed in Apple Mail are encrypted by GPGMail if the receiver's PGP is present in the keychain.... PASSED! -CHECK #75: New e-mails composed in Apple Mail and saved as drafts are encrypted by GPGMail.... PASSED! -CHECK #76: New e-mails composed in Apple Mail are signed by GPGMail.... PASSED! -CHECK #77: Apple Mail with automatically check for updates to GPGMail.... PASSED! -CHECK #78: The Google Chrome browser is currently closed.... PASSED! -CHECK #79: All Google Chrome web browser profiles prevent information leakage through navigation errors.... PASSED! -CHECK #80: All Google Chrome web browser profiles prevent information leakage through URL suggestions.... PASSED! -CHECK #81: All Google Chrome web browser profiles prevent information leakage through network prediction.... PASSED! -CHECK #82: All Google Chrome web browser profiles prevent information leakage through report security incidents to Google.... PASSED! -CHECK #83: All Google Chrome web browser profiles have Google Safe Browsing enabled.... PASSED! -CHECK #84: All Google Chrome web browser profiles prevent information leakage through spell-checking network services.... PASSED! -CHECK #85: All Google Chrome web browser profiles prevent information leakage through reporting usage statistics to Google.... PASSED! -CHECK #86: All Google Chrome web browser profiles use the Do-Not-Track HTTP header.... PASSED! -CHECK #87: All Google Chrome web browser profiles prevent pop-ups.... PASSED! -CHECK #88: All Google Chrome web browser profiles prevent geolocation by websites.... PASSED! -CHECK #89: All Google Chrome web browser profiles block unsandboxed plug-in software.... PASSED! -CHECK #90: All Google Chrome web browser profiles prevent filling personal information into forms automatically.... PASSED! -CHECK #91: All Google Chrome web browser profiles have disabled Password Manager.... PASSED! -CHECK #92: All Google Chrome web browser profiles have disabled automatic sign-in for stored passwords.... PASSED! -CHECK #93: All Google Chrome web browser profiles have disabled Google CloudPrint.... PASSED! -CHECK #94: All Google Chrome web browser profiles have disabled Flash cookies.... PASSED! -CHECK #95: All Google Chrome web browser profiles have disabled the Chrome Pepper Flash Player plug-in.... PASSED! -CHECK #96: All Google Chrome web browser profiles have disabled the Adobe Shockwave Flash plug-in.... PASSED! -CHECK #97: All Google Chrome web browser profiles have disabled the Adobe Flash Player plug-in.... PASSED! -CHECK #98: All Google Chrome web browser profiles have disabled the Native Client plug-in.... PASSED! -CHECK #99: All Google Chrome web browser profiles have disabled the Widevine Content Decryption Module plug-in.... PASSED! -CHECK #100: All Google Chrome web browser profiles have enabled the uBlock Origin extension.... PASSED! -CHECK #100: All Google Chrome web browser profiles have enabled the uBlock Origin extension.... PASSED! -CHECK #101: All Google Chrome web browser profiles have enabled the Ghostery extension.... PASSED! -CHECK #102: All Google Chrome web browser profiles have enabled the ScriptSafe extension.... PASSED! -CHECK #103: Google Chrome is the default web browser.... PASSED! -Wrote results to '~/Documents/osx-config-check_2016-07-08_17-43-50.log'. +------------------------------------------------------------------------------------------ +osx-config-check v1.0.0-alpha (pidgeotto) +Download the latest copy of this tool at: https://github.com/kristovatlas/osx-config-check +Report bugs/issues: + * GitHub: https://github.com/kristovatlas/osx-config-check/issues + * Twitter: https://twitter.com/kristovatlas +------------------------------------------------------------------------------------------ + + +CHECK #1: Homebrew is installed.... PASSED! + +CHECK #2: Binaries installed to /usr/local/bin are preferred over those in /usr/bin (Note: If this check does not pass, other tests will fail)... PASSED! + +CHECK #3: Java Runtime Environment is up to date.... PASSED! + +CHECK #4: The System Preferences application is currently closed.... PASSED! + +CHECK #5: Current user is a non-admin account.... PASSED! + +CHECK #6: The OSX application firewall is enabled (system-wide).... PASSED! + +CHECK #7: The OSX application firewall is enabled (current user only).... PASSED! + +CHECK #8: A password is required to wake the computer from sleep or screen saver (system-wide).... PASSED! + +CHECK #9: A password is required to wake the computer from sleep or screen saver (current user only).... PASSED! + +CHECK #10: There is no delay between starting the screen saver and locking the machine (system-wide).... PASSED! + +CHECK #11: There is no delay between starting the screen saver and locking the machine (current user only).... PASSED! + +CHECK #12: Logging is enabled for the operating system.... PASSED! + +CHECK #13: Homebrew analytics are disabled.... PASSED! + +CHECK #14: Stealth mode is enabled for OSX: Computer does not respond to ICMP ping requests or connection attempts from a closed TCP/UDP port. (system-wide)... PASSED! + +CHECK #15: Stealth mode is enabled for OSX: Computer does not respond to ICMP ping requests or connection attempts from a closed TCP/UDP port. (current user only)... PASSED! + +CHECK #16: Automatic whitelisting of Apple-signed applications through the firewall is disabled (system-wide).... FAILED! + Apply the following fix? This will execute this command: + 'defaults -currentHost write /Library/Preferences/com.apple.alf allowsignedenabled -bool false' [Y/n] y + Attempting configuration fix with elevated privileges; you may be prompted for your OS X login password... +Password: + +CHECK #16: Automatic whitelisting of Apple-signed applications through the firewall is disabled (system-wide).... PASSED! + +CHECK #17: Automatic whitelisting of Apple-signed applications through the firewall is disabled (current user only).... PASSED! + +CHECK #18: Captive portal for connecting to new networks is disabled to prevent MITM attacks.... PASSED! + +CHECK #19: OpenSSL is up to date.... PASSED! + +CHECK #20: Hidden files are displayed in Finder.... PASSED! + +CHECK #21: All application software is currently up to date.... PASSED! +The next configuration check requires elevated privileges; you may be prompted for your current OS X user's password below. The command to be executed is: 'sudo softwareupdate --schedule | grep -i 'Automatic check is on'' + +CHECK #22: Automatic check for software updates is enabled.... PASSED! + +CHECK #23: GateKeeper protection against untrusted applications is enabled.... PASSED! + +CHECK #24: Bluetooth is disabled.... FAILED! + Apply the following EXPERIMENTAL fix? This will execute this command: + 'defaults write /Library/Preferences/com.apple.Bluetooth ControllerPowerState -bool false; killall -HUP blued' [y/N] n + +CHECK #25: The infrared receiver is disabled.... PASSED! + +CHECK #26: AirDrop file sharing is disabled.... PASSED! + +CHECK #27: File sharing is disabled.... PASSED! + +CHECK #28: Printer sharing is disabled.... PASSED! +The next configuration check requires elevated privileges; you may be prompted for your current OS X user's password below. The command to be executed is: 'sudo systemsetup -getremotelogin' + +CHECK #29: Remote login is disabled.... PASSED! + +CHECK #30: Remote Management is disabled.... PASSED! +The next configuration check requires elevated privileges; you may be prompted for your current OS X user's password below. The command to be executed is: 'sudo systemsetup -getremoteappleevents' + +CHECK #31: Remote Apple events are disabled.... PASSED! + +CHECK #32: Internet Sharing is disabled on all network interfaces.... PASSED! +The next configuration check requires elevated privileges; you may be prompted for your current OS X user's password below. The command to be executed is: 'sudo systemsetup getwakeonnetworkaccess' + +CHECK #33: Wake on Network Access feature is disabled.... PASSED! +The next configuration check requires elevated privileges; you may be prompted for your current OS X user's password below. The command to be executed is: 'sudo systemsetup getusingnetworktime' + +CHECK #34: Automatic setting of time and date is disabled.... PASSED! + +CHECK #35: IPv6 is disabled on all network interfaces.... PASSED! + +CHECK #36: An administrator password is required to change system-wide preferences.... PASSED! + +CHECK #37: Documents are not stored to iCloud Drive by default. (May be mistaken if iCloud is disabled)... PASSED! + +CHECK #38: The File Vault key is protected when going to standby mode.... PASSED! + +CHECK #39: The system will store a copy of memory to persistent storage, and will remove power to memory.... PASSED! + +CHECK #40: git is up to date or is not installed... PASSED! + +CHECK #41: Apple Push Notifications are disabled.... PASSED! + +CHECK #42: Google DNS servers are used by default on all network interfaces.... PASSED! + +CHECK #43: The curl utility is up to date or absent from the system.... PASSED! + +CHECK #44: FileVault file system encryption is enabled.... PASSED! + +CHECK #45: FileVault file system encryption is enabled at the root directory.... PASSED! + +CHECK #46: The idle timer for screen saver activation is set to 10 minutes or less.... PASSED! + +CHECK #47: System Integrity Protection (SIP) is enabled.... PASSED! + +CHECK #48: The Safari application is currently closed.... PASSED! + +CHECK #49: Safari will not auto-fill credit card data.... PASSED! + +CHECK #50: Safari will not auto-fill your contact data.... PASSED! + +CHECK #51: Safari will not auto-fill miscellaneous forms.... PASSED! + +CHECK #52: Safari will not auto-fill usernames or passwords.... PASSED! + +CHECK #53: Files downloaded in Safari are not automatically opened.... PASSED! + +CHECK #54: Cookies and local storage are always blocked in Safari.... PASSED! + +CHECK #55: Safari extensions are disabled.... PASSED! + +CHECK #56: The Safari web browser will warn when visiting known fraudulent websites.... PASSED! + +CHECK #57: JavaScript is disabled in the Safari web browser.... PASSED! + +CHECK #58: JavaScript is disabled in the Safari web browser (Legacy version).... PASSED! + +CHECK #59: Pop-up windows are blocked in the Safari web browser.... PASSED! + +CHECK #60: Pop-up windows are blocked in the Safari web browser (Legacy version).... PASSED! + +CHECK #61: The WebGL plug-in is disabled in the Safari web browser.... PASSED! + +CHECK #62: Plug-ins are disabled in the Safari web browser.... PASSED! + +CHECK #63: Plug-ins are disabled in the Safari web browser (Legacy version).... PASSED! + +CHECK #64: Plug-ins are blocked by default in the Safari web browser unless a site is explicitly added to a list of allowed sites.... PASSED! + +CHECK #65: The Java plug-in for Safari web browser is blocked unless a site is explicitly added to a list of allowed sites.... PASSED! + +CHECK #66: The Java plug-in is disabled in the Safari web browser.... PASSED! + +CHECK #67: The Java plug-in is disabled in the Safari web browser (Legacy version).... PASSED! + +CHECK #68: The Safari web browser is configured to treat SHA-1 certificates as insecure.... PASSED! + +CHECK #69: The Safari web browser will not pre-load webpages that rank highly as search matches.... PASSED! + +CHECK #70: The Safari web browser will not include search engine suggestions for text typed in the location bar.... PASSED! + +CHECK #71: The Safari web browser's search suggestions are disabled.... PASSED! + +CHECK #72: The Safari web browser uses the Do-Not-Track HTTP header.... PASSED! + +CHECK #73: PDF viewing is disabled in the Safari web browser.... PASSED! + +CHECK #74: Full website addresses are displayed in the location bar of the Safari web browser.... PASSED! + +CHECK #75: The Mail application is currently closed.... PASSED! + +CHECK #76: Apple Mail does not automatically load remote content in e-mails.... PASSED! + +CHECK #77: Mail identified by Apple Mail as junk is sent to the Junk mailbox.... PASSED! + +CHECK #78: GPGMail is in use.... PASSED! + +CHECK #79: New e-mails composed in Apple Mail are encrypted by GPGMail if the receiver's PGP is present in the keychain.... PASSED! + +CHECK #80: New e-mails composed in Apple Mail and saved as drafts are encrypted by GPGMail.... PASSED! + +CHECK #81: New e-mails composed in Apple Mail are signed by GPGMail.... PASSED! + +CHECK #82: Apple Mail automatically checks for updates to GPGMail.... PASSED! + +CHECK #83: The Google Chrome browser is currently closed.... FAILED! + Apply the following fix? This will execute this command: + 'killall "Google Chrome" ; sleep 3' [Y/n] y + +CHECK #83: The Google Chrome browser is currently closed.... PASSED! + +CHECK #84: All Google Chrome web browser profiles prevent information leakage through navigation errors.... PASSED! + +CHECK #85: All Google Chrome web browser profiles prevent information leakage through URL suggestions.... PASSED! + +CHECK #86: All Google Chrome web browser profiles prevent information leakage through network prediction.... PASSED! + +CHECK #87: All Google Chrome web browser profiles prevent information leakage by blocking security incidents reports to Google.... PASSED! + +CHECK #88: All Google Chrome web browser profiles have Google Safe Browsing enabled.... PASSED! + +CHECK #89: All Google Chrome web browser profiles prevent information leakage through spell-checking network services.... PASSED! + +CHECK #90: All Google Chrome web browser profiles prevent information leakage through reporting usage statistics to Google.... PASSED! + +CHECK #91: All Google Chrome web browser profiles use the Do-Not-Track HTTP header.... PASSED! + +CHECK #92: All Google Chrome web browser profiles prevent pop-ups.... PASSED! + +CHECK #93: All Google Chrome web browser profiles prevent geolocation by websites.... PASSED! + +CHECK #94: All Google Chrome web browser profiles block unsandboxed plug-in software.... PASSED! + +CHECK #95: All Google Chrome web browser profiles prevent filling personal information into forms automatically.... PASSED! + +CHECK #96: All Google Chrome web browser profiles have disabled Password Manager.... PASSED! + +CHECK #97: All Google Chrome web browser profiles have disabled automatic sign-in for stored passwords.... PASSED! + +CHECK #98: All Google Chrome web browser profiles have disabled Google CloudPrint.... PASSED! + +CHECK #99: All Google Chrome web browser profiles block Flash cookies.... PASSED! + +CHECK #100: All Google Chrome web browser profiles have disabled the Chrome Pepper Flash Player plug-in.... PASSED! + +CHECK #101: All Google Chrome web browser profiles have disabled the Adobe Shockwave Flash plug-in.... PASSED! + +CHECK #102: All Google Chrome web browser profiles have disabled the Adobe Flash Player plug-in.... PASSED! + +CHECK #103: All Google Chrome web browser profiles have disabled the Native Client plug-in.... PASSED! + +CHECK #104: All Google Chrome web browser profiles have disabled the Widevine Content Decryption Module plug-in.... PASSED! + +CHECK #105: All Google Chrome web browser profiles have enabled the uBlock Origin extension.... FAILED! + +CHECK #106: All Google Chrome web browser profiles have enabled the Ghostery extension.... FAILED! + +CHECK #107: All Google Chrome web browser profiles have enabled the ScriptSafe extension.... FAILED! + +CHECK #108: Google Chrome is the default web browser.... PASSED! + +CHECK #109: OSX/Keydnap malware is not present.... PASSED! +Wrote results to '~/Documents/osx-config-check_2016-09-01_17-09-36.log'. ========================== -2 tests could not be automatically fixed, but manual instructions are available. Please manually remediate these problems and re-run the tool: -TEST #100: All Google Chrome web browser profiles have enabled the uBlock Origin extension. +3 tests could not be automatically fixed, but manual instructions are available. Please manually remediate these problems and re-run the tool: +TEST #105: All Google Chrome web browser profiles have enabled the uBlock Origin extension. 1. For each of your Chrome profiles, visit https://chrome.google.com/webstore/detail/ublock-origin/cjpalhdlnbpafiamejdnhcphjbkeiagm in Google Chrome. 2. Select "Add to Chrome". 3. Complete any required follow-up steps as instructed on the screen. ========================== -TEST #101: All Google Chrome web browser profiles have enabled the Ghostery extension. +TEST #106: All Google Chrome web browser profiles have enabled the Ghostery extension. 1. For each of your Chrome profiles, visit https://chrome.google.com/webstore/detail/ghostery/mlomiejdfkolichcflejclcbmpeaniij in Google Chrome. 2. Select "Add to Chrome". 3. Complete any required follow-up steps as instructed on the screen. ========================== +TEST #107: All Google Chrome web browser profiles have enabled the ScriptSafe extension. +1. For each of your Chrome profiles, visit https://chrome.google.com/webstore/detail/scriptsafe/oiigbmnaadbkfbmpbfijlflahbdbdgdf in Google Chrome. +2. Select "Add to Chrome". +3. Complete any required follow-up steps as instructed on the screen. +========================== ``` ## Troubleshooting @@ -170,6 +318,14 @@ TEST #101: All Google Chrome web browser profiles have enabled the Ghostery exte If you receive an error message referencing these terms, the user you are currently logged in as may not be permitted to temporarily assume elevated privileges, preventing this tool from fully auditing and/or fixing your user's configuration. If you have added a non-Administrator user to your machine to help secure it, you will find that your non-Administrator user is not part of the "sudoers" list by default. To learn about how to add your user to the "sudoers" list, please [refer to this link](http://osxdaily.com/2014/02/06/add-user-sudoers-file-mac/). +### Trouble Connecting to Wi-Fi + +This tool encourages users to use DNS servers run by the Google corporation. This can break some wi-fi networks that use "active portals" to login, like those found at cafes, airports, etc. If you're having trouble connecting to a wi-fi network after using this tool, please use the "dns_helper" tool included. From the terminal application, run: + + bash dns_helper.sh + +And follow the instructions on the screen carefully. + ## Contributing Please read [CONTRIBUTING.md](CONTRIBUTING.md) before submitting pull requests to the repository. diff --git a/app.py b/app.py index 9bea7ca..84d4f6d 100644 --- a/app.py +++ b/app.py @@ -1,10 +1,10 @@ #!/usr/bin/env python """Checks the configuration of various osx options.""" +import sys import time import datetime from os.path import expanduser -import sys import re from subprocess import Popen, PIPE, STDOUT from warnings import warn @@ -12,16 +12,17 @@ import const #const.py import prompt #prompt.py -const.ENABLE_DEBUG_PRINT = False const.DEFAULT_OUTPUT_LOCATION = "~/Documents/" -const.WRITE_TO_LOG_FILE = True #TODO: Allow user to pass command line arg const.DEFAULT_CONFIG_FILE = "osx-config.json" -const.PROMPT_FOR_FIXES = True #TODO: allow user to pass command line arg const.WARN_FOR_RECOMMENDED = True #TODO: command line flag const.WARN_FOR_EXPERIMENTAL = True #TODO: command line flag const.FIX_RECOMMENDED_BY_DEFAULT = True #TODO: command line flag const.FIX_EXPERIMENTAL_BY_DEFAULT = False #TODO: command line flag +const.VERSION = "v1.0.0-alpha (pidgeotto)" + +const.API_FILENAME = './scripts/api.sh' + const.COLORS = { 'HEADER': '\033[95m', 'OKBLUE': '\033[94m', @@ -36,6 +37,7 @@ const.PASSED_STR = const.COLORS['OKGREEN'] + "PASSED!" + const.COLORS['ENDC'] const.FAILED_STR = const.COLORS['FAIL'] + "FAILED!" + const.COLORS['ENDC'] +const.SKIPPED_STR = const.COLORS['OKBLUE'] + "SKIPPED!" + const.COLORS['ENDC'] const.NO_SUDO_STR = ("%s%s%s" % (const.COLORS['WARNING'], ("Insufficient privileges to perform this check. " @@ -48,6 +50,10 @@ 'EXPERIMENTAL', const.COLORS['ENDC'])) +const.SUDO_STR = ("%s%ssudo%s" % + (const.COLORS['BOLD'], const.COLORS['RED'], + const.COLORS['ENDC'])) + def get_timestamp(): """Genereate a current timestamp that won't break a filename.""" timestamp_format = '%Y-%m-%d_%H-%M-%S' @@ -59,6 +65,26 @@ def get_timestamp(): glob_check_num = 1 +class CheckResult(object): + """Each test can have one of three results, informing the next step.""" + explicit_pass = 1 + explicit_fail = 2 + no_pass = 3 + all_skipped = 4 + +def check_result_to_str(val): + """Convert enum to string representation""" + if val == CheckResult.explicit_pass: + return const.PASSED_STR + elif val == CheckResult.explicit_fail: + return const.FAILED_STR + elif val == CheckResult.no_pass: + return const.FAILED_STR + elif val == CheckResult.all_skipped: + return const.SKIPPED_STR + else: + raise ValueError + class Confidence(object): """Likelihood that a configuration will create negative side-effects. @@ -71,21 +97,19 @@ class Confidence(object): class ConfigCheck(object): """Encapsulates configuration to check in operating system.""" - check_type = '' - expected_stdout = '' - - def __init__(self, command, comparison_type, expected, case_sensitive, - description, confidence, fix=None, sudo_fix=None, - manual_fix=None, sudo_command=None): + def __init__(self, tests, description, confidence, fix=None, sudo_fix=None, + manual_fix=None): """ Args: - command (str): The command to run to check OS configuration. - comparison_type (str): "exact match" or "regex match" - expected (str): The expected string to match or regex to match - against the stdout of the specified `command`. - case_senstive (bool): Specifies whether `expected` is a - case-sensitive comparison. + tests (List[dict]): The ordered list of tests to be performed, each + a `dict` with these attributes including command_pass and/or + command_fail: + * type (str): "exact match" or "regex match" + * command (str) + * command_pass (Optional[str]) + * command_fail (Optional[str]) + * case_sensitive (bool) description (str): A human-readable description of the configuration being checked. confidence (str): "required", "recommended", or "experimental" @@ -97,16 +121,17 @@ def __init__(self, command, comparison_type, expected, case_sensitive, change. manual_fix (Optional[str]): Instructions to output to the user to manually remediate if a config cannot be fixed automatically. - sudo_command (Optional[str]): A version of `command` that - requests administrative privileges from the operating system. - This will only be executed if `command` does not produce the - desired results. """ - assert comparison_type in ('exact match', 'regex match') - self.command = command - self.comparison_type = comparison_type - self.expected = expected - self.case_sensitive = case_sensitive + assert isinstance(tests, list) + assert len(tests) > 0 + for test in tests: + assert isinstance(test, dict), "%s" % str(test) + assert test['type'] in ('exact match', 'regex match') + assert 'command' in test + assert 'command_pass' in test or 'command_fail' in test + test['case_sensitive'] = bool(test['case_sensitive']) + self.tests = tests + self.description = description if confidence == 'required': self.confidence = Confidence.required @@ -121,7 +146,6 @@ def __init__(self, command, comparison_type, expected, case_sensitive, self.fix = fix #default: None self.sudo_fix = sudo_fix #default: None self.manual_fix = manual_fix #default: None - self.sudo_command = sudo_command #default: None def __str__(self): return str(self.__dict__) @@ -147,28 +171,6 @@ def read_config(config_filename): if '_comment' in config_check: continue - #Config MUST specify a command to check the status of the system - command = config_check['command'] - - #Config MUST specify either expected STDOUT or regex pattern - expected = None - comparison_type = None - if config_check['type'] == 'exact match': - comparison_type = 'exact match' - expected = config_check['expected_stdout'] - elif config_check['type'] == 'regex match': - comparison_type = 'regex match' - expected = config_check['expected_regex'] - else: - sys.exit("Expected comparison string does not match 'type' field.") - - #Config MUST specify whether the commands checking the status are case - #sensitive - case_sensitive = False - assert config_check['case_sensitive'] in ('true', True, 'false', False) - if config_check['case_sensitive'] in ('true', True): - case_sensitive = True - #Config MUST specify a description of the check description = config_check['description'] dprint("Description: %s" % description) @@ -176,6 +178,9 @@ def read_config(config_filename): #Config MUST indicate the confidence of the configuration check confidence = config_check['confidence'] + #Config MUST include at least one test obj + tests = config_check['tests'] + #Config MUST specify a fix object assert 'fix' in config_check assert isinstance(config_check['fix'], dict) @@ -195,22 +200,13 @@ def read_config(config_filename): if 'manual' in config_check['fix']: manual_fix = config_check['fix']['manual'] - #Config MAY specify a sudo_command, a sudo version of "command" - sudo_command = None - if 'sudo_command' in config_check: - sudo_command = config_check['sudo_command'] - config_check_obj = ConfigCheck( - command=command, - comparison_type=comparison_type, - expected=expected, - case_sensitive=case_sensitive, + tests=tests, description=description, confidence=confidence, fix=fix, sudo_fix=sudo_fix, - manual_fix=manual_fix, - sudo_command=sudo_command) + manual_fix=manual_fix) config_checks.append(config_check_obj) return config_checks @@ -218,53 +214,86 @@ def read_config(config_filename): def run_check(config_check, last_attempt=False, quiet_fail=False): """Perform the specified configuration check against the OS. - This will perform the check once without sudo privileges; if that fails and - a sudo version of this check has been specified, that will be performed, - with the final result value being a logical-or of the outcomes. + Each config check may specify multiple test cases with early-succeed and/or + early-fail parameters. + + These are the possible conditions resulting from run_check: + 1. One of the tests explicitly passed. + 2. One of the tests explicitly failed. + 3. All of the tests were run and none of them passed or failed. (This + should be considered a fail.) + 4. All of the tests were skipped because we're skipping sudo checks and + the only tests available require sudo privs. Args: - config_check (`ConfigCheck`): The check to perform. + config_check (`ConfigCheck`): The check to perform. May contain multiple + commands to test. last_attempt (bool): Is this the last time the script checks this configuration, or will we check again during this run? quiet_fail (bool): Suppress print failed results to stdout? Default: False. - Returns: - bool: Whether check passed. + Returns: `CheckResult`: The check explicitly passed, explicitly + failed, never passed, or all checks were skipped. + + Raises: ValueError if result of _execute_check is not valid. """ assert isinstance(config_check, ConfigCheck) - passed = _execute_check(config_check.command, config_check.comparison_type, - config_check.expected, config_check.case_sensitive) - - if not passed and config_check.sudo_command is not None: - fancy_sudo_command = re.sub("sudo", - ("%s%ssudo%s" % (const.COLORS['BOLD'], - const.COLORS['RED'], - const.COLORS['ENDC'])), - config_check.sudo_command) - print(("The next configuration check requires elevated privileges; %s" - "you may be prompted for your current OS X user's password " - "below%s. The command to be executed is: '%s'") % - (const.COLORS['BOLD'], const.COLORS['ENDC'], - fancy_sudo_command)) - passed = _execute_check(config_check.sudo_command, - config_check.comparison_type, - config_check.expected, - config_check.case_sensitive) - - if passed or not quiet_fail: + #Assume all tests have been skipped until demonstrated otherwise. + result = CheckResult.all_skipped + for test in config_check.tests: + #alert user if he might get prompted for admin privs due to sudo use + if 'sudo ' in test['command']: + if const.SKIP_SUDO_TESTS: + dprint("Skipping test because app skipping sudo tests.") + else: + fancy_sudo_command = re.sub( + "sudo", const.SUDO_STR, test['command']) + print(("The next configuration check requires elevated " + "privileges; %syou may be prompted for your current OS " + "X user's password below%s. The command to be executed " + "is: '%s'") % + (const.COLORS['BOLD'], const.COLORS['ENDC'], + fancy_sudo_command)) + + if 'sudo ' not in test['command'] or not const.SKIP_SUDO_TESTS: + command_pass = None + if 'command_pass' in test: + command_pass = str(test['command_pass']) + command_fail = None + if 'command_fail' in test: + command_fail = str(test['command_fail']) + result = _execute_check(command=test['command'], + comparison_type=test['type'], + case_sensitive=test['case_sensitive'], + command_pass=command_pass, + command_fail=command_fail) + if result == CheckResult.explicit_pass: + dprint("Test passed exlicitly for '%s'" % test['command']) + break + elif result == CheckResult.explicit_fail: + dprint("Test failed exlicitly for '%s'" % test['command']) + break + elif result == CheckResult.no_pass: + dprint("Test did not pass for '%s'" % test['command']) + continue + else: + raise ValueError("Invalid return value from _execute_check.") + + if result == CheckResult.explicit_pass or not quiet_fail: msg = ("\nCHECK #%d: %s... %s" % (glob_check_num, - config_check.description, - _get_result_str(passed))) + config_check.description, + check_result_to_str(result))) print msg if const.WRITE_TO_LOG_FILE: log_to_file(msg) - if not passed and last_attempt and do_warn(config_check): + if (result not in (CheckResult.explicit_pass, CheckResult.all_skipped) and + last_attempt and do_warn(config_check)): warn("Attempted fix %s" % const.FAILED_STR) - return passed + return result def log_to_file(string): """Append string, followed by newline character, to log file. @@ -279,23 +308,39 @@ def log_to_file(string): with open(log_file_loc, 'a+') as log_file: log_file.write("%s\n" % string) -def _get_result_str(result_bool): - return const.PASSED_STR if result_bool else const.FAILED_STR - -def _execute_check(command, comparison_type, expected, case_sensitive): +def _execute_check(command, comparison_type, case_sensitive, command_pass=None, + command_fail=None): """Helper function for `run_check` -- executes command and checks result. + This check can result in three conditions: + 1. The check explicitly passed, and no subsequent tests need to be performed + for this check. Returns True. + 2. The check explicitly failed, and no subsequent tests need to be performed + for this check. Raises ConfigCheckFailedExplicitly. + 3. The check produced another result, and if there is another test + available, it + Args: command (str): The command to execute to perform the check. comparison_type (str): 'exact match' or 'regex match' - expected (str): Result expected in output, either exact match or regex. case_sensitive (bool): Whether the comparison to output is case - senstive. + sensitive. + command_pass (str or None): The output of the command which constitutes + an explicit pass for the test, either as an exact string or regex + depending on `comparison_type`. + command_fail (str or None): The output of the command which constitutes + an explicit fail for the test, either as an exact string or regex + depending on `comparison_type`. Returns: - bool: Whether the output matched the expected output of the command. + `CheckResult`: explicit pass, explicit failure, or lacking of passing for + this test only. + + Raises: + ValueError if `comparison_type` is not an expected value """ #http://stackoverflow.com/questions/7129107/python-how-to-suppress-the-output-of-os-system + command = "source %s ; %s" % (const.API_FILENAME, command) process = Popen(command, stdout=PIPE, stderr=STDOUT, shell=True) stdout, _ = process.communicate() @@ -303,15 +348,36 @@ def _execute_check(command, comparison_type, expected, case_sensitive): dprint("Command executed to check config: '%s'" % str(command)) dprint("Result of command: '%s'" % str(stdout)) - dprint("Expected this result: '%s'" % str(expected)) + dprint("Explicit pass condition for command: '%s'" % str(command_pass)) + dprint("Explicit fail condition for command: '%s'" % str(command_fail)) if comparison_type == 'exact match': if case_sensitive: - return stdout == expected + if command_fail is not None and stdout == command_fail: + return CheckResult.explicit_fail + if command_pass is not None and stdout == command_pass: + return CheckResult.explicit_pass + else: + return CheckResult.no_pass else: - return stdout.lower() == str(expected).lower() + if (command_fail is not None and + stdout.lower() == str(command_fail.lower())): + return CheckResult.explicit_fail + if (command_pass is not None and + stdout.lower() == str(command_pass).lower()): + return CheckResult.explicit_pass + else: + return CheckResult.no_pass elif comparison_type == 'regex match': - return is_match(expected, stdout, ignore_case=(not case_sensitive)) + ignore_case = not case_sensitive + if (command_fail is not None and + is_match(command_fail, stdout, ignore_case=ignore_case)): + return CheckResult.explicit_fail + if (command_pass is not None and + is_match(command_pass, stdout, ignore_case=ignore_case)): + return CheckResult.explicit_pass + else: + return CheckResult.no_pass else: raise ValueError @@ -341,14 +407,26 @@ def _try_fix(config_check, use_sudo=False): print(("\tAttempting configuration fix with elevated privileges; %syou " "may be prompted for your OS X login password%s...") % (const.COLORS['BOLD'], const.COLORS['ENDC'])) + stdoutdata = "" + stderrdata = "" if command is not None: + command = "source %s ; %s" % (const.API_FILENAME, command) process = Popen(command, stdout=PIPE, stderr=STDOUT, shell=True) - process.communicate() + stdoutdata, stderrdata = process.communicate() dprint("Command executed: '%s'" % str(command)) + dprint("Command STDOUT: '%s'" % str(stdoutdata)) + dprint("Command STDERR: '%s'" % str(stderrdata)) def do_fix_and_test(config_check): - """Attempt to fix misconfiguration w/ and w/o sudo privs, returning result. + """Attempt to fix misconfiguration, returning the result. + + If a non-sudo fix is specified, this will be attempted first. + If a non-sudo fix fails or there is none specified and a sudo fix is + specified, this will be attempted next. + If all previous attempts have failed or none have been specified and + instructions for manually fixing the configuration have been specified, + these will be printed out at the end of execution by another function. Args: config_check (`ConfigCheck`): The check to perform. @@ -356,24 +434,55 @@ def do_fix_and_test(config_check): Returns: bool: Whether an attempted fix was successful. """ - _try_fix(config_check, use_sudo=False) - if run_check(config_check, last_attempt=False, quiet_fail=True): - return True - else: + dprint("Entered do_fix_and_test()") + + if config_check.fix is not None: + _try_fix(config_check, use_sudo=False) + check_result = run_check( + config_check, last_attempt=False, quiet_fail=True) + if check_result == CheckResult.explicit_pass: + return True + + if config_check.sudo_fix is not None: _try_fix(config_check, use_sudo=True) - return run_check(config_check, last_attempt=True, quiet_fail=False) + check_result = run_check( + config_check, last_attempt=True, quiet_fail=False) + return True if check_result == CheckResult.explicit_pass else False + else: + return False + +def dprint_settings(): + """Prints current global flags when debug printing is enabled.""" + dprint("ENABLE_DEBUG_PRINT: %s" % str(const.ENABLE_DEBUG_PRINT)) + dprint("WRITE_TO_LOG_FILE: %s" % str(const.WRITE_TO_LOG_FILE)) + dprint("PROMPT_FOR_FIXES: %s" % str(const.PROMPT_FOR_FIXES)) + dprint("ATTEMPT_FIXES: %s" % str(const.ATTEMPT_FIXES)) + dprint("SKIP_SUDO_TESTS: %s" % str(const.SKIP_SUDO_TESTS)) def main(): """Main function.""" global glob_check_num + args = get_sys_args() + const.ENABLE_DEBUG_PRINT = args['debug-print'] + const.WRITE_TO_LOG_FILE = args['write-to-log-file'] + const.PROMPT_FOR_FIXES = not args['no-prompt'] + const.ATTEMPT_FIXES = not args['report-only'] + const.SKIP_SUDO_TESTS = args['skip-sudo-checks'] + + dprint_settings() + _print_banner() config_checks = read_config(const.DEFAULT_CONFIG_FILE) completely_failed_tests = [] for config_check in config_checks: - if not run_check(config_check): - #config failed check + check_result = run_check(config_check) + if check_result in (CheckResult.explicit_fail, CheckResult.no_pass): + if not const.ATTEMPT_FIXES: + glob_check_num += 1 + continue + if config_check.fix is None and config_check.sudo_fix is None: #no automatic fix available if config_check.manual_fix is not None: @@ -392,9 +501,14 @@ def main(): elif config_check.confidence == Confidence.experimental: prompt_default = const.FIX_EXPERIMENTAL_BY_DEFAULT descriptor = const.EXPERIMENTAL_STR + ' ' + + next_fix_command = config_check.fix + if next_fix_command is None: + next_fix_command = config_check.sudo_fix + question = (("\tApply the following %s fix? This will " "execute this command:\n\t\t'%s'") % - (descriptor, config_check.fix)) + (descriptor, next_fix_command)) if prompt.query_yes_no(question=question, default=_bool_to_yes_no(prompt_default)): fixed = do_fix_and_test(config_check) @@ -419,6 +533,7 @@ def main(): glob_check_num += 1 if const.WRITE_TO_LOG_FILE: + log_to_file("osx-config %s" % const.VERSION) print("Wrote results to %s'%s'%s." % (const.COLORS['BOLD'], const.LOG_FILE_LOC, const.COLORS['ENDC'])) @@ -465,7 +580,7 @@ def is_match(regex, string, ignore_case=False): def _print_banner(): banner = (("---------------------------------------------------------------" "---------------------------\n" - "%s%sosx-config-check%s\n" + "%s%sosx-config-check%s %s\n" "Download the latest copy of this tool at: " "https://github.com/kristovatlas/osx-config-check \n" "Report bugs/issues:\n" @@ -475,8 +590,61 @@ def _print_banner(): "---------------------------------------------------------------" "---------------------------\n") % (const.COLORS['BOLD'], const.COLORS['OKBLUE'], - const.COLORS['ENDC'])) + const.COLORS['ENDC'], const.VERSION)) print _underline_hyperlink(banner) +def print_usage(): + """Prints usage for this command-line tool and exits.""" + print("Usage: python app.py [OPTIONS]\n" + "OPTIONS:\n" + "\t--debug-print Enables verbose output for debugging the " + "tool.\n" + "\t--report-only Only reports on compliance and does not " + "offer to fix broken configurations.\n" + "\t--disable-logs Refrain from creating a log file with the " + "results.\n" + "\t--disable-prompt Refrain from prompting user before applying " + "fixes.\n" + "\t--skip-sudo-checks Do not perform checks that require sudo " + "privileges.\n" + "\t--help -h Print this usage information.\n") + sys.exit() + +def get_sys_args(): + """Parses command line args, setting defaults where not specified. + + Returns: dict: + * debug-print (bool) + * report-only (bool) + * write-to-log-file (bool) + * no-prompt (bool) + * skip-sudo-checks (bool) + """ + args = {'debug-print': False, + 'report-only': False, + 'write-to-log-file': True, + 'no-prompt': False, + 'skip-sudo-checks': False} + unprocessed_args = sys.argv[1:] + while len(unprocessed_args) > 0: + flag = unprocessed_args.pop(0) + if flag == '--debug-print': + args['debug-print'] = True + elif flag == '--report-only': + args['report-only'] = True + elif flag == '--disable-logs': + args['write-to-log-file'] = False + elif flag == '--disable-prompt': + args['no-prompt'] = True + elif flag == '--skip-sudo-checks': + args['skip-sudo-checks'] = True + elif flag == '-h' or flag == '--help': + print_usage() + else: + print "ERROR: Unrecognized option '%s'" % flag + print_usage() + + return args + if __name__ == "__main__": main() diff --git a/dns_helper.sh b/dns_helper.sh new file mode 100644 index 0000000..eb8a983 --- /dev/null +++ b/dns_helper.sh @@ -0,0 +1,61 @@ +#!/bin/bash +#Author: Kristov Atlas https://github.com/kristovatlas/osx-config-check +#Description: Helps user temporarily return to automatic DNS configuration in +#order to resolve problems connecting to wi-fi active portals that use their own +#DNS servers. + +#This uses the networksetup tool and requires sudo privs + +STORED_DNS='' + +function store_dns { + #echo "DEBUG: entered store_dns" + STORED_DNS=$(networksetup -getdnsservers Wi-Fi | tr -s "\n" " ") + if [ "$STORED_DNS" = "There aren't any DNS Servers set on Wi-Fi. " ]; then + echo "Oops! You already had DNS settings set to automatic. You're having some other kind of problem connecting to wi-fi. Try opening your browser and surfing to 'http://example' to bring up an active-portal login page." + exit + fi + echo "(Your current DNS servers are '$STORED_DNS')" +} + +function set_automatic_dns { + #echo "DEBUG: entered set_automatic_dns." + store_dns + echo "Enter your OSX login password if prompted: " + sudo networksetup -setdnsservers Wi-Fi "empty" + + NEW_VAL=$(networksetup -getdnsservers Wi-Fi) + if [ "$NEW_VAL" = "There aren't any DNS Servers set on Wi-Fi." ]; then + echo "Successfully changed DNS settings to automatic." + else + echo "Oops! There may have been a problem setting DNS settings to automatic :(" + fi + #echo "DEBUG: new DNS settings: '$NEW_VAL'" +} + +function restore_dns { + #echo "DEBUG: Entered restore_dns" + echo "Enter your OSX login password if prompted: " + sudo networksetup -setdnsservers Wi-Fi $STORED_DNS + echo "DNS settings restored." +} + +echo This program will help you temporarily restore automatic DNS settings when you\'re having trouble connecting to Wi-Fi networks. + +valid_response=0 +while [ $valid_response -eq 0 ] ; do + read -r -p "Temporarily set DNS to automatic settings? [Y/n] " response + response=$(perl -e "print lc('$response')") + + if [[ $response =~ ^(yes|y| ) ]]; then + valid_response=1 + set_automatic_dns + else + if [[ $response =~ ^(no|n) ]]; then + exit + fi + fi +done + +read -r -p "You're now ready to connect to a Wi-Fi active portal. You may need to open a web browser and surf to 'http://example.com' to interact with the active portal. When you're done connecting, PRESS ENTER here to restore your original DNS settings." +restore_dns diff --git a/osx-config.hjson b/osx-config.hjson index ae6e596..60c118f 100644 --- a/osx-config.hjson +++ b/osx-config.hjson @@ -7,15 +7,19 @@ /* syntax: [ { - `description` is a human-readable string describing the configuration being checked. (REQUIRED FIELD) + `description` is a human-readable string describing the configuration being checked; it should be a present-tense statement about a positive security configuration. (REQUIRED FIELD) `confidence` indicates subjective estimation of negative side-effects. valid values: "required", "recommended", "experimental". (REQUIRED FIELD) `reference` provides a link to where a user can find more information about this configuration, or a citation of where this configuration was taken from. (OPTIONAL FIELD) - `type` is "exact match" or "regex match". (REQUIRED FIELD) - `command` is the command you want to verify the output of. Should not contain sudo. (OPTIONAL FIELD) - `sudo_command` a version of the command that requires elevated privileges should the `command` version fail to pass. (OPTIONAL FIELD) - `expected_stdout` is the stdout string to match if type is "exact match". (REQUIRED FIELD -- this or `expected_regex`) - `expected_regex` is the regex to match against stdout if type is "regex match". (REQUIRED FIELD -- this or `expected_stdout`) - `case_sensitive` is "true" or "false". (REQUIRED FIELD) + `tests`: // is an ordered array of test objects. (REQUIRED FIELD, should not be empty) + [ + { + `type` is "exact match" or "regex match". (REQUIRED FIELD) + `command` is the command you want to verify the output of (REQUIRED FIELD) + `command_pass` is the value that `command`'s output should match. If it matches, all tests pass and subsequent tests for this config are not evaluated. (OPTIONAL FIELD) + `command_fail` is the value that `command`'s output should NOT match. If it matches, all tests fail and subsequent tests for this config are not evaluated. (OPTIONAL FIELD) + `case_sensitive` is "true" or "false" depending on whether the `command_pass` and/or `command_fail` values are case-sensitive. (REQUIRED FIELD) + } + ] `fix`: // is a JSON object that specifies how to remediate a broken configuration (REQUIRED FIELD, should not be empty) { `command` is the command that you use to attempt automatic remediation without sudo privileges. (OPTIONAL FIELD) @@ -24,56 +28,120 @@ } } ] -/* samples: +*/ +/* NOTES: + * back-slashes '\' must be escaped with a double black-slash, i.e. '\\' +*/ [ + /* --- BEGIN HOMEBREW SETTINGS --- */ { - description: "The OSX application firewall is enabled." + //Install Homebrew as a useful tool for semi-securely install or updating other tools + description: "Homebrew is installed." confidence: "required" - type: "exact match" - command: "defaults -currentHost read /Library/Preferences/com.apple.alf globalstate" - expected_stdout: "1" - case_sensitive: "false" - fix: - { - command: "defaults -currentHost write /Library/Preferences/com.apple.alf globalstate -bool true" - sudo_command: "sudo defaults -currentHost write /Library/Preferences/com.apple.alf globalstate -bool true" + tests: + [ + { + type: "exact match" + command: + echo $(homebrew_is_installed) + command_pass: "1" + command_fail: "0" + case_sensitive: "false" + } + ] + fix: + { + //This homebrew script requries sudo privs and so the user of this tool should be alerted as to why she is being prompted for a password + sudo_command: "/usr/bin/ruby ./scripts/homebrew_install_ed33f044812cc9c509a4d8e6997c44441b06dd4e1fc87f131ee9f319d77fcd50.rb" manual: - 1. Open System Preferences. - 2. Select "Security & Privacy". - 3. Select "Firewall". - 4. If necessary, click the lock icon in the bottom left corner and enter your administrator credentials. - 5. Select "Turn On Firewall". + ''' + Homebrew is a useful tool for installing and updating programs from the command line. + There are various things that can go wrong when attempting to install Homebrew. + Please review their installation guide here: + https://github.com/Homebrew/brew/blob/master/share/doc/homebrew/Installation.md + ''' } - }, + } { - description: "The File Vault key is destroyed when going to standby mode." + //Tools installed by Homebrew should be preferred according to the PATH + //environment variable. + "description": "Binaries installed to /usr/local/bin are preferred over those in /usr/bin (Note: If this check does not pass, other tests will fail)" confidence: "required" - type: "regex match" - command: "pmset -g" - expected_regex: ".*DestroyFVKeyOnStandby\\s+1.*" - case_sensitive: "false" + tests: + [ + { + type: "exact match" + command: "bash ./scripts/check_usr_local_bin_pos.sh" + command_pass: 1 + command_fail: 0 + case_sensitive: false + } + ] + fix: + { + //Only "fix" this PATH preference if we haven't already applied the + //fix to the ~/.profile file. Otherwise, the user will need to + //restart Terminal in order for this take effect. + command: + python ./scripts/set_path_precedence.py "/usr/local/bin" "/usr/bin" + manual: + ''' + 1. Bring the Terminal application to the foreground if it is not already. You should see the word "Terminal" in the top left corner of your screen. + 2. Select Terminal->Quit + 3. Re-open the Terminal application and run the tool again; this check should now pass. + ''' + } + } + /* ---- END HOMEBREW SETTINGS ---- */ + + { + //JRE is a scourge + description: "Java Runtime Environment is up to date." + confidence: recommended + tests: + [ + { + //Pass test if `java` is not installed + type: "exact match" + command: java_is_installed + command_pass: 0 + case_sensitive: false + } + { + //Past test if the latest version available via `brew cask install java` is installed + type: "exact match" + command: java -version 2>&1 >/dev/null | grep 'java version' + command_pass: + java version "1.8.0_102" + case_sensitive: false + } + ] fix: { - command: "pmset -a destroyfvkeyonstandby 1" - sudo_command: "sudo pmset -a destroyfvkeyonstandby 1" + manual: + ''' + 1. Your installation of Java is not up to date. You can either update it or remove it. + 2. To update Java, see: https://www.java.com/en/download/faq/java_mac.xml + 3. To remove Java, see: https://www.java.com/en/download/help/mac_uninstall_java.xml + ''' } } -] -*/ -/* NOTES: - * back-slashes '\' must be escaped with a double black-slash, i.e. '\\' -*/ -[ + /* --- BEGIN SYSTEM SETTINGS --- */ { //Check if the System Preferences app is closed -- otherwise, it may override changes this app makes. description: "The System Preferences application is currently closed." confidence: "required" reference: "https://developer.apple.com/legacy/library/documentation/Darwin/Reference/ManPages/man1/defaults.1.html" - type: "exact match" - command: "ps ax | grep -c '/Applications/System Preferences.app/Contents/MacOS/System Preferences'" - expected_stdout: "2" //a value of "3" means it's running -- the other 2 are `/bin/sh` and the `grep` command. - case_sensitive: "false" + tests: + [ + { + type: "exact match" + command: "ps ax | grep -c '/Applications/System Preferences.app/Contents/MacOS/System Preferences'" + command_pass: "2" //a value of "3" means it's running -- the other 2 are `/bin/sh` and the `grep` command. + case_sensitive: "false" + } + ] fix: { command: @@ -83,10 +151,15 @@ { description: "Current user is a non-admin account." confidence: "required" - type: "exact match" - command: "id -Gn | grep -c -w admin" - expected_stdout: "0" - case_sensitive: "false" + tests: + [ + { + type: "exact match" + command: "id -Gn | grep -c -w admin" + command_pass: "0" + case_sensitive: "false" + } + ] fix: { manual: @@ -106,10 +179,23 @@ description: "The OSX application firewall is enabled (system-wide)." confidence: "required" reference: "https://github.com/drduh/OS-X-Security-and-Privacy-Guide" - type: "exact match" - command: "defaults -currentHost read /Library/Preferences/com.apple.alf globalstate" - expected_stdout: "1" - case_sensitive: "false" + tests: + [ + { + //Exempt users who are using Little Snitch + type: "exact match" + command: little_snitch_is_installed + command_pass: 1 + case_sensitive: false + } + { + type: "exact match" + command: "defaults -currentHost read /Library/Preferences/com.apple.alf globalstate" + command_pass: "1" + command_fail: "0" + case_sensitive: "false" + } + ] fix: { command: "defaults -currentHost write /Library/Preferences/com.apple.alf globalstate -bool true" @@ -121,10 +207,23 @@ description: "The OSX application firewall is enabled (current user only)." confidence: "required" reference: "https://github.com/drduh/OS-X-Security-and-Privacy-Guide" - type: "exact match" - command: "defaults -currentHost read ~/Library/Preferences/com.apple.alf globalstate" - expected_stdout: "1" - case_sensitive: "false" + tests: + [ + { + //Exempt users who are using Little Snitch + type: "exact match" + command: little_snitch_is_installed + command_pass: 1 + case_sensitive: false + } + { + type: "exact match" + command: "defaults -currentHost read ~/Library/Preferences/com.apple.alf globalstate" + command_pass: "1" + command_fail: "0" + case_sensitive: "false" + } + ] fix: { command: "defaults -currentHost write ~/Library/Preferences/com.apple.alf globalstate -bool true" @@ -135,11 +234,23 @@ description: "A password is required to wake the computer from sleep or screen saver (system-wide)." confidence: "required" reference: "https://github.com/SummitRoute/osxlockdown/blob/58697f5162fe9e43df7dc9b6b94ffa34b0e11d4f/commands.yaml" - type: "exact match" - command: "defaults read /Library/Preferences/com.apple.screensaver askForPassword" - sudo_command: "sudo defaults read /Library/Preferences/com.apple.screensaver askForPassword" - expected_stdout: "1" - case_sensitive: "false" + tests: + [ + { + type: "exact match" + command: "defaults read /Library/Preferences/com.apple.screensaver askForPassword" + command_pass: "1" + command_fail: "0" + case_sensitive: "false" + }, + { + type: "exact match" + command: "sudo defaults read /Library/Preferences/com.apple.screensaver askForPassword" + command_pass: "1" + command_fail: "0" + case_sensitive: "false" + } + ] fix: { command: "defaults write /Library/Preferences/com.apple.screensaver askForPassword -bool true" @@ -150,10 +261,15 @@ description: "A password is required to wake the computer from sleep or screen saver (current user only)." confidence: "required" reference: "https://github.com/SummitRoute/osxlockdown/blob/58697f5162fe9e43df7dc9b6b94ffa34b0e11d4f/commands.yaml" - type: "exact match" - command: "defaults read ~/Library/Preferences/com.apple.screensaver askForPassword" - expected_stdout: "1" - case_sensitive: "false" + tests: + [ + { + type: "exact match" + command: "defaults read ~/Library/Preferences/com.apple.screensaver askForPassword" + command_pass: "1" + case_sensitive: "false" + } + ] fix: { command: "defaults write ~/Library/Preferences/com.apple.screensaver askForPassword -bool true" @@ -164,11 +280,23 @@ description: "There is no delay between starting the screen saver and locking the machine (system-wide)." confidence: "required" reference: "https://github.com/SummitRoute/osxlockdown/blob/58697f5162fe9e43df7dc9b6b94ffa34b0e11d4f/commands.yaml" - type: "exact match" - command: "defaults -currentHost read /Library/Preferences/com.apple.screensaver askForPasswordDelay" - sudo_command: "sudo defaults -currentHost read /Library/Preferences/com.apple.screensaver askForPasswordDelay" - expected_stdout: "0" - case_sensitive: "false" + tests: + [ + { + type: "exact match" + command: "defaults -currentHost read /Library/Preferences/com.apple.screensaver askForPasswordDelay" + command_pass: "0" + command_fail: "1" + case_sensitive: "false" + }, + { + type: "exact match" + command: "sudo defaults -currentHost read /Library/Preferences/com.apple.screensaver askForPasswordDelay" + command_pass: "0" + command_fail: "1" + case_sensitive: "false" + } + ] fix: { command: "defaults -currentHost write /Library/Preferences/com.apple.screensaver askForPasswordDelay -bool false" @@ -181,10 +309,16 @@ description: "There is no delay between starting the screen saver and locking the machine (current user only)." confidence: "required" reference: "https://github.com/SummitRoute/osxlockdown/blob/58697f5162fe9e43df7dc9b6b94ffa34b0e11d4f/commands.yaml" - type: "exact match" - command: "defaults -currentHost read ~/Library/Preferences/com.apple.screensaver askForPasswordDelay" - expected_stdout: "0" - case_sensitive: "false" + tests: + [ + { + type: "exact match" + command: "defaults -currentHost read ~/Library/Preferences/com.apple.screensaver askForPasswordDelay" + command_pass: "0" + command_fail: "1" + case_sensitive: "false" + } + ] fix: { command: "defaults -currentHost write ~/Library/Preferences/com.apple.screensaver askForPasswordDelay -bool false" @@ -195,10 +329,17 @@ description: "Logging is enabled for the operating system." confidence: "required" reference: "https://github.com/drduh/OS-X-Security-and-Privacy-Guide" - type: "exact match" - command: "defaults -currentHost read /Library/Preferences/com.apple.alf loggingenabled" - expected_stdout: "1" - case_sensitive: "false" + tests: + [ + { + type: "exact match" + command: "defaults -currentHost read /Library/Preferences/com.apple.alf loggingenabled" + command_pass: "1" + command_fail: "0" + case_sensitive: "false" + + } + ] fix: { command: "defaults -currentHost write /Library/Preferences/com.apple.alf loggingenabled -bool true" @@ -209,17 +350,26 @@ description: "Homebrew analytics are disabled." confidence: "required" reference: "https://github.com/Homebrew/brew/blob/master/share/doc/homebrew/Analytics.md" - type: "exact match" - //test based on: https://github.com/Homebrew/brew/blob/master/Library/Homebrew/utils/analytics.sh - command: "[[ -n $HOMEBREW_NO_ANALYTICS ]] && echo 1 || echo 0" - expected_stdout: "1" - case_sensitive: "false" + tests: + [ + { + type: "exact match" + //test based on: https://github.com/Homebrew/brew/blob/master/Library/Homebrew/utils/analytics.sh + command: "[[ -n $HOMEBREW_NO_ANALYTICS ]] && echo 1 || echo 0" + command_pass: "1" + command_fail: "0" + case_sensitive: "false" + } + ] fix: { - //TODO: This fix works if you login/logout, but I haven't been able to get a fix working that doesn't require login/logout. The enironment variable is context dependent, and it's not clear how to set the variable in the parent-most environment without this action. command: "grep -q 'export HOMEBREW_NO_ANALYTICS=1' ~/.profile || echo 'export HOMEBREW_NO_ANALYTICS=1' >> ~/.profile ; source ~/.profile" manual: - 1. In order for the automatic fix to be applied, you must logout of the current user and log back in. Sorry for the inconvenience! + ''' + 1. Bring the Terminal application to the foreground if it is not already. You should see the word "Terminal" in the top left corner of your screen. + 2. Select Terminal->Quit + 3. Re-open the Terminal application and run the tool again; this check should now pass. + ''' } }, { @@ -228,10 +378,16 @@ description: "Stealth mode is enabled for OSX: Computer does not respond to ICMP ping requests or connection attempts from a closed TCP/UDP port. (system-wide)" confidence: "recommended" reference: "https://github.com/drduh/OS-X-Security-and-Privacy-Guide" - type: "exact match" - command: "defaults -currentHost read /Library/Preferences/com.apple.alf stealthenabled" - expected_stdout: "1" - case_sensitive: "false" + tests: + [ + { + type: "exact match" + command: "defaults -currentHost read /Library/Preferences/com.apple.alf stealthenabled" + command_pass: "1" + command_fail: "0" + case_sensitive: "false" + } + ] fix: { command: "defaults write /Library/Preferences/com.apple.alf stealthenabled -bool true" @@ -244,10 +400,16 @@ description: "Stealth mode is enabled for OSX: Computer does not respond to ICMP ping requests or connection attempts from a closed TCP/UDP port. (current user only)" confidence: "recommended" reference: "https://github.com/drduh/OS-X-Security-and-Privacy-Guide" - type: "exact match" - command: "defaults -currentHost read ~/Library/Preferences/com.apple.alf stealthenabled" - expected_stdout: "1" - case_sensitive: "false" + tests: + [ + { + type: "exact match" + command: "defaults -currentHost read ~/Library/Preferences/com.apple.alf stealthenabled" + command_pass: "1" + command_fail: "0" + case_sensitive: "false" + } + ] fix: { command: "defaults write ~/Library/Preferences/com.apple.alf stealthenabled -bool true" @@ -257,13 +419,19 @@ }, { //System Preferences->Security & Privacy->Firewall->Firewall Options...->Automatically allow signed software to receive incoming connections - description: "Automatic whitelisting of Apple-signed applications for firewall is disabled (system-wide)." + description: "Automatic whitelisting of Apple-signed applications through the firewall is disabled (system-wide)." confidence: "required" reference: "https://github.com/drduh/OS-X-Security-and-Privacy-Guide" - type: "exact match" - command: "defaults -currentHost read /Library/Preferences/com.apple.alf allowsignedenabled" - expected_stdout: "0" - case_sensitive: "false" + tests: + [ + { + type: "exact match" + command: "defaults -currentHost read /Library/Preferences/com.apple.alf allowsignedenabled" + command_pass: "0" + command_fail: "1" + case_sensitive: "false" + } + ] fix: { command: "defaults -currentHost write /Library/Preferences/com.apple.alf allowsignedenabled -bool false" @@ -273,13 +441,19 @@ }, { //System Preferences->Security & Privacy->Firewall->Firewall Options...->Automatically allow signed software to receive incoming connections - description: "Automatic whitelisting of Apple-signed applications for firewall is disabled (current user only)." + description: "Automatic whitelisting of Apple-signed applications through the firewall is disabled (current user only)." confidence: "required" reference: "https://github.com/drduh/OS-X-Security-and-Privacy-Guide" - type: "exact match" - command: "defaults -currentHost read ~/Library/Preferences/com.apple.alf allowsignedenabled" - expected_stdout: "0" - case_sensitive: "false" + tests: + [ + { + type: "exact match" + command: "defaults -currentHost read ~/Library/Preferences/com.apple.alf allowsignedenabled" + command_pass: "0" + command_fail: "1" + case_sensitive: "false" + } + ] fix: { command: "defaults -currentHost write ~/Library/Preferences/com.apple.alf allowsignedenabled -bool false" @@ -290,10 +464,16 @@ description: "Captive portal for connecting to new networks is disabled to prevent MITM attacks." confidence: "required" reference: "https://github.com/drduh/OS-X-Security-and-Privacy-Guide" - type: "exact match" - command: "defaults -currentHost read /Library/Preferences/SystemConfiguration/com.apple.captive.control Active" - expected_stdout: "0" - case_sensitive: "false" + tests: + [ + { + type: "exact match" + command: "defaults -currentHost read /Library/Preferences/SystemConfiguration/com.apple.captive.control Active" + command_pass: "0" + command_fail: "1" + case_sensitive: "false" + } + ] fix: { command: "defaults -currentHost write /Library/Preferences/SystemConfiguration/com.apple.captive.control Active -bool false" @@ -302,28 +482,43 @@ undo: "sudo defaults -currentHost write /Library/Preferences/SystemConfiguration/com.apple.captive.control Active -bool true" }, { - description: "OpenSSL is up-to-date." + description: "OpenSSL is up to date." confidence: "required" reference: "https://github.com/drduh/OS-X-Security-and-Privacy-Guide" - type: "exact match" - command: "openssl version" - expected_stdout: "OpenSSL 1.0.2h 3 May 2016" - case_sensitive: "false" - fix: - { - command: "brew update ; brew install openssl ; brew upgrade openssl ; brew link openssl --force ; mv /usr/bin/openssl /usr/bin/openssl-apple" - sudo_command: "brew update ; brew install openssl ; brew upgrade openssl ; brew link openssl --force ; sudo mv /usr/bin/openssl /usr/bin/openssl-apple" + tests: + [ + { + type: "exact match" + command: "openssl version" + command_pass: "OpenSSL 1.0.2h 3 May 2016" + case_sensitive: "false" + } + ] + fix: + { + command: "brew update ; brew install openssl ; brew upgrade openssl ; bash ./scripts/set_openssl_latest_path.sh" + manual: + ''' + 1. Bring the Terminal application to the foreground if it is not already. You should see the word "Terminal" in the top left corner of your screen. + 2. Select Terminal->Quit + 3. Re-open the Terminal application and run the tool again; this check should now pass. + ''' } - undo: "sudo mv /usr/bin/openssl-apple /usr/bin/openssl ; brew unlink openssl" }, { description: "Hidden files are displayed in Finder." confidence: "recommended" reference: "http://lifehacker.com/the-best-hidden-settings-you-can-unlock-with-os-xs-ter-1476627111" - type: "exact match" - command: "defaults -currentHost read /Library/Preferences/SystemConfiguration/com.apple.finder AppleShowAllFiles" - expected_stdout: "1" - case_sensitive: "false" + tests: + [ + { + type: "exact match" + command: "defaults -currentHost read /Library/Preferences/SystemConfiguration/com.apple.finder AppleShowAllFiles" + command_pass: "1" + command_fail: "0" + case_sensitive: "false" + } + ] fix: { command: "defaults -currentHost write /Library/Preferences/SystemConfiguration/com.apple.finder AppleShowAllFiles -bool true && killall Dock" @@ -335,11 +530,17 @@ description: "All application software is currently up to date." confidence: "required" reference: "https://github.com/SummitRoute/osxlockdown/" - type: "exact match" - command: - LASTUPDATE=$(defaults read /Library/Preferences/com.apple.SoftwareUpdate | grep LastSuccessfulDate | sed -e 's@^.* "\([0-9\\-]*\) .*$@\1@'); if [ "$LASTUPDATE" = "$(date +%Y-%m-%d)" ];then echo 1 && exit; fi; exit 0 && exit - expected_stdout: "1" - case_sensitive: "false" + tests: + [ + { + type: "exact match" + command: + LASTUPDATE=$(defaults read /Library/Preferences/com.apple.SoftwareUpdate | grep LastSuccessfulDate | sed -e 's@^.* "\([0-9\\-]*\) .*$@\1@'); if [ "$LASTUPDATE" = "$(date +%Y-%m-%d)" ];then echo 1 && exit; fi; echo 0 && exit + command_pass: "1" + command_fail: "0" + case_sensitive: "false" + } + ] fix: { command: "softwareupdate -i -a" @@ -351,11 +552,15 @@ description: "Automatic check for software updates is enabled." confidence: "required" reference: "https://github.com/SummitRoute/osxlockdown/" - type: "exact match" - command: "softwareupdate --schedule | grep 'Automatic check is on'" - sudo_command: "sudo softwareupdate --schedule | grep 'Automatic check is on'" - expected_stdout: "Automatic check is on" - case_sensitive: "false" + tests: + [ + { + type: "exact match" + command: "sudo softwareupdate --schedule | grep -i 'Automatic check is on'" + command_pass: "Automatic check is on" + case_sensitive: "false" + } + ] fix: { command: "softwareupdate --schedule on" @@ -366,10 +571,15 @@ //System Preferences->Security & Privacy->General->Allow apps downloaded from description: "GateKeeper protection against untrusted applications is enabled." confidence: "required" - type: "exact match" - command: "spctl --status | grep 'assessments enabled'" - expected_stdout: "assessments enabled" - case_sensitive: "false" + tests: + [ + { + type: "exact match" + command: "spctl --status | grep -i 'assessments enabled'" + command_pass: "assessments enabled" + case_sensitive: "false" + } + ] fix: { command: "spctl --master-enable" @@ -381,11 +591,23 @@ //System Preferences->Bluetooth->Turn Bluetooth Off description: "Bluetooth is disabled." confidence: "experimental" - type: "exact match" - command: "defaults read /Library/Preferences/com.apple.Bluetooth ControllerPowerState" - sudo_command: "sudo defaults read /Library/Preferences/com.apple.Bluetooth ControllerPowerState" - expected_stdout: "0" - case_sensitive: "false" + tests: + [ + { + type: "exact match" + command: "defaults read /Library/Preferences/com.apple.Bluetooth ControllerPowerState" + command_pass: "0" + command_fail: "1" + case_sensitive: "false" + }, + { + type: "exact match" + command: "sudo defaults read /Library/Preferences/com.apple.Bluetooth ControllerPowerState" + command_pass: "0" + command_fail: "1" + case_sensitive: "false" + } + ] fix: { command: "defaults write /Library/Preferences/com.apple.Bluetooth ControllerPowerState -bool false; killall -HUP blued" @@ -396,11 +618,23 @@ { description: "The infrared receiver is disabled." confidence: "required" - type: "exact match" - command: "defaults read /Library/Preferences/com.apple.driver.AppleIRController DeviceEnabled" - sudo_command: "sudo defaults read /Library/Preferences/com.apple.driver.AppleIRController DeviceEnabled" - expected_stdout: "0" - case_sensitive: "false" + tests: + [ + { + type: "exact match" + command: "defaults read /Library/Preferences/com.apple.driver.AppleIRController DeviceEnabled" + command_pass: "0" + command_fail: "1" + case_sensitive: "false" + }, + { + type: "exact match" + command: "sudo defaults read /Library/Preferences/com.apple.driver.AppleIRController DeviceEnabled" + command_pass: "0" + command_fail: "1" + case_sensitive: "false" + } + ] fix: { command: "defaults write /Library/Preferences/com.apple.driver.AppleIRController DeviceEnabled -bool false" @@ -411,17 +645,28 @@ { description: "AirDrop file sharing is disabled." confidence: "required" - type: "exact match" - command: "defaults read com.apple.NetworkBrowser DisableAirDrop" - sudo_command: "sudo defaults read com.apple.NetworkBrowser DisableAirDrop" - expected_stdout: "1" - case_sensitive: "false" - fix: - { - command: "defaults write /Library/Preferences/com.apple.NetworkBrowser DisableAirDrop -bool true" - sudo_command: "sudo defaults write /Library/Preferences/com.apple.NetworkBrowser DisableAirDrop -bool true" - } - undo: "defaults write /Library/Preferences/com.apple.NetworkBrowser DisableAirDrop -bool false" + tests: + [ + { + type: "exact match" + command: "defaults read com.apple.NetworkBrowser DisableAirDrop" + command_pass: "1" + command_fail: "0" + case_sensitive: "false" + }, + { + type: "exact match" + command: "sudo defaults read com.apple.NetworkBrowser DisableAirDrop" + command_pass: "1" + command_fail: "0" + case_sensitive: "false" + } + ] + fix: + { + command: "defaults_write_ignore_missing com.apple.NetworkBrowser DisableAirDrop -bool true" + } + undo: "defaults write com.apple.NetworkBrowser DisableAirDrop -bool false" }, /* Begin: System Preferences->Sharing */ @@ -430,11 +675,17 @@ description: "File sharing is disabled." confidence: "recommended" reference: "https://github.com/SummitRoute/osxlockdown/blob/58697f5162fe9e43df7dc9b6b94ffa34b0e11d4f/commands.yaml" - type: "exact match" - command: - if [ -n "$(launchctl list | egrep AppleFileServer)" ]; then exit 1; fi; if [ -n "$(grep -i array /Library/Preferences/SystemConfiguration/com.apple.smb.server.plist)" ]; then echo 1; exit; fi; echo 0; exit - expected_stdout: "0" - case_sensitive: "false" + tests: + [ + { + type: "exact match" + command: + if [ -n "$(launchctl list | egrep AppleFileServer)" ]; then exit 1; fi; if [ -n "$(grep -i array /Library/Preferences/SystemConfiguration/com.apple.smb.server.plist)" ]; then echo 1; exit; fi; echo 0; exit + command_pass: "0" + command_fail: "1" + case_sensitive: "false" + } + ] fix: { command: "launchctl unload -w /System/Library/LaunchDaemons/com.apple.AppleFileServer.plist; launchctl unload -w /System/Library/LaunchDaemons/com.apple.smbd.plist" @@ -445,11 +696,17 @@ description: "Printer sharing is disabled." confidence: "required" reference: "https://github.com/SummitRoute/osxlockdown/blob/58697f5162fe9e43df7dc9b6b94ffa34b0e11d4f/commands.yaml" - type: "exact match" - command: - if [ -n "$(system_profiler SPPrintersDataType | grep Shared | grep Yes)" ]; then echo 1; exit; fi; if [ -n "$(system_profiler SPPrintersDataType | grep 'System Printer Sharing: Yes')" ]; then echo 1; exit; fi; echo 0; exit - expected_stdout: "0" - case_sensitive: "false" + tests: + [ + { + type: "exact match" + command: + if [ -n "$(system_profiler SPPrintersDataType | grep Shared | grep Yes)" ]; then echo 1; exit; fi; if [ -n "$(system_profiler SPPrintersDataType | grep 'System Printer Sharing: Yes')" ]; then echo 1; exit; fi; echo 0; exit + command_pass: "0" + command_fail: "1" + case_sensitive: "false" + } + ] fix: { command: "cupsctl --no-share-printers" @@ -459,11 +716,21 @@ //System Preferences->Sharing->Remote Login description: "Remote login is disabled." confidence: "required" - type: "exact match" - command: "systemsetup -getremotelogin" - sudo_command: "sudo systemsetup -getremotelogin" - expected_stdout: "Remote Login: Off" - case_sensitive: "false" + tests: + [ + { + type: "exact match" + command: "systemsetup -getremotelogin" + command_pass: "Remote Login: Off" + case_sensitive: "false" + }, + { + type: "exact match" + command: "sudo systemsetup -getremotelogin" + command_pass: "Remote Login: Off" + case_sensitive: "false" + } + ] fix: { command: "systemsetup -f -setremotelogin off" @@ -475,11 +742,17 @@ //System Preferences->Sharing->Remote Management description: "Remote Management is disabled." confidence: "required" - type: "exact match" - command: - if [ -n "$(ps -ef | egrep "/System/Library/CoreServices/RemoteManagement/ARDAgent.app/Contents/MacOS/[A]RDAgent")" ]; then echo 1; exit; fi; echo 0; exit - expected_stdout: "0" - case_sensitive: "false" + tests: + [ + { + type: "exact match" + command: + if [ -n "$(ps -ef | egrep "/System/Library/CoreServices/RemoteManagement/ARDAgent.app/Contents/MacOS/[A]RDAgent")" ]; then echo 1; exit; fi; echo 0; exit + command_pass: "0" + command_fail: "1" + case_sensitive: "false" + } + ] fix: { command: "/System/Library/CoreServices/RemoteManagement/ARDAgent.app/Contents/Resources/kickstart -deactivate -stop" @@ -492,11 +765,21 @@ description: "Remote Apple events are disabled." confidence: "required" reference: "https://github.com/SummitRoute/osxlockdown/blob/58697f5162fe9e43df7dc9b6b94ffa34b0e11d4f/commands.yaml" - type: "exact match" - command: "systemsetup -getremoteappleevents" - sudo_command: "sudo systemsetup -getremoteappleevents" - expected_stdout: "Remote Apple Events: Off" - case_sensitive: "false" + tests: + [ + { + type: "exact match" + command: "systemsetup -getremoteappleevents" + command_pass: "Remote Apple Events: Off" + case_sensitive: "false" + }, + { + type: "exact match" + command: "sudo systemsetup -getremoteappleevents" + command_pass: "Remote Apple Events: Off" + case_sensitive: "false" + } + ] fix: { command: "systemsetup -setremoteappleevents off" @@ -510,10 +793,15 @@ description: "Internet Sharing is disabled on all network interfaces." confidence: "required" reference: "https://github.com/SummitRoute/osxlockdown/blob/58697f5162fe9e43df7dc9b6b94ffa34b0e11d4f/commands.yaml" - type: "exact match" - command: "defaults read /Library/Preferences/SystemConfiguration/com.apple.nat NAT | grep -c 'Enabled = 1'" - expected_stdout: "0" - case_sensitive: "false" + tests: + [ + { + type: "exact match" + command: "defaults read /Library/Preferences/SystemConfiguration/com.apple.nat NAT | grep -c 'Enabled = 1'" + command_pass: "0" + case_sensitive: "false" + } + ] fix: { command: "defaults write /Library/Preferences/SystemConfiguration/com.apple.nat NAT -dict-add Enabled -bool false" @@ -525,11 +813,21 @@ //System Preferences->Energy Saver->Wake for network access description: "Wake on Network Access feature is disabled." confidence: "required" - type: "exact match" - command: "systemsetup getwakeonnetworkaccess" - sudo_command: "sudo systemsetup getwakeonnetworkaccess" - expected_stdout: "Wake On Network Access: Off" - case_sensitive: "false" + tests: + [ + { + type: "exact match" + command: "systemsetup getwakeonnetworkaccess" + command_pass: "Wake On Network Access: Off" + case_sensitive: "false" + }, + { + type: "exact match" + command: "sudo systemsetup getwakeonnetworkaccess" + command_pass: "Wake On Network Access: Off" + case_sensitive: "false" + } + ] fix: { command: "systemsetup -setwakeonnetworkaccess off" @@ -541,11 +839,23 @@ //Disables NTPd. There are definitely some downsides to this; some security software requires synchronized clocks, so this increases the risk of getting out of sync. I think most of this software will fail-safe, though. Disabling this has various benefits. See discussion here: https://github.com/SummitRoute/osxlockdown/issues/18 description: "Automatic setting of time and date is disabled." confidence: "recommended" - type: "exact match" - command: "systemsetup getusingnetworktime" - sudo_command: "sudo systemsetup getusingnetworktime" - expected_stdout: "Network Time: Off" - case_sensitive: "false" + tests: + [ + { + type: "exact match" + command: "systemsetup getusingnetworktime" + command_pass: "Network Time: Off" + command_fail: "Network Time: On" + case_sensitive: "false" + }, + { + type: "exact match" + command: "sudo systemsetup getusingnetworktime" + command_pass: "Network Time: Off" + command_fail: "Network Time: On" + case_sensitive: "false" + } + ] fix: { command: "systemsetup setusingnetworktime off" @@ -554,15 +864,21 @@ undo: "sudo systemsetup setusingnetworktime on" }, { - //There are a number of attacks based on IPv6 use. For the sake of simplicity, it's best to disable it entirely unless it is requried. See: https://www.ernw.de/download/ERNW_Hardening_IPv6_MacOS-X_v1_0.pdf + //There are a number of attacks based on IPv6 use. For the sake of simplicity, it's best to disable it entirely unless it is required. See: https://www.ernw.de/download/ERNW_Hardening_IPv6_MacOS-X_v1_0.pdf description: "IPv6 is disabled on all network interfaces." confidence: "recommended" reference: "https://github.com/SummitRoute/osxlockdown/blob/58697f5162fe9e43df7dc9b6b94ffa34b0e11d4f/commands.yaml" - type: "exact match" - command: - networksetup -listallnetworkservices | while read i; do SUPPORT=$(networksetup -getinfo "$i" | grep "IPv6: Automatic") && if [ -n "$SUPPORT" ]; then echo 1; fi; done; echo 0; exit - expected_stdout: "0" - case_sensitive: "false" + tests: + [ + { + type: "exact match" + command: + networksetup -listallnetworkservices | while read i; do SUPPORT=$(networksetup -getinfo "$i" | grep "IPv6: Automatic") && if [ -n "$SUPPORT" ]; then echo 1; fi; done; echo 0; exit + command_pass: "0" + //command_fail would be one or more instances of the character "1" + case_sensitive: "false" + } + ] fix: { command: @@ -573,11 +889,17 @@ description: "An administrator password is required to change system-wide preferences." confidence: "required" reference: "https://github.com/SummitRoute/osxlockdown/blob/58697f5162fe9e43df7dc9b6b94ffa34b0e11d4f/commands.yaml" - type: "exact match" - command: - if [ -n "$(security authorizationdb read system.preferences 2> /dev/null | grep -A1 shared | grep -E '(true|false)' | grep 'false')" ]; then echo 0; else echo 1; fi - expected_stdout: "0" - case_sensitive: "false" + tests: + [ + { + type: "exact match" + command: + if [ -n "$(security authorizationdb read system.preferences 2> /dev/null | grep -A1 shared | grep -E '(true|false)' | grep 'false')" ]; then echo 0; else echo 1; fi + command_pass: "0" + command_fail: "1" + case_sensitive: "false" + } + ] fix: { //TODO: Add warning to user before fix command is run that she will be prompted for her admin credentials. this requires a new field @@ -589,10 +911,16 @@ description: "Documents are not stored to iCloud Drive by default. (May be mistaken if iCloud is disabled)" confidence: "required" reference: "http://mjtsai.com/blog/2014/10/26/yosemite-uploads-unsaved-documents-and-recent-addresses-to-icloud/" - type: "exact match" - command: "defaults read NSGlobalDomain NSDocumentSaveNewDocumentsToCloud" - expected_stdout: "0" - case_sensitive: "false" + tests: + [ + { + type: "exact match" + command: "defaults read NSGlobalDomain NSDocumentSaveNewDocumentsToCloud" + command_pass: "0" + command_fail: "1" + case_sensitive: "false" + } + ] fix: { command: "defaults write NSGlobalDomain NSDocumentSaveNewDocumentsToCloud -bool false" @@ -600,27 +928,40 @@ undo: "defaults write NSGlobalDomain NSDocumentSaveNewDocumentsToCloud -bool true" }, { - description: "The File Vault key is destroyed when going to standby mode." + description: "The File Vault key is protected when going to standby mode." + //Once this set of configurations is proven stable, this can be upgraded from "experimental" to "recommended". We may want to warn the user first that waking will be slower and require authenticating twice. confidence: "experimental" reference: "https://github.com/drduh/OS-X-Security-and-Privacy-Guide" - type: "regex match" - command: "pmset -g" - expected_regex: ".*destroyfvkeyonstandby\\s+1.*" - case_sensitive: "false" + tests: + [ + { + type: "exact match" + command: "bash ./scripts/DestroyFVKeyOnStandby_check.sh" + command_pass: "1" + command_fail: "0" + case_sensitive: "false" + } + ] fix: { - command: "pmset -a destroyfvkeyonstandby 1" - sudo_command: "sudo pmset -a destroyfvkeyonstandby 1" + //Additional configurations are required to make this setting not fight with powernap/standby/autopoweroff. See: https://github.com/drduh/OS-X-Security-and-Privacy-Guide/issues/124 + command: "pmset -a destroyfvkeyonstandby 1 ; pmset -a hibernatemode 25 ; pmset -a powernap 0 ; pmset -a standby 0 ; pmset -a standbydelay 0; pmset -a autopoweroff 0" + sudo_command: "sudo pmset -a destroyfvkeyonstandby 1 ; sudo pmset -a hibernatemode 25 ; sudo pmset -a powernap 0 ; sudo pmset -a standby 0 ; sudo pmset -a standbydelay 0; sudo pmset -a autopoweroff 0" } }, { description: "The system will store a copy of memory to persistent storage, and will remove power to memory." confidence: "recommended" reference: "https://github.com/drduh/OS-X-Security-and-Privacy-Guide" - type: "regex match" - command: "pmset -g" - expected_regex: ".*hibernatemode\\s+25.*" - case_sensitive: "false" + tests: + [ + { + type: "regex match" + command: "pmset -g" + command_pass: ".*hibernatemode\\s+25.*" + case_sensitive: "false" + } + ] fix: { command: "pmset -a hibernatemode 25" @@ -630,26 +971,49 @@ { description: "git is up to date or is not installed" confidence: "required" - type: "regex match" - command: "git --version" - expected_regex: ".*(command not found|2\\.8\\.2).*" - case_sensitive: "false" - fix: - { - //This will make sure latest git is installed via homebrew and make make apple's version of git non-competitive - command: "brew update && brew install git && brew upgrade git && mv /usr/bin/git /usr/bin/git-apple" - sudo_command: "brew update && brew install git && brew upgrade git && sudo mv /usr/bin/git /usr/bin/git-apple" + tests: + [ + { + type: "regex match" + command: "git --version" + command_pass: ".*(command not found|2\\.9\\.3).*" + case_sensitive: "false" + } + ] + fix: + { + //Only "fix" this PATH preference if we haven't already applied the + //fix to the ~/.profile file. Otherwise, the user will need to + //restart Terminal in order for this take effect. + command: + brew update ; brew install git ; brew upgrade git ; python ./scripts/set_path_precedence.py "/usr/local/bin" "/usr/bin" + manual: + ''' + 1. Bring the Terminal application to the foreground if it is not already. You should see the word "Terminal" in the top left corner of your screen. + 2. Select Terminal->Quit + 3. Re-open the Terminal application and run the tool again; this check should now pass. + ''' } }, { description: "Apple Push Notifications are disabled." confidence: "recommended" reference: "https://github.com/drduh/OS-X-Security-and-Privacy-Guide" - type: "regex match" - command: "launchctl list" - sudo_command: "sudo launchctl list" - expected_regex: "^((?!com\\.apple\\.apsd).)*$" - case_sensitive: "false" + tests: + [ + { + type: "regex match" + command: "launchctl list" + command_pass: "^((?!com\\.apple\\.apsd).)*$" + case_sensitive: "false" + }, + { + type: "regex match" + command: "sudo launchctl list" + command_pass: "^((?!com\\.apple\\.apsd).)*$" + case_sensitive: "false" + } + ] fix: { command: "launchctl unload -w /System/Library/LaunchDaemons/com.apple.apsd.plist" @@ -660,25 +1024,36 @@ { description: "Google DNS servers are used by default on all network interfaces." confidence: "recommended" - type: "regex match" - command: "networksetup listallnetworkservices | grep -v 'An asterisk' | xargs -I{} networksetup -getdnsservers '{}' " - expected_regex: "^(8\\.8\\.8\\.8\\n8\\.8\\.4\\.4\n*)+$" - case_sensitive: "false" + tests: + [ + { + type: "regex match" + command: "networksetup listallnetworkservices | grep -v 'An asterisk' | xargs -I{} networksetup -getdnsservers '{}' " + command_pass: "^(8\\.8\\.8\\.8\\n8\\.8\\.4\\.4\n*)+$" + case_sensitive: "false" + } + ] fix: { - command: "networksetup listallnetworkservices | grep -v 'An asterisk' | xargs -I{} networksetup -setdnsservers '{}' 8.8.8.8 8.8.4.4" + sudo_command: sudo bash ./scripts/use_google_dns.sh } }, { description: "The curl utility is up to date or absent from the system." confidence: "required" - type: "regex match" - command: "curl --version" - expected_regex: ".*(command not found|7\\.48\\.0).*" - case_sensitive: "false" + tests: + [ + { + type: "regex match" + command: "curl --version" + command_pass: ".*(command not found|7\\.50\\.1).*" + case_sensitive: "false" + } + ] fix: { - command: "brew update ; brew install curl ; brew upgrade curl ; brew link curl --force" + command: + brew update ; brew install curl ; brew upgrade curl ; python ./scripts/set_path_precedence.py "/usr/local/bin" "/usr/bin" } undo: "brew unlink curl" }, @@ -686,10 +1061,15 @@ description: "FileVault file system encryption is enabled." confidence: "required" reference: "https://github.com/drduh/OS-X-Security-and-Privacy-Guide" - type: "regex match" - command: "fdesetup status -verbose" - expected_regex: "^.*FileVault is On.*$" - case_sensitive: "false" + tests: + [ + { + type: "regex match" + command: "fdesetup status -verbose" + command_pass: "^.*FileVault is On.*$" + case_sensitive: "false" + } + ] fix: { /* @@ -715,10 +1095,15 @@ description: "FileVault file system encryption is enabled at the root directory." confidence: "required" reference: "https://github.com/drduh/OS-X-Security-and-Privacy-Guide" - type: "regex match" - command: "fdesetup status -verbose" - expected_regex: "^.*device path \\=\\s+.*$" - case_sensitive: "false" + tests: + [ + { + type: "regex match" + command: "fdesetup status -verbose" + command_pass: "^.*device path \\=\\s+.*$" + case_sensitive: "false" + } + ] fix: { manual: "Sorry, no instructions are currently available to remediate this issue." @@ -729,18 +1114,52 @@ description: "The idle timer for screen saver activation is set to 10 minutes or less." confidence: "recommended" reference: "https://github.com/SummitRoute/osxlockdown/blob/58697f5162fe9e43df7dc9b6b94ffa34b0e11d4f/commands.yaml" - type: "regex match" - //This is a clever way for polling settings for multiple users from the current logged in user :-) - command: - UUID=`ioreg -rd1 -c IOPlatformExpertDevice | grep "IOPlatformUUID" | sed -e 's/^.*"\(.*\)"$/\1/'`; for i in $(find /Users -type d -maxdepth 1); do PREF=$i/Library/Preferences/ByHost/com.apple.screensaver.$UUID; if [ -e $PREF.plist ]; then TIMEOUT=$(defaults read $PREF.plist idleTime) && if [ $TIMEOUT -eq 0 ] || [ $TIMEOUT -gt 600 ]; then echo 1; fi; else echo 0; fi; done; - expected_regex: "^(0\n*)+$" //all zeroes - case_sensitive: "false" + tests: + [ + { + type: "regex match" + //This is a clever way for polling settings for multiple users from the current logged in user :-) + command: + UUID=`ioreg -rd1 -c IOPlatformExpertDevice | grep "IOPlatformUUID" | sed -e 's/^.*"\(.*\)"$/\1/'`; for i in $(find /Users -type d -maxdepth 1); do PREF=$i/Library/Preferences/ByHost/com.apple.screensaver.$UUID; if [ -e $PREF.plist ]; then TIMEOUT=$(defaults read $PREF.plist idleTime) && if [ $TIMEOUT -eq 0 ] || [ $TIMEOUT -gt 600 ]; then echo 1; fi; else echo 0; fi; done; + command_pass: "^(0\n*)+$" //all zeroes + case_sensitive: "false" + } + ] fix: { command: UUID=`ioreg -rd1 -c IOPlatformExpertDevice | grep "IOPlatformUUID" | sed -e 's/^.*"\(.*\)"$/\1/'`; for i in $(find /Users -type d -maxdepth 1); do PREF=$i/Library/Preferences/ByHost/com.apple.screensaver.$UUID; if [ -e $PREF.plist ]; then defaults -currentHost write $PREF.plist idleTime -int 600; fi; done } - }, + } + { + description: "System Integrity Protection (SIP) is enabled." + confidence: required + reference: "https://github.com/drduh/OS-X-Security-and-Privacy-Guide#system-integrity-protection" + tests: + [ + { + //SIP is not available for OS X before 10.11 + //TODO: not sure about 10.12 + type: "exact match" + command: is_el_capitan + command_pass: 0 + case_sensitive: false + } + { + type: "exact match" + command: "csrutil status" + command_pass: "System Integrity Protection status: enabled." + case_sensitive: false + } + ] + fix: + { + manual: + ''' + 1. SIP should be enabled by default on your El Capitan machine. You must boot into "Recovery OS" in order to use the "csrutil enable" command. See: https://derflounder.wordpress.com/2015/10/01/system-integrity-protection-adding-another-layer-to-apples-security-model/ + ''' + } + } /* ---- END SYSTEM SETTINGS ---- */ /* ---BEGIN SAFARI BROWSER SETTINGS--- */ @@ -749,10 +1168,15 @@ description: "The Safari application is currently closed." confidence: "required" reference: "https://developer.apple.com/legacy/library/documentation/Darwin/Reference/ManPages/man1/defaults.1.html" - type: "exact match" - command: "ps ax | grep -c '/Applications/Safari.app/Contents/MacOS/Safari'" - expected_stdout: "2" //a value of "3" means it's running -- the other 2 are `/bin/sh` and the `grep` command. - case_sensitive: "false" + tests: + [ + { + type: "exact match" + command: "ps ax | grep -c '/Applications/Safari.app/Contents/MacOS/Safari'" + command_pass: "2" //a value of "3" means it's running -- the other 2 are `/bin/sh` and the `grep` command. + case_sensitive: "false" + } + ] fix: { command: @@ -763,10 +1187,16 @@ //Safari->Preferences->AutoFill->Credit cards description: "Safari will not auto-fill credit card data." confidence: "recommended" - type: "exact match" - command: "defaults -currentHost read ~/Library/Preferences/com.apple.Safari AutoFillCreditCardData" - expected_stdout: "0" - case_sensitive: "false" + tests: + [ + { + type: "exact match" + command: "defaults -currentHost read ~/Library/Preferences/com.apple.Safari AutoFillCreditCardData" + command_pass: "0" + command_fail: "1" + case_sensitive: "false" + } + ] fix: { command: "defaults -currentHost write ~/Library/Preferences/com.apple.Safari AutoFillCreditCardData -bool false" @@ -776,10 +1206,16 @@ //Safari->Preferences->AutoFill->Using info from my Contacts card description: "Safari will not auto-fill your contact data." confidence: "recommended" - type: "exact match" - command: "defaults -currentHost read ~/Library/Preferences/com.apple.Safari AutoFillFromAddressBook" - expected_stdout: "0" - case_sensitive: "false" + tests: + [ + { + type: "exact match" + command: "defaults -currentHost read ~/Library/Preferences/com.apple.Safari AutoFillFromAddressBook" + command_pass: "0" + command_fail: "1" + case_sensitive: "false" + } + ] fix: { command: "defaults -currentHost write ~/Library/Preferences/com.apple.Safari AutoFillFromAddressBook -bool false" @@ -789,10 +1225,16 @@ //Safari->Preferences->AutoFill->Other forms description: "Safari will not auto-fill miscellaneous forms." confidence: "recommended" - type: "exact match" - command: "defaults -currentHost read ~/Library/Preferences/com.apple.Safari AutoFillMiscellaneousForms" - expected_stdout: "0" - case_sensitive: "false" + tests: + [ + { + type: "exact match" + command: "defaults -currentHost read ~/Library/Preferences/com.apple.Safari AutoFillMiscellaneousForms" + command_pass: "0" + command_fail: "1" + case_sensitive: "false" + } + ] fix: { command: "defaults -currentHost write ~/Library/Preferences/com.apple.Safari AutoFillMiscellaneousForms -bool false" @@ -802,10 +1244,16 @@ //Safari->Preferences->AutoFill->User names and passwords description: "Safari will not auto-fill usernames or passwords." confidence: "recommended" - type: "exact match" - command: "defaults -currentHost read ~/Library/Preferences/com.apple.Safari AutoFillPasswords" - expected_stdout: "0" - case_sensitive: "false" + tests: + [ + { + type: "exact match" + command: "defaults -currentHost read ~/Library/Preferences/com.apple.Safari AutoFillPasswords" + command_pass: "0" + command_fail: "1" + case_sensitive: "false" + } + ] fix: { command: "defaults -currentHost write ~/Library/Preferences/com.apple.Safari AutoFillPasswords -bool false" @@ -815,10 +1263,16 @@ //Safari->Preferences->General->Open "safe" files after downloading description: "Files downloaded in Safari are not automatically opened." confidence: "required" - type: "exact match" - command: "defaults -currentHost read ~/Library/Preferences/com.apple.Safari AutoOpenSafeDownloads" - expected_stdout: "0" - case_sensitive: "false" + tests: + [ + { + type: "exact match" + command: "defaults -currentHost read ~/Library/Preferences/com.apple.Safari AutoOpenSafeDownloads" + command_pass: "0" + command_fail: "1" + case_sensitive: "false" + } + ] fix: { command: "defaults -currentHost write ~/Library/Preferences/com.apple.Safari AutoOpenSafeDownloads -bool false" @@ -828,10 +1282,16 @@ //Safari->Preferences->Privacy->Cookies and website data->Always block description: "Cookies and local storage are always blocked in Safari." confidence: "recommended" - type: "exact match" - command: "defaults -currentHost read ~/Library/Preferences/com.apple.Safari BlockStoragePolicy" - expected_stdout: "0" - case_sensitive: "false" + tests: + [ + { + type: "exact match" + command: "defaults -currentHost read ~/Library/Preferences/com.apple.Safari BlockStoragePolicy" + command_pass: "0" + command_fail: "1" + case_sensitive: "false" + } + ] fix: { command: "defaults -currentHost write ~/Library/Preferences/com.apple.Safari BlockStoragePolicy -bool false" @@ -842,10 +1302,16 @@ //Note: Extensions are often a persistence mechanism for browser-based malware. description: "Safari extensions are disabled." confidence: "required" - type: "exact match" - command: "defaults -currentHost read ~/Library/Preferences/com.apple.Safari ExtensionsEnabled" - expected_stdout: "0" - case_sensitive: "false" + tests: + [ + { + type: "exact match" + command: "defaults -currentHost read ~/Library/Preferences/com.apple.Safari ExtensionsEnabled" + command_pass: "0" + command_fail: "1" + case_sensitive: "false" + } + ] fix: { command: "defaults -currentHost write ~/Library/Preferences/com.apple.Safari ExtensionsEnabled -bool false" @@ -856,10 +1322,16 @@ description: "The Safari web browser will warn when visiting known fraudulent websites." //I'm setting this to recommended for on the basis that there is like a privacy trade-off confidence: "recommended" - type: "exact match" - command: "defaults -currentHost read ~/Library/Preferences/com.apple.Safari WarnAboutFraudulentWebsites" - expected_stdout: "1" - case_sensitive: "false" + tests: + [ + { + type: "exact match" + command: "defaults -currentHost read ~/Library/Preferences/com.apple.Safari WarnAboutFraudulentWebsites" + command_pass: "1" + command_fail: "0" + case_sensitive: "false" + } + ] fix: { command: "defaults -currentHost write ~/Library/Preferences/com.apple.Safari WarnAboutFraudulentWebsites -bool true" @@ -868,12 +1340,18 @@ }, { //Safari->Preferences->Security->Web Content->Enable JavaScript - description: "JavaScript disabled in the Safari web browser." + description: "JavaScript is disabled in the Safari web browser." confidence: "recommended" - type: "exact match" - command: "defaults -currentHost read ~/Library/Preferences/com.apple.Safari com.apple.Safari.ContentPageGroupIdentifier.WebKit2JavaScriptEnabled" - expected_stdout: "0" - case_sensitive: "false" + tests: + [ + { + type: "exact match" + command: "defaults -currentHost read ~/Library/Preferences/com.apple.Safari com.apple.Safari.ContentPageGroupIdentifier.WebKit2JavaScriptEnabled" + command_pass: "0" + command_fail: "1" + case_sensitive: "false" + } + ] fix: { command: "defaults -currentHost write ~/Library/Preferences/com.apple.Safari com.apple.Safari.ContentPageGroupIdentifier.WebKit2JavaScriptEnabled -bool false" @@ -881,12 +1359,18 @@ undo: "defaults -currentHost write ~/Library/Preferences/com.apple.Safari com.apple.Safari.ContentPageGroupIdentifier.WebKit2JavaScriptEnabled -bool true" }, { - description: "JavaScript disabled in the Safari web browser (Legacy version)." + description: "JavaScript is disabled in the Safari web browser (Legacy version)." confidence: "recommended" - type: "exact match" - command: "defaults -currentHost read ~/Library/Preferences/com.apple.Safari WebKitJavaScriptEnabled" - expected_stdout: "0" - case_sensitive: "false" + tests: + [ + { + type: "exact match" + command: "defaults -currentHost read ~/Library/Preferences/com.apple.Safari WebKitJavaScriptEnabled" + command_pass: "0" + command_fail: "1" + case_sensitive: "false" + } + ] fix: { command: "defaults -currentHost write ~/Library/Preferences/com.apple.Safari WebKitJavaScriptEnabled -bool false" @@ -897,10 +1381,16 @@ //Safari->Preferences->Security->Web Content->Block pop-up windows description: "Pop-up windows are blocked in the Safari web browser." confidence: "required" - type: "exact match" - command: "defaults -currentHost read ~/Library/Preferences/com.apple.Safari com.apple.Safari.ContentPageGroupIdentifier.WebKit2JavaScriptCanOpenWindowsAutomatically" - expected_stdout: "0" - case_sensitive: "false" + tests: + [ + { + type: "exact match" + command: "defaults -currentHost read ~/Library/Preferences/com.apple.Safari com.apple.Safari.ContentPageGroupIdentifier.WebKit2JavaScriptCanOpenWindowsAutomatically" + command_pass: "0" + command_fail: "1" + case_sensitive: "false" + } + ] fix: { command: "defaults -currentHost write ~/Library/Preferences/com.apple.Safari com.apple.Safari.ContentPageGroupIdentifier.WebKit2JavaScriptCanOpenWindowsAutomatically -bool false" @@ -911,10 +1401,16 @@ //Safari->Preferences->Security->Web Content->Block pop-up windows description: "Pop-up windows are blocked in the Safari web browser (Legacy version)." confidence: "required" - type: "exact match" - command: "defaults -currentHost read ~/Library/Preferences/com.apple.Safari WebKitJavaScriptCanOpenWindowsAutomatically" - expected_stdout: "0" - case_sensitive: "false" + tests: + [ + { + type: "exact match" + command: "defaults -currentHost read ~/Library/Preferences/com.apple.Safari WebKitJavaScriptCanOpenWindowsAutomatically" + command_pass: "0" + command_fail: "1" + case_sensitive: "false" + } + ] fix: { command: "defaults -currentHost write ~/Library/Preferences/com.apple.Safari WebKitJavaScriptCanOpenWindowsAutomatically -bool false" @@ -925,10 +1421,16 @@ //Safari->Preferences->Security->Web Content->Allow WebGL description: "The WebGL plug-in is disabled in the Safari web browser." confidence: "recommended" - type: "exact match" - command: "defaults -currentHost read ~/Library/Preferences/com.apple.Safari com.apple.Safari.ContentPageGroupIdentifier.WebKit2WebGLEnabled" - expected_stdout: "0" - case_sensitive: "false" + tests: + [ + { + type: "exact match" + command: "defaults -currentHost read ~/Library/Preferences/com.apple.Safari com.apple.Safari.ContentPageGroupIdentifier.WebKit2WebGLEnabled" + command_pass: "0" + command_fail: "1" + case_sensitive: "false" + } + ] fix: { command: "defaults -currentHost write ~/Library/Preferences/com.apple.Safari com.apple.Safari.ContentPageGroupIdentifier.WebKit2WebGLEnabled -bool false" @@ -939,10 +1441,16 @@ //Safari->Preferences->Security->Internet plug-ins->Allow Plug-ins description: "Plug-ins are disabled in the Safari web browser." confidence: "recommended" - type: "exact match" - command: "defaults -currentHost read ~/Library/Preferences/com.apple.Safari com.apple.Safari.ContentPageGroupIdentifier.WebKit2PluginsEnabled" - expected_stdout: "0" - case_sensitive: "false" + tests: + [ + { + type: "exact match" + command: "defaults -currentHost read ~/Library/Preferences/com.apple.Safari com.apple.Safari.ContentPageGroupIdentifier.WebKit2PluginsEnabled" + command_pass: "0" + command_fail: "1" + case_sensitive: "false" + } + ] fix: { command: "defaults -currentHost write ~/Library/Preferences/com.apple.Safari com.apple.Safari.ContentPageGroupIdentifier.WebKit2PluginsEnabled -bool false" @@ -952,10 +1460,16 @@ { description: "Plug-ins are disabled in the Safari web browser (Legacy version)." confidence: "recommended" - type: "exact match" - command: "defaults -currentHost read ~/Library/Preferences/com.apple.Safari WebKitPluginsEnabled" - expected_stdout: "0" - case_sensitive: "false" + tests: + [ + { + type: "exact match" + command: "defaults -currentHost read ~/Library/Preferences/com.apple.Safari WebKitPluginsEnabled" + command_pass: "0" + command_fail: "1" + case_sensitive: "false" + } + ] fix: { command: "defaults -currentHost write ~/Library/Preferences/com.apple.Safari WebKitPluginsEnabled -bool false" @@ -966,10 +1480,15 @@ //Safari->Preferences->Security->Internet plug-ins->Plug-in Settings...->When visiting other websites description: "Plug-ins are blocked by default in the Safari web browser unless a site is explicitly added to a list of allowed sites." confidence: "required" - type: "exact match" - command: "defaults -currentHost read ~/Library/Preferences/com.apple.Safari PlugInFirstVisitPolicy" - expected_stdout: "PlugInPolicyBlock" - case_sensitive: "false" + tests: + [ + { + type: "exact match" + command: "defaults -currentHost read ~/Library/Preferences/com.apple.Safari PlugInFirstVisitPolicy" + command_pass: "PlugInPolicyBlock" + case_sensitive: "false" + } + ] fix: { command: "defaults -currentHost write ~/Library/Preferences/com.apple.Safari PlugInFirstVisitPolicy PlugInPolicyBlock" @@ -979,12 +1498,17 @@ //Safari->Preferences->Security->Internet plug-ins->Plug-in Settings...->Java->When visiting other websites->Block description: "The Java plug-in for Safari web browser is blocked unless a site is explicitly added to a list of allowed sites." confidence: "required" - type: "exact match" - //Note: dictionary values for PList fields are easier to handle with `PlistBuddy` instead of `defaults`. - command: - /usr/libexec/PlistBuddy -c "Print :ManagedPlugInPolicies:com.oracle.java.JavaAppletPlugin:PlugInFirstVisitPolicy" ~/Library/Preferences/com.apple.Safari.plist - expected_stdout: "PlugInPolicyBlock" - case_sensitive: "false" + tests: + [ + { + type: "exact match" + //Note: dictionary values for PList fields are easier to handle with `PlistBuddy` instead of `defaults`. + command: + /usr/libexec/PlistBuddy -c "Print :ManagedPlugInPolicies:com.oracle.java.JavaAppletPlugin:PlugInFirstVisitPolicy" ~/Library/Preferences/com.apple.Safari.plist + command_pass: "PlugInPolicyBlock" + case_sensitive: "false" + } + ] fix: { command: @@ -995,10 +1519,16 @@ //Safari->Preferences->Security->Internet plug-ins->Plug-in Settings...->Java description: "The Java plug-in is disabled in the Safari web browser." confidence: "required" - type: "exact match" - command: "defaults -currentHost read ~/Library/Preferences/com.apple.Safari com.apple.Safari.ContentPageGroupIdentifier.WebKit2JavaEnabled" - expected_stdout: "0" - case_sensitive: "false" + tests: + [ + { + type: "exact match" + command: "defaults -currentHost read ~/Library/Preferences/com.apple.Safari com.apple.Safari.ContentPageGroupIdentifier.WebKit2JavaEnabled" + command_pass: "0" + command_fail: "1" + case_sensitive: "false" + } + ] fix: { command: "defaults -currentHost write ~/Library/Preferences/com.apple.Safari com.apple.Safari.ContentPageGroupIdentifier.WebKit2JavaEnabled -bool false" @@ -1009,10 +1539,16 @@ //This appears to be an old method circa 2009 for disabling Java. See: http://alblue.bandlem.com/2009/05/disabling-java-in-webkit.html description: "The Java plug-in is disabled in the Safari web browser (Legacy version)." confidence: "required" - type: "exact match" - command: "defaults -currentHost read ~/Library/Preferences/com.apple.Safari WebKitJavaEnabled" - expected_stdout: "0" - case_sensitive: "false" + tests: + [ + { + type: "exact match" + command: "defaults -currentHost read ~/Library/Preferences/com.apple.Safari WebKitJavaEnabled" + command_pass: "0" + command_fail: "1" + case_sensitive: "false" + } + ] fix: { command: "defaults -currentHost write ~/Library/Preferences/com.apple.Safari WebKitJavaEnabled -bool false" @@ -1023,10 +1559,16 @@ //Safari->Develop->Treat SHA-1 Certificates as Insecure description: "The Safari web browser is configured to treat SHA-1 certificates as insecure." confidence: "recommended" - type: "exact match" - command: "defaults -currentHost read ~/Library/Preferences/com.apple.Safari TreatSHA1CertificatesAsInsecure" - expected_stdout: "1" - case_sensitive: "false" + tests: + [ + { + type: "exact match" + command: "defaults -currentHost read ~/Library/Preferences/com.apple.Safari TreatSHA1CertificatesAsInsecure" + command_pass: "1" + command_fail: "0" + case_sensitive: "false" + } + ] fix: { command: "defaults -currentHost write ~/Library/Preferences/com.apple.Safari TreatSHA1CertificatesAsInsecure -bool true" @@ -1037,10 +1579,16 @@ //Safari->Preferences->Search->Preload Top Hit in the background description: "The Safari web browser will not pre-load webpages that rank highly as search matches." confidence: "recommended" - type: "exact match" - command: "defaults -currentHost read ~/Library/Preferences/com.apple.Safari PreloadTopHit" - expected_stdout: "0" - case_sensitive: "false" + tests: + [ + { + type: "exact match" + command: "defaults -currentHost read ~/Library/Preferences/com.apple.Safari PreloadTopHit" + command_pass: "0" + command_fail: "1" + case_sensitive: "false" + } + ] fix: { command: "defaults -currentHost write ~/Library/Preferences/com.apple.Safari PreloadTopHit -bool false" @@ -1051,10 +1599,16 @@ //Safari->Preferences->Search->Search engine->Include search engine suggestions description: "The Safari web browser will not include search engine suggestions for text typed in the location bar." confidence: "required" - type: "exact match" - command: "defaults -currentHost read ~/Library/Preferences/com.apple.Safari SuppressSearchSuggestions" - expected_stdout: "1" - case_sensitive: "false" + tests: + [ + { + type: "exact match" + command: "defaults -currentHost read ~/Library/Preferences/com.apple.Safari SuppressSearchSuggestions" + command_pass: "1" + command_fail: "0" + case_sensitive: "false" + } + ] fix: { command: "defaults -currentHost write ~/Library/Preferences/com.apple.Safari SuppressSearchSuggestions -bool true" @@ -1065,10 +1619,16 @@ //Safari->Preferences->Search->Smart Search Field->Include Safari Suggestions description: "The Safari web browser's search suggestions are disabled." confidence: "required" - type: "exact match" - command: "defaults -currentHost read ~/Library/Preferences/com.apple.Safari UniversalSearchEnabled" - expected_stdout: "0" - case_sensitive: "false" + tests: + [ + { + type: "exact match" + command: "defaults -currentHost read ~/Library/Preferences/com.apple.Safari UniversalSearchEnabled" + command_pass: "0" + command_fail: "1" + case_sensitive: "false" + } + ] fix: { command: "defaults -currentHost write ~/Library/Preferences/com.apple.Safari UniversalSearchEnabled -bool false" @@ -1079,10 +1639,16 @@ //Safari->Preferences->Privacy->Website tracking->Ask websites not to track me description: "The Safari web browser uses the Do-Not-Track HTTP header." confidence: "recommended" - type: "exact match" - command: "defaults -currentHost read ~/Library/Preferences/com.apple.Safari SendDoNotTrackHTTPHeader" - expected_stdout: "1" - case_sensitive: "false" + tests: + [ + { + type: "exact match" + command: "defaults -currentHost read ~/Library/Preferences/com.apple.Safari SendDoNotTrackHTTPHeader" + command_pass: "1" + command_fail: "0" + case_sensitive: "false" + } + ] fix: { command: "defaults -currentHost write ~/Library/Preferences/com.apple.Safari SendDoNotTrackHTTPHeader -bool true" @@ -1092,10 +1658,16 @@ { description: "PDF viewing is disabled in the Safari web browser." confidence: "recommended" - type: "exact match" - command: "defaults -currentHost read ~/Library/Preferences/com.apple.Safari WebKitOmitPDFSupport" - expected_stdout: "1" - case_sensitive: "false" + tests: + [ + { + type: "exact match" + command: "defaults -currentHost read ~/Library/Preferences/com.apple.Safari WebKitOmitPDFSupport" + command_pass: "1" + command_fail: "0" + case_sensitive: "false" + } + ] fix: { command: "defaults -currentHost write ~/Library/Preferences/com.apple.Safari WebKitOmitPDFSupport -bool true" @@ -1105,12 +1677,18 @@ { //Safari->Preferences->Advanced->Smart Search Field->Show full website address //This might help prevent phishing attacks - description: "Full website addresses are disabled in the location bar of the Safari web browser." + description: "Full website addresses are displayed in the location bar of the Safari web browser." confidence: "required" - type: "exact match" - command: "defaults -currentHost read ~/Library/Preferences/com.apple.Safari ShowFullURLInSmartSearchField" - expected_stdout: "1" - case_sensitive: "false" + tests: + [ + { + type: "exact match" + command: "defaults -currentHost read ~/Library/Preferences/com.apple.Safari ShowFullURLInSmartSearchField" + command_pass: "1" + command_fail: "0" + case_sensitive: "false" + } + ] fix: { command: "defaults -currentHost write ~/Library/Preferences/com.apple.Safari ShowFullURLInSmartSearchField -bool true" @@ -1123,12 +1701,17 @@ { //Check if the Mail app is closed -- otherwise, it may override changes this app makes. description: "The Mail application is currently closed." - confidence: "required" + confidence: required reference: "https://developer.apple.com/legacy/library/documentation/Darwin/Reference/ManPages/man1/defaults.1.html" - type: "exact match" - command: "ps ax | grep -c '/Applications/Mail.app/Contents/MacOS/Mail'" - expected_stdout: "2" //a value of "3" means it's running -- the other 2 are `/bin/sh` and the `grep` command. - case_sensitive: "false" + tests: + [ + { + type: "exact match" + command: "ps ax | grep -c '/Applications/Mail.app/Contents/MacOS/Mail'" + command_pass: 2 //a value of "3" means it's running -- the other 2 are `/bin/sh` and the `grep` command. + case_sensitive: false + } + ] fix: { command: @@ -1138,13 +1721,24 @@ { //Mail->Preferences->Viewing->Load remote content in messages description: "Apple Mail does not automatically load remote content in e-mails." - confidence: "recommended" - type: "exact match" - //Either Apple Mail is not in use or remote content is disabled. I use "ls" here to resolve the "~" symbol to the fully qualified file path that "test" requires. - command: - REMOTELOAD=$(defaults read ~/Library/Preferences/com.apple.mail-shared DisableURLLoading | grep 1) ; if [ ! -e $(ls ~/Library/Preferences/com.apple.mail-shared.plist) ] || [ -n "$REMOTELOAD" ]; then echo 1; else echo 0; fi - expected_stdout: "1" - case_sensitive: "false" + confidence: recommended + tests: + [ + { + //If Apple Mail is not in use by the user, this test passes + type: "exact match" + command: apple_mail_in_use + command_pass: 0 + case_sensitive: false + } + { + type: "exact match" + command: "defaults read ~/Library/Preferences/com.apple.mail-shared DisableURLLoading" + command_pass: 1 + command_fail: 0 + case_sensitive: false + } + ] fix: { command: "defaults write ~/Library/Preferences/com.apple.mail-shared DisableURLLoading -bool true" @@ -1154,25 +1748,77 @@ { //Mail->Preferences->Junk Mail->Enable junk mail filtering AND When junk mail arrives: Move it to the Junk mailbox description: "Mail identified by Apple Mail as junk is sent to the Junk mailbox." - confidence: "recommended" - type: "exact match" - command: "defaults -currentHost read ~/Library/Containers/com.apple.mail/Data/Library/Preferences/com.apple.mail JunkMailBehavior" - expected_stdout: "2" - case_sensitive: "false" + confidence: recommended + tests: + [ + { + //If Apple Mail is not in use by the user, this test passes + type: "exact match" + command: apple_mail_in_use + command_pass: 0 + case_sensitive: false + } + { + type: "exact match" + command: "defaults -currentHost read ~/Library/Containers/com.apple.mail/Data/Library/Preferences/com.apple.mail JunkMailBehavior" + command_pass: 2 + case_sensitive: false + } + ] fix: { command: "defaults -currentHost write ~/Library/Containers/com.apple.mail/Data/Library/Preferences/com.apple.mail JunkMailBehavior -int 2" } }, + { + description: "GPGMail is in use." + confidence: recommended + tests: + [ + { + type: "exact match" + command: gpg_mail_in_use + command_pass: 1 + command_fail: 0 + case_sensitive: false + } + ] + fix: + { + manual: + ''' + 1. Visit https://gpgtools.org/ and install GPG Suite. This tool can be used to encrypted and sign emails sent to other PGP users. + ''' + } + } { //Mail->Preferences->GPGMail->Composing->Encrypt new messages by default description: "New e-mails composed in Apple Mail are encrypted by GPGMail if the receiver's PGP is present in the keychain." - confidence: "recommended" - type: "exact match" - command: - AUTOENCRYPT=$(defaults read ~/Library/Preferences/org.gpgtools.gpgmail EncryptNewEmailsByDefault | grep 1) ; if [ ! -e $(ls ~/Library/Preferences/org.gpgtools.gpgmail.plist) ] || [ -n "$AUTOENCRYPT" ]; then echo 1; else echo 0; fi - expected_stdout: "1" - case_sensitive: "false" + confidence: recommended + tests: + [ + { + //If Apple Mail is not in use by the user, this test passes + type: "exact match" + command: apple_mail_in_use + command_pass: 0 + case_sensitive: false + } + { + //If GPG Mail is not in use by the user, this test passes + type: "exact match" + command: gpg_mail_in_use + command_pass: 0 + case_sensitive: false + } + { + type: "exact match" + command: "defaults read ~/Library/Preferences/org.gpgtools.gpgmail EncryptNewEmailsByDefault" + command_pass: 1 + command_fail: 0 + case_sensitive: false + } + ] fix: { command: "defaults write ~/Library/Preferences/org.gpgtools.gpgmail.plist EncryptNewEmailsByDefault -bool true" @@ -1182,12 +1828,31 @@ { //Mail->Preferences->GPGMail->Composing->Encrypt drafts description: "New e-mails composed in Apple Mail and saved as drafts are encrypted by GPGMail." - confidence: "required" - type: "exact match" - command: - AUTOENCRYPTDRAFTS=$(defaults read ~/Library/Preferences/org.gpgtools.gpgmail OptionallyEncryptDrafts | grep 1) ; if [ ! -e $(ls ~/Library/Preferences/org.gpgtools.gpgmail.plist) ] || [ -n "$AUTOENCRYPTDRAFTS" ]; then echo 1; else echo 0; fi - expected_stdout: "1" - case_sensitive: "false" + confidence: required + tests: + [ + { + //If Apple Mail is not in use by the user, this test passes + type: "exact match" + command: apple_mail_in_use + command_pass: 0 + case_sensitive: false + } + { + //If GPG Mail is not in use by the user, this test passes + type: "exact match" + command: gpg_mail_in_use + command_pass: 0 + case_sensitive: false + } + { + type: "exact match" + command: "defaults read ~/Library/Preferences/org.gpgtools.gpgmail OptionallyEncryptDrafts" + command_pass: 1 + command_fail: 0 + case_sensitive: false + } + ] fix: { command: "defaults write ~/Library/Preferences/org.gpgtools.gpgmail.plist OptionallyEncryptDrafts -bool true" @@ -1197,12 +1862,31 @@ { //Mail->Preferences->GPGMail->Composing->Sign new messages by default description: "New e-mails composed in Apple Mail are signed by GPGMail." - confidence: "required" - type: "exact match" - command: - AUTOSIGN=$(defaults read ~/Library/Preferences/org.gpgtools.gpgmail SignNewEmailsByDefault | grep 1) ; if [ ! -e $(ls ~/Library/Preferences/org.gpgtools.gpgmail.plist) ] || [ -n "$AUTOSIGN" ]; then echo 1; else echo 0; fi - expected_stdout: "1" - case_sensitive: "false" + confidence: required + tests: + [ + { + //If Apple Mail is not in use by the user, this test passes + type: "exact match" + command: apple_mail_in_use + command_pass: 0 + case_sensitive: false + } + { + //If GPG Mail is not in use by the user, this test passes + type: "exact match" + command: gpg_mail_in_use + command_pass: 0 + case_sensitive: false + } + { + type: "exact match" + command: "defaults read ~/Library/Preferences/org.gpgtools.gpgmail SignNewEmailsByDefault" + command_pass: 1 + command_fail: 0 + case_sensitive: false + } + ] fix: { command: "defaults write ~/Library/Preferences/org.gpgtools.gpgmail.plist SignNewEmailsByDefault -bool true" @@ -1211,13 +1895,32 @@ }, { //Mail->Preferences->GPGMail->Updates->Automatically check for updates - description: "Apple Mail with automatically check for updates to GPGMail." - confidence: "required" - type: "exact match" - command: - AUTOCHECK=$(defaults read ~/Library/Preferences/org.gpgtools.gpgmail SUEnableAutomaticChecks | grep 1) ; if [ ! -e $(ls ~/Library/Preferences/org.gpgtools.gpgmail.plist) ] || [ -n "$AUTOCHECK" ]; then echo 1; else echo 0; fi - expected_stdout: "1" - case_sensitive: "false" + description: "Apple Mail automatically checks for updates to GPGMail." + confidence: required + tests: + [ + { + //If Apple Mail is not in use by the user, this test passes + type: "exact match" + command: apple_mail_in_use + command_pass: 0 + case_sensitive: false + } + { + //If GPG Mail is not in use by the user, this test passes + type: "exact match" + command: gpg_mail_in_use + command_pass: 0 + case_sensitive: false + } + { + type: "exact match" + command: "defaults read ~/Library/Preferences/org.gpgtools.gpgmail SUEnableAutomaticChecks" + command_pass: 1 + command_fail: 0 + case_sensitive: false + } + ] fix: { command: "defaults write ~/Library/Preferences/org.gpgtools.gpgmail.plist SUEnableAutomaticChecks -bool true" @@ -1231,10 +1934,21 @@ //Check if the Chrome app is closed -- otherwise, it may override changes this app makes. description: "The Google Chrome browser is currently closed." confidence: "required" - type: "exact match" - command: "ps ax | grep -c '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome'" - expected_stdout: "2" //a value of "3" means it's running -- the other 2 are `/bin/sh` and the `grep` command. - case_sensitive: "false" + tests: + [ + { + type: "exact match" + command: chrome_is_installed + command_pass: 0 + case_sensitive: false + }, + { + type: "exact match" + command: "ps ax | grep -c 'Google Chrome.app'" + command_pass: 2 //a value of "3" or higher means it's running -- the first 2 are `/bin/sh` and the `grep` command. + case_sensitive: false + } + ] fix: { command: @@ -1245,11 +1959,22 @@ //Chrome->Preferences->Show Advanced Settings->Privacy->Use a web service to help resolve navigation errors description: "All Google Chrome web browser profiles prevent information leakage through navigation errors." confidence: "recommended" - type: "regex match" - command: - if [ ! -e "/Applications/Google Chrome.app" ]; then echo "False"; else find ~/Library/Application\ Support/Google/Chrome -name "Preferences" -maxdepth 2 | xargs -I{} python ./scripts/chrome_defaults.py read '{}' alternate_error_pages.enabled ; fi - expected_regex: "^(False\n?)+$" - case_sensitive: "false" + tests: + [ + { + type: "exact match" + command: chrome_is_installed + command_pass: 0 + case_sensitive: false + }, + { + type: "regex match" + command: + find ~/Library/Application\ Support/Google/Chrome -name "Preferences" -maxdepth 2 | xargs -I{} python ./scripts/chrome_defaults.py read '{}' alternate_error_pages.enabled + command_pass: "^(False\n?)+$" + case_sensitive: "false" + } + ] fix: { command: @@ -1260,11 +1985,22 @@ //Chrome->Preferences->Show Advanced Settings->Privacy->Use a prediction service to help complete searches and URLs typed in the address bar or the app launcher description: "All Google Chrome web browser profiles prevent information leakage through URL suggestions." confidence: "required" - type: "regex match" - command: - if [ ! -e "/Applications/Google Chrome.app" ]; then echo "False"; else find ~/Library/Application\ Support/Google/Chrome -name "Preferences" -maxdepth 2 | xargs -I{} python ./scripts/chrome_defaults.py read '{}' search.suggest_enabled ; fi - expected_regex: "^(False\n?)+$" - case_sensitive: "false" + tests: + [ + { + type: "exact match" + command: chrome_is_installed + command_pass: 0 + case_sensitive: false + }, + { + type: "regex match" + command: + find ~/Library/Application\ Support/Google/Chrome -name "Preferences" -maxdepth 2 | xargs -I{} python ./scripts/chrome_defaults.py read '{}' search.suggest_enabled + command_pass: "^(False\n?)+$" + case_sensitive: "false" + } + ] fix: { command: @@ -1275,11 +2011,22 @@ //Chrome->Preferences->Show Advanced Settings->Privacy->Use a prediction service to load pages more quickly description: "All Google Chrome web browser profiles prevent information leakage through network prediction." confidence: "required" - type: "regex match" - command: - if [ ! -e "/Applications/Google Chrome.app" ]; then echo "2"; else find ~/Library/Application\ Support/Google/Chrome -name "Preferences" -maxdepth 2 | xargs -I{} python ./scripts/chrome_defaults.py read '{}' net.network_prediction_options ; fi - expected_regex: "^(2\n?)+$" - case_sensitive: "false" + tests: + [ + { + type: "exact match" + command: chrome_is_installed + command_pass: 0 + case_sensitive: false + }, + { + type: "regex match" + command: + find ~/Library/Application\ Support/Google/Chrome -name "Preferences" -maxdepth 2 | xargs -I{} python ./scripts/chrome_defaults.py read '{}' net.network_prediction_options + command_pass: "^(2\n?)+$" + case_sensitive: "false" + } + ] fix: { command: @@ -1288,13 +2035,24 @@ }, { //Chrome->Preferences->Show Advanced Settings->Privacy->Automatically report details of possible security incidents to Google - description: "All Google Chrome web browser profiles prevent information leakage through report security incidents to Google." + description: "All Google Chrome web browser profiles prevent information leakage by blocking security incidents reports to Google." confidence: "recommended" - type: "regex match" - command: - if [ ! -e "/Applications/Google Chrome.app" ]; then echo "False"; else find ~/Library/Application\ Support/Google/Chrome -name "Preferences" -maxdepth 2 | xargs -I{} python ./scripts/chrome_defaults.py read '{}' safebrowsing.extended_reporting_enabled ; fi - expected_regex: "^(False\n?)+$" - case_sensitive: "false" + tests: + [ + { + type: "exact match" + command: chrome_is_installed + command_pass: 0 + case_sensitive: false + }, + { + type: "regex match" + command: + find ~/Library/Application\ Support/Google/Chrome -name "Preferences" -maxdepth 2 | xargs -I{} python ./scripts/chrome_defaults.py read '{}' safebrowsing.extended_reporting_enabled + command_pass: "^(False\n?)+$" + case_sensitive: "false" + } + ] fix: { command: @@ -1307,11 +2065,22 @@ description: "All Google Chrome web browser profiles have Google Safe Browsing enabled." confidence: "recommended" reference: "https://en.wikipedia.org/wiki/Google_Safe_Browsing" - type: "regex match" - command: - if [ ! -e "/Applications/Google Chrome.app" ]; then echo "True"; else find ~/Library/Application\ Support/Google/Chrome -name "Preferences" -maxdepth 2 | xargs -I{} python ./scripts/chrome_defaults.py read '{}' safebrowsing.enabled ; fi - expected_regex: "^(True\n?)+$" - case_sensitive: "false" + tests: + [ + { + type: "exact match" + command: chrome_is_installed + command_pass: 0 + case_sensitive: false + }, + { + type: "regex match" + command: + find ~/Library/Application\ Support/Google/Chrome -name "Preferences" -maxdepth 2 | xargs -I{} python ./scripts/chrome_defaults.py read '{}' safebrowsing.enabled + command_pass: "^(True\n?)+$" + case_sensitive: "false" + } + ] fix: { command: @@ -1322,11 +2091,22 @@ //Chrome->Preferences->Show Advanced Settings->Privacy->Use a web service to help resolve spelling errors description: "All Google Chrome web browser profiles prevent information leakage through spell-checking network services." confidence: "recommended" - type: "regex match" - command: - if [ ! -e "/Applications/Google Chrome.app" ]; then echo "False"; else find ~/Library/Application\ Support/Google/Chrome -name "Preferences" -maxdepth 2 | xargs -I{} python ./scripts/chrome_defaults.py read '{}' spellcheck.use_spelling_service ; fi - expected_regex: "^(False\n?)+$" - case_sensitive: "false" + tests: + [ + { + type: "exact match" + command: chrome_is_installed + command_pass: 0 + case_sensitive: false + }, + { + type: "regex match" + command: + find ~/Library/Application\ Support/Google/Chrome -name "Preferences" -maxdepth 2 | xargs -I{} python ./scripts/chrome_defaults.py read '{}' spellcheck.use_spelling_service + command_pass: "^(False\n?)+$" + case_sensitive: "false" + } + ] fix: { command: @@ -1337,11 +2117,22 @@ //Chrome->Preferences->Show Advanced Settings->Privacy->Automatically send usage statistics and crash reports to Google description: "All Google Chrome web browser profiles prevent information leakage through reporting usage statistics to Google." confidence: "required" - type: "regex match" - command: - if [ ! -e "/Applications/Google Chrome.app" ]; then echo "False"; exit; fi; if [ -e "$(ls ~/Library/Application\ Support/Google/Chrome/Consent\ To\ Send\ Stats)" ]; then echo "True"; exit; fi ; echo $(python ./scripts/chrome_defaults.py read ~/Library/Application\ Support/Google/Chrome/Local\ State user_experience_metrics.reporting_enabled) - expected_regex: ".*False$" - case_sensitive: "false" + tests: + [ + { + type: "exact match" + command: chrome_is_installed + command_pass: 0 + case_sensitive: false + }, + { + type: "regex match" + command: + if [ -e "$(ls ~/Library/Application\ Support/Google/Chrome/Consent\ To\ Send\ Stats)" ]; then echo "True"; exit; fi ; echo $(python ./scripts/chrome_defaults.py read ~/Library/Application\ Support/Google/Chrome/Local\ State user_experience_metrics.reporting_enabled) + command_pass: ".*False$" + case_sensitive: "false" + } + ] fix: { command: @@ -1352,12 +2143,23 @@ //Chrome->Preferences->Show Advanced Settings->Privacy->Send a "Do Not Track" request with your browsing traffic description: "All Google Chrome web browser profiles use the Do-Not-Track HTTP header." confidence: "recommended" - type: "regex match" - //This check should short-circuit and match the regex if Chrome is not installed - command: - if [ ! -e "/Applications/Google Chrome.app" ]; then echo "True"; else find ~/Library/Application\ Support/Google/Chrome -name "Preferences" -maxdepth 2 | xargs -I{} python ./scripts/chrome_defaults.py read '{}' enable_do_not_track ; fi - expected_regex: "^(True\n?)+$" - case_sensitive: "false" + tests: + [ + { + type: "exact match" + command: chrome_is_installed + command_pass: 0 + case_sensitive: false + }, + { + type: "regex match" + //This check should short-circuit and match the regex if Chrome is not installed + command: + find ~/Library/Application\ Support/Google/Chrome -name "Preferences" -maxdepth 2 | xargs -I{} python ./scripts/chrome_defaults.py read '{}' enable_do_not_track + command_pass: "^(True\n?)+$" + case_sensitive: "false" + } + ] fix: { command: @@ -1368,12 +2170,23 @@ //Chrome->Preferences->Show Advanced Settings->Privacy->Content Settings->Pop-ups->Do not allow any site to show pop-ups (recommended) description: "All Google Chrome web browser profiles prevent pop-ups." confidence: "required" - type: "regex match" - command: - if [ ! -e "/Applications/Google Chrome.app" ]; then echo "The attribute 'profile.default_content_setting_values.popups' does not exist"; else find ~/Library/Application\ Support/Google/Chrome -name "Preferences" -maxdepth 2 | xargs -I{} python ./scripts/chrome_defaults.py read '{}' profile.default_content_setting_values.popups ; fi - expected_regex: - ^(The attribute 'profile.default_content_setting_values.popups' does not exist\n?)|(None\n?)+$ - case_sensitive: "false" + tests: + [ + { + type: "exact match" + command: chrome_is_installed + command_pass: 0 + case_sensitive: false + }, + { + type: "regex match" + command: + find ~/Library/Application\ Support/Google/Chrome -name "Preferences" -maxdepth 2 | xargs -I{} python ./scripts/chrome_defaults.py read '{}' profile.default_content_setting_values.popups + command_pass: + ^((The attribute 'profile.default_content_setting_values.popups' does not exist in '[^']+'\.\n?)|(None\n?))+$ + case_sensitive: "false" + } + ] fix: { command: @@ -1384,11 +2197,22 @@ //Chrome->Preferences->Show Advanced Settings->Privacy->Content Settings->Location->Do not allow any site to track your physical location description: "All Google Chrome web browser profiles prevent geolocation by websites." confidence: "recommended" - type: "regex match" - command: - if [ ! -e "/Applications/Google Chrome.app" ]; then echo "2"; else find ~/Library/Application\ Support/Google/Chrome -name "Preferences" -maxdepth 2 | xargs -I{} python ./scripts/chrome_defaults.py read '{}' profile.default_content_setting_values.geolocation ; fi - expected_regex: "^(2\n?)+$" - case_sensitive: "false" + tests: + [ + { + type: "exact match" + command: chrome_is_installed + command_pass: 0 + case_sensitive: false + }, + { + type: "regex match" + command: + find ~/Library/Application\ Support/Google/Chrome -name "Preferences" -maxdepth 2 | xargs -I{} python ./scripts/chrome_defaults.py read '{}' profile.default_content_setting_values.geolocation + command_pass: "^(2\n?)+$" + case_sensitive: "false" + } + ] fix: { command: @@ -1401,11 +2225,22 @@ description: "All Google Chrome web browser profiles block unsandboxed plug-in software." confidence: "recommended" reference: "http://superuser.com/questions/654595/adobe-flash-player-ppapi-vs-npapi-in-google-chrome" - type: "regex match" - command: - if [ ! -e "/Applications/Google Chrome.app" ]; then echo "2"; else find ~/Library/Application\ Support/Google/Chrome -name "Preferences" -maxdepth 2 | xargs -I{} python ./scripts/chrome_defaults.py read '{}' profile.default_content_setting_values.ppapi_broker ; fi - expected_regex: "^(2\n?)+$" - case_sensitive: "false" + tests: + [ + { + type: "exact match" + command: chrome_is_installed + command_pass: 0 + case_sensitive: false + }, + { + type: "regex match" + command: + find ~/Library/Application\ Support/Google/Chrome -name "Preferences" -maxdepth 2 | xargs -I{} python ./scripts/chrome_defaults.py read '{}' profile.default_content_setting_values.ppapi_broker + command_pass: "^(2\n?)+$" + case_sensitive: "false" + } + ] fix: { command: @@ -1416,11 +2251,22 @@ //Chrome->Preferences->Show Advanced Settings->Passwords and forms->Enable Autofill to fill out web forms in a single click description: "All Google Chrome web browser profiles prevent filling personal information into forms automatically." confidence: "required" - type: "regex match" - command: - if [ ! -e "/Applications/Google Chrome.app" ]; then echo "False"; else find ~/Library/Application\ Support/Google/Chrome -name "Preferences" -maxdepth 2 | xargs -I{} python ./scripts/chrome_defaults.py read '{}' autofill.enabled ; fi - expected_regex: "^(False\n?)+$" - case_sensitive: "false" + tests: + [ + { + type: "exact match" + command: chrome_is_installed + command_pass: 0 + case_sensitive: false + }, + { + type: "regex match" + command: + find ~/Library/Application\ Support/Google/Chrome -name "Preferences" -maxdepth 2 | xargs -I{} python ./scripts/chrome_defaults.py read '{}' autofill.enabled + command_pass: "^(False\n?)+$" + case_sensitive: "false" + } + ] fix: { command: @@ -1432,11 +2278,22 @@ //Chrome->Preferences->Show Advanced Settings->Passwords and forms->Offer to save your web passwords. description: "All Google Chrome web browser profiles have disabled Password Manager." confidence: "recommended" - type: "regex match" - command: - if [ ! -e "/Applications/Google Chrome.app" ]; then echo "False"; else find ~/Library/Application\ Support/Google/Chrome -name "Preferences" -maxdepth 2 | xargs -I{} python ./scripts/chrome_defaults.py read '{}' profile.password_manager_enabled ; fi - expected_regex: "^(False\n?)+$" - case_sensitive: "false" + tests: + [ + { + type: "exact match" + command: chrome_is_installed + command_pass: 0 + case_sensitive: false + }, + { + type: "regex match" + command: + find ~/Library/Application\ Support/Google/Chrome -name "Preferences" -maxdepth 2 | xargs -I{} python ./scripts/chrome_defaults.py read '{}' profile.password_manager_enabled + command_pass: "^(False\n?)+$" + case_sensitive: "false" + } + ] fix: { command: @@ -1447,11 +2304,22 @@ //Chrome->Preferences->Show Advanced Settings->Passwords and forms->Manage passwords->Auto Sign-In description: "All Google Chrome web browser profiles have disabled automatic sign-in for stored passwords." confidence: "required" - type: "regex match" - command: - if [ ! -e "/Applications/Google Chrome.app" ]; then echo "False"; else find ~/Library/Application\ Support/Google/Chrome -name "Preferences" -maxdepth 2 | xargs -I{} python ./scripts/chrome_defaults.py read '{}' credentials_enable_autosignin ; fi - expected_regex: "^(False\n?)+$" - case_sensitive: "false" + tests: + [ + { + type: "exact match" + command: chrome_is_installed + command_pass: 0 + case_sensitive: false + }, + { + type: "regex match" + command: + find ~/Library/Application\ Support/Google/Chrome -name "Preferences" -maxdepth 2 | xargs -I{} python ./scripts/chrome_defaults.py read '{}' credentials_enable_autosignin + command_pass: "^(False\n?)+$" + case_sensitive: "false" + } + ] fix: { command: @@ -1462,11 +2330,22 @@ //Chrome->Preferences->Show Advanced Settings->Google CloudPrint->Show notifications when new printers are detected on network description: "All Google Chrome web browser profiles have disabled Google CloudPrint." confidence: "required" - type: "regex match" - command: - if [ ! -e "/Applications/Google Chrome.app" ]; then echo "False"; else find ~/Library/Application\ Support/Google/Chrome -name "Preferences" -maxdepth 2 | xargs -I{} python ./scripts/chrome_defaults.py read '{}' local_discovery.notifications_enabled ; fi - expected_regex: "^(False\n?)+$" - case_sensitive: "false" + tests: + [ + { + type: "exact match" + command: chrome_is_installed + command_pass: 0 + case_sensitive: false + }, + { + type: "regex match" + command: + find ~/Library/Application\ Support/Google/Chrome -name "Preferences" -maxdepth 2 | xargs -I{} python ./scripts/chrome_defaults.py read '{}' local_discovery.notifications_enabled + command_pass: "^(False\n?)+$" + case_sensitive: "false" + } + ] fix: { command: @@ -1476,14 +2355,25 @@ { //Note: I'm not so clear on what 'clear_lso_data_enabled' does. Maybe it should typically be set to true? 'False' is the setting achieved when you disable Flash through the plugins GUI. //chrome://plugins/->Adobe Flash Player->Disable - description: "All Google Chrome web browser profiles have disabled Flash cookies." + description: "All Google Chrome web browser profiles block Flash cookies." confidence: "required" reference: "https://en.wikipedia.org/wiki/Local_shared_object" - type: "regex match" - command: - if [ ! -e "/Applications/Google Chrome.app" ]; then echo "False"; else find ~/Library/Application\ Support/Google/Chrome -name "Preferences" -maxdepth 2 | xargs -I{} python ./scripts/chrome_defaults.py read '{}' browser.clear_lso_data_enabled ; fi - expected_regex: "^(False\n?)+$" - case_sensitive: "false" + tests: + [ + { + type: "exact match" + command: chrome_is_installed + command_pass: 0 + case_sensitive: false + }, + { + type: "regex match" + command: + find ~/Library/Application\ Support/Google/Chrome -name "Preferences" -maxdepth 2 | xargs -I{} python ./scripts/chrome_defaults.py read '{}' browser.clear_lso_data_enabled + command_pass: "^(False\n?)+$" + case_sensitive: "false" + } + ] fix: { command: @@ -1495,11 +2385,22 @@ description: "All Google Chrome web browser profiles have disabled the Chrome Pepper Flash Player plug-in." confidence: "required" reference: "http://www.newtriks.com/2012/12/01/how-to-disable-the-chrome-pepper-flash-player/" - type: "regex match" - command: - if [ ! -e "/Applications/Google Chrome.app" ]; then echo "False"; else find ~/Library/Application\ Support/Google/Chrome -name "Preferences" -maxdepth 2 | xargs -I{} python ./scripts/chrome_defaults.py read '{}' browser.pepper_flash_settings_enabled ; fi - expected_regex: "^(False\n?)+$" - case_sensitive: "false" + tests: + [ + { + type: "exact match" + command: chrome_is_installed + command_pass: 0 + case_sensitive: false + }, + { + type: "regex match" + command: + find ~/Library/Application\ Support/Google/Chrome -name "Preferences" -maxdepth 2 | xargs -I{} python ./scripts/chrome_defaults.py read '{}' browser.pepper_flash_settings_enabled + command_pass: "^(False\n?)+$" + case_sensitive: "false" + } + ] fix: { command: @@ -1510,12 +2411,23 @@ //chrome://plugins/->Adobe Flash Player->Disable description: "All Google Chrome web browser profiles have disabled the Adobe Shockwave Flash plug-in." confidence: "required" - type: "regex match" - command: - if [ ! -e "/Applications/Google Chrome.app" ]; then echo "'enabled': False, 'name': 'Shockwave Flash'"; else find ~/Library/Application\ Support/Google/Chrome -name "Preferences" -maxdepth 2 | xargs -I{} python ./scripts/chrome_defaults.py read '{}' plugins.plugins_list ; fi - expected_regex: - ^(\[[^\[]+'enabled': False, 'name': 'Shockwave Flash'[^\]]+\]\n?)+$ - case_sensitive: "false" + tests: + [ + { + type: "exact match" + command: chrome_is_installed + command_pass: 0 + case_sensitive: false + }, + { + type: "regex match" + command: + find ~/Library/Application\ Support/Google/Chrome -name "Preferences" -maxdepth 2 | xargs -I{} python ./scripts/chrome_defaults.py read '{}' plugins.plugins_list + command_pass: + ^(\[[^\[]+'enabled': False, 'name': 'Shockwave Flash'[^\]]+\]\n?)+$ + case_sensitive: "false" + } + ] fix: { //To simplify syntax, most of this logic has been stored in the "chrome_flash.sh" script @@ -1527,12 +2439,23 @@ //chrome://plugins/->Adobe Flash Player->Disable description: "All Google Chrome web browser profiles have disabled the Adobe Flash Player plug-in." confidence: "required" - type: "regex match" - command: - if [ ! -e "/Applications/Google Chrome.app" ]; then echo "'enabled': False, 'name': 'Adobe Flash Player'"; else find ~/Library/Application\ Support/Google/Chrome -name "Preferences" -maxdepth 2 | xargs -I{} python ./scripts/chrome_defaults.py read '{}' plugins.plugins_list ; fi - expected_regex: - ^(\[[^\[]+'enabled': False, 'name': 'Adobe Flash Player'[^\]]+\]\n?)+$ - case_sensitive: "false" + tests: + [ + { + type: "exact match" + command: chrome_is_installed + command_pass: 0 + case_sensitive: false + }, + { + type: "regex match" + command: + find ~/Library/Application\ Support/Google/Chrome -name "Preferences" -maxdepth 2 | xargs -I{} python ./scripts/chrome_defaults.py read '{}' plugins.plugins_list + command_pass: + ^(\[[^\[]+'enabled': False, 'name': 'Adobe Flash Player'[^\]]+\]\n?)+$ + case_sensitive: "false" + } + ] fix: { //To simplify syntax, most of this logic has been stored in the "chrome_flash.sh" script @@ -1545,12 +2468,23 @@ description: "All Google Chrome web browser profiles have disabled the Native Client plug-in." confidence: "required" reference: "https://developer.chrome.com/native-client" - type: "regex match" - command: - if [ ! -e "/Applications/Google Chrome.app" ]; then echo "'enabled': False, 'name': 'Native Client'"; else find ~/Library/Application\ Support/Google/Chrome -name "Preferences" -maxdepth 2 | xargs -I{} python ./scripts/chrome_defaults.py read '{}' plugins.plugins_list ; fi - expected_regex: - ^(\[[^\[]+'enabled': False, 'name': 'Native Client'[^\]]+\]\n?)+$ - case_sensitive: "false" + tests: + [ + { + type: "exact match" + command: chrome_is_installed + command_pass: 0 + case_sensitive: false + }, + { + type: "regex match" + command: + find ~/Library/Application\ Support/Google/Chrome -name "Preferences" -maxdepth 2 | xargs -I{} python ./scripts/chrome_defaults.py read '{}' plugins.plugins_list + command_pass: + ^(\[[^\[]+'enabled': False, 'name': 'Native Client'[^\]]+\]\n?)+$ + case_sensitive: "false" + } + ] fix: { //To simplify syntax, most of this logic has been stored in the "chrome_nativeclient.sh" script @@ -1562,12 +2496,23 @@ //chrome://plugins/->Widevine Content Decryption Module->Disable description: "All Google Chrome web browser profiles have disabled the Widevine Content Decryption Module plug-in." confidence: "recommended" - type: "regex match" - command: - if [ ! -e "/Applications/Google Chrome.app" ]; then echo "'enabled': False, 'name': 'Widevine Content Decryption Module'"; else find ~/Library/Application\ Support/Google/Chrome -name "Preferences" -maxdepth 2 | xargs -I{} python ./scripts/chrome_defaults.py read '{}' plugins.plugins_list ; fi - expected_regex: - ^(\[[^\[]+'enabled': False, 'name': 'Widevine Content Decryption Module'[^\]]+\]\n?)+$ - case_sensitive: "false" + tests: + [ + { + type: "exact match" + command: chrome_is_installed + command_pass: 0 + case_sensitive: false + }, + { + type: "regex match" + command: + find ~/Library/Application\ Support/Google/Chrome -name "Preferences" -maxdepth 2 | xargs -I{} python ./scripts/chrome_defaults.py read '{}' plugins.plugins_list + command_pass: + ^(\[[^\[]+'enabled': False, 'name': 'Widevine Content Decryption Module'[^\]]+\]\n?)+$ + case_sensitive: "false" + } + ] fix: { //To simplify syntax, most of this logic has been stored in the "chrome_widevine.sh" script @@ -1579,12 +2524,23 @@ //chrome://extensions/->uBlock Origin description: "All Google Chrome web browser profiles have enabled the uBlock Origin extension." confidence: "recommended" - type: "exact match" - //This style of bash command basically prints "False" and exits any time it detects a problem in any Chrome profile, since we're looking for 100% compliance. We'll create an exception for the default System and Guest profiles, since these are not configurable through the GUI. - command: - if [ ! -e "/Applications/Google Chrome.app" ]; then echo "True" ; exit ; fi ; DISABLEREASONS=$(find ~/Library/Application\ Support/Google/Chrome -name "Preferences" -maxdepth 2 | xargs -I{} python ./scripts/chrome_defaults.py read '{}' extensions.settings.cjpalhdlnbpafiamejdnhcphjbkeiagm.disable_reasons | grep -v "does not exist" | grep -v "not found") ; if [[ -n $DISABLEREASONS ]] ; then echo "False" ; exit ; fi ; BADSTATE=$(find ~/Library/Application\ Support/Google/Chrome -name "Preferences" -maxdepth 2 | grep -v "Guest Profile" | grep -v "System Profile" | xargs -I{} python ./scripts/chrome_defaults.py read '{}' extensions.settings.cjpalhdlnbpafiamejdnhcphjbkeiagm.state | grep -v "1") ; if [[ -n $BADSTATE ]] ; then echo "False" ; fi ; echo "True" ; - expected_stdout: "True" - case_sensitive: "false" + tests: + [ + { + type: "exact match" + command: chrome_is_installed + command_pass: 0 + case_sensitive: false + }, + { + type: "exact match" + //This style of bash command basically prints "False" and exits any time it detects a problem in any Chrome profile, since we're looking for 100% compliance. We'll create an exception for the default System and Guest profiles, since these are not configurable through the GUI. + command: + DISABLEREASONS=$(find ~/Library/Application\ Support/Google/Chrome -name "Preferences" -maxdepth 2 | xargs -I{} python ./scripts/chrome_defaults.py read '{}' extensions.settings.cjpalhdlnbpafiamejdnhcphjbkeiagm.disable_reasons | grep -v "does not exist" | grep -v "not found") ; if [[ -n $DISABLEREASONS ]] ; then echo "False" ; exit ; fi ; BADSTATE=$(find ~/Library/Application\ Support/Google/Chrome -name "Preferences" -maxdepth 2 | grep -v "Guest Profile" | grep -v "System Profile" | xargs -I{} python ./scripts/chrome_defaults.py read '{}' extensions.settings.cjpalhdlnbpafiamejdnhcphjbkeiagm.state | grep -v "1") ; if [[ -n $BADSTATE ]] ; then echo "False" ; fi ; echo "True" ; + command_pass: "True" + case_sensitive: "false" + } + ] fix: { manual: @@ -1599,12 +2555,23 @@ //chrome://extensions/->Ghostery description: "All Google Chrome web browser profiles have enabled the Ghostery extension." confidence: "recommended" - type: "exact match" - //This style of bash command basically prints "False" and exits any time it detects a problem in any Chrome profile, since we're looking for 100% compliance. We'll create an exception for the default System and Guest profiles, since these are not configurable through the GUI. - command: - if [ ! -e "/Applications/Google Chrome.app" ]; then echo "True" ; exit ; fi ; DISABLEREASONS=$(find ~/Library/Application\ Support/Google/Chrome -name "Preferences" -maxdepth 2 | xargs -I{} python ./scripts/chrome_defaults.py read '{}' extensions.settings.mlomiejdfkolichcflejclcbmpeaniij.disable_reasons | grep -v "does not exist" | grep -v "not found") ; if [[ -n $DISABLEREASONS ]] ; then echo "False" ; exit ; fi ; BADSTATE=$(find ~/Library/Application\ Support/Google/Chrome -name "Preferences" -maxdepth 2 | grep -v "Guest Profile" | grep -v "System Profile" | xargs -I{} python ./scripts/chrome_defaults.py read '{}' extensions.settings.mlomiejdfkolichcflejclcbmpeaniij.state | grep -v "1") ; if [[ -n $BADSTATE ]] ; then echo "False" ; fi ; echo "True" ; - expected_stdout: "True" - case_sensitive: "false" + tests: + [ + { + type: "exact match" + command: chrome_is_installed + command_pass: 0 + case_sensitive: false + }, + { + type: "exact match" + //This style of bash command basically prints "False" and exits any time it detects a problem in any Chrome profile, since we're looking for 100% compliance. We'll create an exception for the default System and Guest profiles, since these are not configurable through the GUI. + command: + DISABLEREASONS=$(find ~/Library/Application\ Support/Google/Chrome -name "Preferences" -maxdepth 2 | xargs -I{} python ./scripts/chrome_defaults.py read '{}' extensions.settings.mlomiejdfkolichcflejclcbmpeaniij.disable_reasons | grep -v "does not exist" | grep -v "not found") ; if [[ -n $DISABLEREASONS ]] ; then echo "False" ; exit ; fi ; BADSTATE=$(find ~/Library/Application\ Support/Google/Chrome -name "Preferences" -maxdepth 2 | grep -v "Guest Profile" | grep -v "System Profile" | xargs -I{} python ./scripts/chrome_defaults.py read '{}' extensions.settings.mlomiejdfkolichcflejclcbmpeaniij.state | grep -v "1") ; if [[ -n $BADSTATE ]] ; then echo "False" ; fi ; echo "True" ; + command_pass: "True" + case_sensitive: "false" + } + ] fix: { manual: @@ -1619,12 +2586,23 @@ //chrome://extensions/->ScriptSafe description: "All Google Chrome web browser profiles have enabled the ScriptSafe extension." confidence: "experimental" - type: "exact match" - //This style of bash command basically prints "False" and exits any time it detects a problem in any Chrome profile, since we're looking for 100% compliance. We'll create an exception for the default System and Guest profiles, since these are not configurable through the GUI. - command: - if [ ! -e "/Applications/Google Chrome.app" ]; then echo "True" ; exit ; fi ; DISABLEREASONS=$(find ~/Library/Application\ Support/Google/Chrome -name "Preferences" -maxdepth 2 | xargs -I{} python ./scripts/chrome_defaults.py read '{}' extensions.settings.oiigbmnaadbkfbmpbfijlflahbdbdgdf.disable_reasons | grep -v "does not exist" | grep -v "not found") ; if [[ -n $DISABLEREASONS ]] ; then echo "False" ; exit ; fi ; BADSTATE=$(find ~/Library/Application\ Support/Google/Chrome -name "Preferences" -maxdepth 2 | grep -v "Guest Profile" | grep -v "System Profile" | xargs -I{} python ./scripts/chrome_defaults.py read '{}' extensions.settings.oiigbmnaadbkfbmpbfijlflahbdbdgdf.state | grep -v "1") ; if [[ -n $BADSTATE ]] ; then echo "False" ; fi ; echo "True" ; - expected_stdout: "True" - case_sensitive: "false" + tests: + [ + { + type: "exact match" + command: chrome_is_installed + command_pass: 0 + case_sensitive: false + }, + { + type: "exact match" + //This style of bash command basically prints "False" and exits any time it detects a problem in any Chrome profile, since we're looking for 100% compliance. We'll create an exception for the default System and Guest profiles, since these are not configurable through the GUI. + command: + DISABLEREASONS=$(find ~/Library/Application\ Support/Google/Chrome -name "Preferences" -maxdepth 2 | xargs -I{} python ./scripts/chrome_defaults.py read '{}' extensions.settings.oiigbmnaadbkfbmpbfijlflahbdbdgdf.disable_reasons | grep -v "does not exist" | grep -v "not found") ; if [[ -n $DISABLEREASONS ]] ; then echo "False" ; exit ; fi ; BADSTATE=$(find ~/Library/Application\ Support/Google/Chrome -name "Preferences" -maxdepth 2 | grep -v "Guest Profile" | grep -v "System Profile" | xargs -I{} python ./scripts/chrome_defaults.py read '{}' extensions.settings.oiigbmnaadbkfbmpbfijlflahbdbdgdf.state | grep -v "1") ; if [[ -n $BADSTATE ]] ; then echo "False" ; fi ; echo "True" ; + command_pass: "True" + case_sensitive: "false" + } + ] fix: { manual: @@ -1638,11 +2616,16 @@ { description: "Google Chrome is the default web browser." confidence: "recommended" - type: "exact match" - command: - VERSIONER_PERL_PREFER_32_BIT=true perl -MMac::InternetConfig -le 'print +(GetICHelper "http")[1]' - expected_stdout: "Google Chrome" - case_sensitive: "false" + tests: + [ + { + type: "exact match" + command: + VERSIONER_PERL_PREFER_32_BIT=true perl -MMac::InternetConfig -le 'print +(GetICHelper "http")[1]' + command_pass: "Google Chrome" + case_sensitive: "false" + } + ] fix: { manual: @@ -1657,19 +2640,120 @@ /* ----END GOOGLE CHROME SETTINGS---- */ + /* --- BEGIN COMMON MALWARE DETECTION --- */ + + { + description: "OSX/Keydnap malware is not present." + confidence: "required" + reference: "http://www.welivesecurity.com/2016/08/30/osxkeydnap-spreads-via-signed-transmission-application/" + tests: + [ + { + type: "exact match" + command: + if [ -e "/Applications/Transmission.app/Contents/Resources/License.rtf" ] ; then echo 1 ; else echo 0 ; fi + command_fail: 1 + case_sensitive: false + } + { + type: "exact match" + command: + if [ -e "/Volumes/Transmission/Transmission.app/Contents/Resources/License.rtf" ] ; then echo 1 ; else echo 0 ; fi + command_fail: 1 + case_sensitive: false + } + { + type: "exact match" + command: + if [ -e "$HOME/Library/Application Support/com.apple.iCloud.sync.daemon/icloudsyncd" ] ; then echo 1 ; else echo 0 ; fi + command_fail: 1 + case_sensitive: false + } + { + type: "exact match" + command: + if [ -e "$HOME/Library/Application Support/com.apple.iCloud.sync.daemon/process.id" ] ; then echo 1 ; else echo 0 ; fi + command_fail: 1 + case_sensitive: false + } + { + type: "exact match" + command: + if [ -e "$HOME/Library/LaunchAgents/com.apple.iCloud.sync.daemon.plist" ] ; then echo 1 ; else echo 0 ; fi + command_fail: 1 + case_sensitive: false + } + { + type: "exact match" + command: + if [ -e "/Library/Application Support/com.apple.iCloud.sync.daemon/" ] ; then echo 1 ; else echo 0 ; fi + command_fail: 1 + case_sensitive: false + } + { + type: "exact match" + command: + if [ -e "/Library/Application Support/com.apple.iCloud.sync.daemon/" ] ; then echo 1 ; else echo 0 ; fi + command_pass: 0 + command_fail: 1 + case_sensitive: false + } + ] + fix: + { + manual: + ''' + 1. One or more of the files associated with the OSX/Keydnap malware was found. Please report this to the authors of osx-config-check via GitHub (https://github.com/kristovatlas/osx-config-check) or Twitter (https://twitter.com/kristovatlas). + 2. Refer to this link: http://www.welivesecurity.com/2016/08/30/osxkeydnap-spreads-via-signed-transmission-application/ + ''' + } + } + + /* ---- END COMMON MALWARE DETECTION ---- */ + /* useful for debugging `sudo_command` { description: "Can read /private/var/root" confidence: "required" - type: "regex match" - command: "ls /private/var/root" - sudo_command: "sudo ls /private/var/root" - expected_regex: ".*Library.*" - case_sensitive: true + tests: + [ + { + type: "regex match" + command: "ls /private/var/root" + command_pass: ".*Library.*" + case_sensitive: "true" + }, + { + type: "regex match" + command: "sudo ls /private/var/root" + command_pass: ".*Library.*" + case_sensitive: "true" + } + ] fix: { manual: "" } } */ + /* useful for debugging api.sh + { + description: "DEBUG for api.sh" + confidence: "required" + tests: + [ + { + type: "exact match" + command: + echo $(homebrew_is_installed) + command_pass: "1" + case_sensitive: "false" + } + ] + fix: + { + manual: "blah" + } + } + */ ] diff --git a/osx-config.json b/osx-config.json index 4ed825b..5cb2031 100644 --- a/osx-config.json +++ b/osx-config.json @@ -1 +1 @@ -[{"_comment": "DO NOT EDIT THIS FILE. THIS WAS AUTOMATICALLY GENERATED BY THE hjson_to_json.py SCRIPT. INSTEAD, EDIT THE osx-config.hjson FILE."}, {"description": "The System Preferences application is currently closed.", "confidence": "required", "reference": "https://developer.apple.com/legacy/library/documentation/Darwin/Reference/ManPages/man1/defaults.1.html", "type": "exact match", "command": "ps ax | grep -c '/Applications/System Preferences.app/Contents/MacOS/System Preferences'", "expected_stdout": "2", "case_sensitive": "false", "fix": {"command": "killall \"System Preferences\" ; sleep 1"}}, {"description": "Current user is a non-admin account.", "confidence": "required", "type": "exact match", "command": "id -Gn | grep -c -w admin", "expected_stdout": "0", "case_sensitive": "false", "fix": {"manual": "1. For most of your work, you should be logged into a non-administrator account. If you've already set this up and you're just logged into your admin account in order to run this tool as prescribed, you can ignore this failed test.\n2. To create a new, non-admin user for most of your work: Open System Preferences.\n3. Select \"Users & Groups\".\n4. If necessary, click the lock icon in the lower left corner and provide your administrator credentials.\n5. Click the \"+\" to create a new user. Make sure the \"Allow user to administer this computer\" checkbox is un-checked for that user.\n6. You may also want to add your non-administrator user to a list of users who can use the \"sudo\" command within the Terminal application to briefly gain administrator-like credentials for special circumstances. See: http://osxdaily.com/2014/02/06/add-user-sudoers-file-mac/"}}, {"description": "The OSX application firewall is enabled (system-wide).", "confidence": "required", "reference": "https://github.com/drduh/OS-X-Security-and-Privacy-Guide", "type": "exact match", "command": "defaults -currentHost read /Library/Preferences/com.apple.alf globalstate", "expected_stdout": "1", "case_sensitive": "false", "fix": {"command": "defaults -currentHost write /Library/Preferences/com.apple.alf globalstate -bool true", "sudo_command": "sudo defaults -currentHost write /Library/Preferences/com.apple.alf globalstate -bool true"}}, {"description": "The OSX application firewall is enabled (current user only).", "confidence": "required", "reference": "https://github.com/drduh/OS-X-Security-and-Privacy-Guide", "type": "exact match", "command": "defaults -currentHost read ~/Library/Preferences/com.apple.alf globalstate", "expected_stdout": "1", "case_sensitive": "false", "fix": {"command": "defaults -currentHost write ~/Library/Preferences/com.apple.alf globalstate -bool true", "sudo_command": "sudo defaults -currentHost write ~/Library/Preferences/com.apple.alf globalstate -bool true"}}, {"description": "A password is required to wake the computer from sleep or screen saver (system-wide).", "confidence": "required", "reference": "https://github.com/SummitRoute/osxlockdown/blob/58697f5162fe9e43df7dc9b6b94ffa34b0e11d4f/commands.yaml", "type": "exact match", "command": "defaults read /Library/Preferences/com.apple.screensaver askForPassword", "sudo_command": "sudo defaults read /Library/Preferences/com.apple.screensaver askForPassword", "expected_stdout": "1", "case_sensitive": "false", "fix": {"command": "defaults write /Library/Preferences/com.apple.screensaver askForPassword -bool true", "sudo_command": "sudo defaults write /Library/Preferences/com.apple.screensaver askForPassword -bool true"}}, {"description": "A password is required to wake the computer from sleep or screen saver (current user only).", "confidence": "required", "reference": "https://github.com/SummitRoute/osxlockdown/blob/58697f5162fe9e43df7dc9b6b94ffa34b0e11d4f/commands.yaml", "type": "exact match", "command": "defaults read ~/Library/Preferences/com.apple.screensaver askForPassword", "expected_stdout": "1", "case_sensitive": "false", "fix": {"command": "defaults write ~/Library/Preferences/com.apple.screensaver askForPassword -bool true"}}, {"description": "There is no delay between starting the screen saver and locking the machine (system-wide).", "confidence": "required", "reference": "https://github.com/SummitRoute/osxlockdown/blob/58697f5162fe9e43df7dc9b6b94ffa34b0e11d4f/commands.yaml", "type": "exact match", "command": "defaults -currentHost read /Library/Preferences/com.apple.screensaver askForPasswordDelay", "sudo_command": "sudo defaults -currentHost read /Library/Preferences/com.apple.screensaver askForPasswordDelay", "expected_stdout": "0", "case_sensitive": "false", "fix": {"command": "defaults -currentHost write /Library/Preferences/com.apple.screensaver askForPasswordDelay -bool false", "sudo_command": "sudo defaults -currentHost write /Library/Preferences/com.apple.screensaver askForPasswordDelay -bool false"}, "undo": "defaults -currentHost write /Library/Preferences/com.apple.screensaver askForPasswordDelay -bool true"}, {"description": "There is no delay between starting the screen saver and locking the machine (current user only).", "confidence": "required", "reference": "https://github.com/SummitRoute/osxlockdown/blob/58697f5162fe9e43df7dc9b6b94ffa34b0e11d4f/commands.yaml", "type": "exact match", "command": "defaults -currentHost read ~/Library/Preferences/com.apple.screensaver askForPasswordDelay", "expected_stdout": "0", "case_sensitive": "false", "fix": {"command": "defaults -currentHost write ~/Library/Preferences/com.apple.screensaver askForPasswordDelay -bool false"}, "undo": "defaults -currentHost write ~/Library/Preferences/com.apple.screensaver askForPasswordDelay -bool true"}, {"description": "Logging is enabled for the operating system.", "confidence": "required", "reference": "https://github.com/drduh/OS-X-Security-and-Privacy-Guide", "type": "exact match", "command": "defaults -currentHost read /Library/Preferences/com.apple.alf loggingenabled", "expected_stdout": "1", "case_sensitive": "false", "fix": {"command": "defaults -currentHost write /Library/Preferences/com.apple.alf loggingenabled -bool true", "sudo_command": "sudo defaults -currentHost write /Library/Preferences/com.apple.alf loggingenabled -bool true"}}, {"description": "Homebrew analytics are disabled.", "confidence": "required", "reference": "https://github.com/Homebrew/brew/blob/master/share/doc/homebrew/Analytics.md", "type": "exact match", "command": "[[ -n $HOMEBREW_NO_ANALYTICS ]] && echo 1 || echo 0", "expected_stdout": "1", "case_sensitive": "false", "fix": {"command": "grep -q 'export HOMEBREW_NO_ANALYTICS=1' ~/.profile || echo 'export HOMEBREW_NO_ANALYTICS=1' >> ~/.profile ; source ~/.profile", "manual": "1. In order for the automatic fix to be applied, you must logout of the current user and log back in. Sorry for the inconvenience!"}}, {"description": "Stealth mode is enabled for OSX: Computer does not respond to ICMP ping requests or connection attempts from a closed TCP/UDP port. (system-wide)", "confidence": "recommended", "reference": "https://github.com/drduh/OS-X-Security-and-Privacy-Guide", "type": "exact match", "command": "defaults -currentHost read /Library/Preferences/com.apple.alf stealthenabled", "expected_stdout": "1", "case_sensitive": "false", "fix": {"command": "defaults write /Library/Preferences/com.apple.alf stealthenabled -bool true", "sudo_command": "sudo defaults write /Library/Preferences/com.apple.alf stealthenabled -bool true"}, "undo": "sudo defaults write /Library/Preferences/com.apple.alf stealthenabled -bool false"}, {"description": "Stealth mode is enabled for OSX: Computer does not respond to ICMP ping requests or connection attempts from a closed TCP/UDP port. (current user only)", "confidence": "recommended", "reference": "https://github.com/drduh/OS-X-Security-and-Privacy-Guide", "type": "exact match", "command": "defaults -currentHost read ~/Library/Preferences/com.apple.alf stealthenabled", "expected_stdout": "1", "case_sensitive": "false", "fix": {"command": "defaults write ~/Library/Preferences/com.apple.alf stealthenabled -bool true", "sudo_command": "sudo defaults write /Library/Preferences/com.apple.alf stealthenabled -bool true"}, "undo": "defaults write ~/Library/Preferences/com.apple.alf stealthenabled -bool false"}, {"description": "Automatic whitelisting of Apple-signed applications for firewall is disabled (system-wide).", "confidence": "required", "reference": "https://github.com/drduh/OS-X-Security-and-Privacy-Guide", "type": "exact match", "command": "defaults -currentHost read /Library/Preferences/com.apple.alf allowsignedenabled", "expected_stdout": "0", "case_sensitive": "false", "fix": {"command": "defaults -currentHost write /Library/Preferences/com.apple.alf allowsignedenabled -bool false", "sudo_command": "sudo defaults -currentHost write /Library/Preferences/com.apple.alf allowsignedenabled -bool false"}, "undo": "sudo defaults -currentHost write /Library/Preferences/com.apple.alf allowsignedenabled -bool true"}, {"description": "Automatic whitelisting of Apple-signed applications for firewall is disabled (current user only).", "confidence": "required", "reference": "https://github.com/drduh/OS-X-Security-and-Privacy-Guide", "type": "exact match", "command": "defaults -currentHost read ~/Library/Preferences/com.apple.alf allowsignedenabled", "expected_stdout": "0", "case_sensitive": "false", "fix": {"command": "defaults -currentHost write ~/Library/Preferences/com.apple.alf allowsignedenabled -bool false"}, "undo": "sudo defaults -currentHost write /Library/Preferences/com.apple.alf allowsignedenabled -bool true"}, {"description": "Captive portal for connecting to new networks is disabled to prevent MITM attacks.", "confidence": "required", "reference": "https://github.com/drduh/OS-X-Security-and-Privacy-Guide", "type": "exact match", "command": "defaults -currentHost read /Library/Preferences/SystemConfiguration/com.apple.captive.control Active", "expected_stdout": "0", "case_sensitive": "false", "fix": {"command": "defaults -currentHost write /Library/Preferences/SystemConfiguration/com.apple.captive.control Active -bool false", "sudo_command": "sudo defaults -currentHost write /Library/Preferences/SystemConfiguration/com.apple.captive.control Active -bool false"}, "undo": "sudo defaults -currentHost write /Library/Preferences/SystemConfiguration/com.apple.captive.control Active -bool true"}, {"description": "OpenSSL is up-to-date.", "confidence": "required", "reference": "https://github.com/drduh/OS-X-Security-and-Privacy-Guide", "type": "exact match", "command": "openssl version", "expected_stdout": "OpenSSL 1.0.2h 3 May 2016", "case_sensitive": "false", "fix": {"command": "brew update ; brew install openssl ; brew upgrade openssl ; brew link openssl --force ; mv /usr/bin/openssl /usr/bin/openssl-apple", "sudo_command": "brew update ; brew install openssl ; brew upgrade openssl ; brew link openssl --force ; sudo mv /usr/bin/openssl /usr/bin/openssl-apple"}, "undo": "sudo mv /usr/bin/openssl-apple /usr/bin/openssl ; brew unlink openssl"}, {"description": "Hidden files are displayed in Finder.", "confidence": "recommended", "reference": "http://lifehacker.com/the-best-hidden-settings-you-can-unlock-with-os-xs-ter-1476627111", "type": "exact match", "command": "defaults -currentHost read /Library/Preferences/SystemConfiguration/com.apple.finder AppleShowAllFiles", "expected_stdout": "1", "case_sensitive": "false", "fix": {"command": "defaults -currentHost write /Library/Preferences/SystemConfiguration/com.apple.finder AppleShowAllFiles -bool true && killall Dock", "sudo_command": "sudo defaults -currentHost write /Library/Preferences/SystemConfiguration/com.apple.finder AppleShowAllFiles -bool true && killall Dock"}, "undo": "defaults -currentHost write /Library/Preferences/SystemConfiguration/com.apple.finder AppleShowAllFiles -bool false && killall Dock"}, {"description": "All application software is currently up to date.", "confidence": "required", "reference": "https://github.com/SummitRoute/osxlockdown/", "type": "exact match", "command": "LASTUPDATE=$(defaults read /Library/Preferences/com.apple.SoftwareUpdate | grep LastSuccessfulDate | sed -e 's@^.* \"\\([0-9\\\\-]*\\) .*$@\\1@'); if [ \"$LASTUPDATE\" = \"$(date +%Y-%m-%d)\" ];then echo 1 && exit; fi; exit 0 && exit", "expected_stdout": "1", "case_sensitive": "false", "fix": {"command": "softwareupdate -i -a", "sudo_command": "sudo softwareupdate -i -a"}}, {"description": "Automatic check for software updates is enabled.", "confidence": "required", "reference": "https://github.com/SummitRoute/osxlockdown/", "type": "exact match", "command": "softwareupdate --schedule | grep 'Automatic check is on'", "sudo_command": "sudo softwareupdate --schedule | grep 'Automatic check is on'", "expected_stdout": "Automatic check is on", "case_sensitive": "false", "fix": {"command": "softwareupdate --schedule on", "sudo_command": "sudo softwareupdate --schedule on"}}, {"description": "GateKeeper protection against untrusted applications is enabled.", "confidence": "required", "type": "exact match", "command": "spctl --status | grep 'assessments enabled'", "expected_stdout": "assessments enabled", "case_sensitive": "false", "fix": {"command": "spctl --master-enable", "sudo_command": "sudo spctl --master-enable"}, "undo": "sudo spctl --master-disable"}, {"description": "Bluetooth is disabled.", "confidence": "experimental", "type": "exact match", "command": "defaults read /Library/Preferences/com.apple.Bluetooth ControllerPowerState", "sudo_command": "sudo defaults read /Library/Preferences/com.apple.Bluetooth ControllerPowerState", "expected_stdout": "0", "case_sensitive": "false", "fix": {"command": "defaults write /Library/Preferences/com.apple.Bluetooth ControllerPowerState -bool false; killall -HUP blued", "sudo_command": "sudo defaults write /Library/Preferences/com.apple.Bluetooth ControllerPowerState -bool false; sudo killall -HUP blued"}, "undo": "defaults write /Library/Preferences/com.apple.Bluetooth ControllerPowerState -bool true; killall -HUP blued"}, {"description": "The infrared receiver is disabled.", "confidence": "required", "type": "exact match", "command": "defaults read /Library/Preferences/com.apple.driver.AppleIRController DeviceEnabled", "sudo_command": "sudo defaults read /Library/Preferences/com.apple.driver.AppleIRController DeviceEnabled", "expected_stdout": "0", "case_sensitive": "false", "fix": {"command": "defaults write /Library/Preferences/com.apple.driver.AppleIRController DeviceEnabled -bool false", "sudo_command": "sudo defaults write /Library/Preferences/com.apple.driver.AppleIRController DeviceEnabled -bool false"}, "undo": "defaults write /Library/Preferences/com.apple.driver.AppleIRController DeviceEnabled -bool true"}, {"description": "AirDrop file sharing is disabled.", "confidence": "required", "type": "exact match", "command": "defaults read com.apple.NetworkBrowser DisableAirDrop", "sudo_command": "sudo defaults read com.apple.NetworkBrowser DisableAirDrop", "expected_stdout": "1", "case_sensitive": "false", "fix": {"command": "defaults write /Library/Preferences/com.apple.NetworkBrowser DisableAirDrop -bool true", "sudo_command": "sudo defaults write /Library/Preferences/com.apple.NetworkBrowser DisableAirDrop -bool true"}, "undo": "defaults write /Library/Preferences/com.apple.NetworkBrowser DisableAirDrop -bool false"}, {"description": "File sharing is disabled.", "confidence": "recommended", "reference": "https://github.com/SummitRoute/osxlockdown/blob/58697f5162fe9e43df7dc9b6b94ffa34b0e11d4f/commands.yaml", "type": "exact match", "command": "if [ -n \"$(launchctl list | egrep AppleFileServer)\" ]; then exit 1; fi; if [ -n \"$(grep -i array /Library/Preferences/SystemConfiguration/com.apple.smb.server.plist)\" ]; then echo 1; exit; fi; echo 0; exit", "expected_stdout": "0", "case_sensitive": "false", "fix": {"command": "launchctl unload -w /System/Library/LaunchDaemons/com.apple.AppleFileServer.plist; launchctl unload -w /System/Library/LaunchDaemons/com.apple.smbd.plist"}}, {"description": "Printer sharing is disabled.", "confidence": "required", "reference": "https://github.com/SummitRoute/osxlockdown/blob/58697f5162fe9e43df7dc9b6b94ffa34b0e11d4f/commands.yaml", "type": "exact match", "command": "if [ -n \"$(system_profiler SPPrintersDataType | grep Shared | grep Yes)\" ]; then echo 1; exit; fi; if [ -n \"$(system_profiler SPPrintersDataType | grep 'System Printer Sharing: Yes')\" ]; then echo 1; exit; fi; echo 0; exit", "expected_stdout": "0", "case_sensitive": "false", "fix": {"command": "cupsctl --no-share-printers"}}, {"description": "Remote login is disabled.", "confidence": "required", "type": "exact match", "command": "systemsetup -getremotelogin", "sudo_command": "sudo systemsetup -getremotelogin", "expected_stdout": "Remote Login: Off", "case_sensitive": "false", "fix": {"command": "systemsetup -f -setremotelogin off", "sudo_command": "sudo systemsetup -f -setremotelogin off"}, "undo": "sudo systemsetup -f -setremotelogin on"}, {"description": "Remote Management is disabled.", "confidence": "required", "type": "exact match", "command": "if [ -n \"$(ps -ef | egrep \"/System/Library/CoreServices/RemoteManagement/ARDAgent.app/Contents/MacOS/[A]RDAgent\")\" ]; then echo 1; exit; fi; echo 0; exit", "expected_stdout": "0", "case_sensitive": "false", "fix": {"command": "/System/Library/CoreServices/RemoteManagement/ARDAgent.app/Contents/Resources/kickstart -deactivate -stop", "sudo_command": "sudo /System/Library/CoreServices/RemoteManagement/ARDAgent.app/Contents/Resources/kickstart -deactivate -stop"}}, {"description": "Remote Apple events are disabled.", "confidence": "required", "reference": "https://github.com/SummitRoute/osxlockdown/blob/58697f5162fe9e43df7dc9b6b94ffa34b0e11d4f/commands.yaml", "type": "exact match", "command": "systemsetup -getremoteappleevents", "sudo_command": "sudo systemsetup -getremoteappleevents", "expected_stdout": "Remote Apple Events: Off", "case_sensitive": "false", "fix": {"command": "systemsetup -setremoteappleevents off", "sudo_command": "systemsetup -setremoteappleevents off"}, "undo": "sudo systemsetup -setremoteappleevents on"}, {"description": "Internet Sharing is disabled on all network interfaces.", "confidence": "required", "reference": "https://github.com/SummitRoute/osxlockdown/blob/58697f5162fe9e43df7dc9b6b94ffa34b0e11d4f/commands.yaml", "type": "exact match", "command": "defaults read /Library/Preferences/SystemConfiguration/com.apple.nat NAT | grep -c 'Enabled = 1'", "expected_stdout": "0", "case_sensitive": "false", "fix": {"command": "defaults write /Library/Preferences/SystemConfiguration/com.apple.nat NAT -dict-add Enabled -bool false", "sudo_command": "sudo defaults write /Library/Preferences/SystemConfiguration/com.apple.nat NAT -dict-add Enabled -bool false"}}, {"description": "Wake on Network Access feature is disabled.", "confidence": "required", "type": "exact match", "command": "systemsetup getwakeonnetworkaccess", "sudo_command": "sudo systemsetup getwakeonnetworkaccess", "expected_stdout": "Wake On Network Access: Off", "case_sensitive": "false", "fix": {"command": "systemsetup -setwakeonnetworkaccess off", "sudo_command": "sudo systemsetup -setwakeonnetworkaccess off"}, "undo": "sudo systemsetup -setwakeonnetworkaccess on"}, {"description": "Automatic setting of time and date is disabled.", "confidence": "recommended", "type": "exact match", "command": "systemsetup getusingnetworktime", "sudo_command": "sudo systemsetup getusingnetworktime", "expected_stdout": "Network Time: Off", "case_sensitive": "false", "fix": {"command": "systemsetup setusingnetworktime off", "sudo_command": "sudo systemsetup setusingnetworktime off"}, "undo": "sudo systemsetup setusingnetworktime on"}, {"description": "IPv6 is disabled on all network interfaces.", "confidence": "recommended", "reference": "https://github.com/SummitRoute/osxlockdown/blob/58697f5162fe9e43df7dc9b6b94ffa34b0e11d4f/commands.yaml", "type": "exact match", "command": "networksetup -listallnetworkservices | while read i; do SUPPORT=$(networksetup -getinfo \"$i\" | grep \"IPv6: Automatic\") && if [ -n \"$SUPPORT\" ]; then echo 1; fi; done; echo 0; exit", "expected_stdout": "0", "case_sensitive": "false", "fix": {"command": "networksetup -listallnetworkservices | while read i; do SUPPORT=$(networksetup -getinfo \"$i\" | grep \"IPv6: Automatic\") && if [ -n \"$SUPPORT\" ]; then networksetup -setv6off \"$i\"; fi; done;"}}, {"description": "An administrator password is required to change system-wide preferences.", "confidence": "required", "reference": "https://github.com/SummitRoute/osxlockdown/blob/58697f5162fe9e43df7dc9b6b94ffa34b0e11d4f/commands.yaml", "type": "exact match", "command": "if [ -n \"$(security authorizationdb read system.preferences 2> /dev/null | grep -A1 shared | grep -E '(true|false)' | grep 'false')\" ]; then echo 0; else echo 1; fi", "expected_stdout": "0", "case_sensitive": "false", "fix": {"command": "security authorizationdb read system.preferences > /tmp/system.preferences.plist &&/usr/libexec/PlistBuddy -c \"Set :shared false\" /tmp/system.preferences.plist && security authorizationdb write system.preferences < /tmp/system.preferences.plist"}}, {"description": "Documents are not stored to iCloud Drive by default. (May be mistaken if iCloud is disabled)", "confidence": "required", "reference": "http://mjtsai.com/blog/2014/10/26/yosemite-uploads-unsaved-documents-and-recent-addresses-to-icloud/", "type": "exact match", "command": "defaults read NSGlobalDomain NSDocumentSaveNewDocumentsToCloud", "expected_stdout": "0", "case_sensitive": "false", "fix": {"command": "defaults write NSGlobalDomain NSDocumentSaveNewDocumentsToCloud -bool false"}, "undo": "defaults write NSGlobalDomain NSDocumentSaveNewDocumentsToCloud -bool true"}, {"description": "The File Vault key is destroyed when going to standby mode.", "confidence": "experimental", "reference": "https://github.com/drduh/OS-X-Security-and-Privacy-Guide", "type": "regex match", "command": "pmset -g", "expected_regex": ".*destroyfvkeyonstandby\\s+1.*", "case_sensitive": "false", "fix": {"command": "pmset -a destroyfvkeyonstandby 1", "sudo_command": "sudo pmset -a destroyfvkeyonstandby 1"}}, {"description": "The system will store a copy of memory to persistent storage, and will remove power to memory.", "confidence": "recommended", "reference": "https://github.com/drduh/OS-X-Security-and-Privacy-Guide", "type": "regex match", "command": "pmset -g", "expected_regex": ".*hibernatemode\\s+25.*", "case_sensitive": "false", "fix": {"command": "pmset -a hibernatemode 25", "sudo_command": "sudo pmset -a hibernatemode 25"}}, {"description": "git is up to date or is not installed", "confidence": "required", "type": "regex match", "command": "git --version", "expected_regex": ".*(command not found|2\\.8\\.2).*", "case_sensitive": "false", "fix": {"command": "brew update && brew install git && brew upgrade git && mv /usr/bin/git /usr/bin/git-apple", "sudo_command": "brew update && brew install git && brew upgrade git && sudo mv /usr/bin/git /usr/bin/git-apple"}}, {"description": "Apple Push Notifications are disabled.", "confidence": "recommended", "reference": "https://github.com/drduh/OS-X-Security-and-Privacy-Guide", "type": "regex match", "command": "launchctl list", "sudo_command": "sudo launchctl list", "expected_regex": "^((?!com\\.apple\\.apsd).)*$", "case_sensitive": "false", "fix": {"command": "launchctl unload -w /System/Library/LaunchDaemons/com.apple.apsd.plist", "sudo_command": "sudo launchctl unload -w /System/Library/LaunchDaemons/com.apple.apsd.plist"}, "undo": "sudo launchctl load -w /System/Library/LaunchDaemons/com.apple.apsd.plist"}, {"description": "Google DNS servers are used by default on all network interfaces.", "confidence": "recommended", "type": "regex match", "command": "networksetup listallnetworkservices | grep -v 'An asterisk' | xargs -I{} networksetup -getdnsservers '{}' ", "expected_regex": "^(8\\.8\\.8\\.8\\n8\\.8\\.4\\.4\n*)+$", "case_sensitive": "false", "fix": {"command": "networksetup listallnetworkservices | grep -v 'An asterisk' | xargs -I{} networksetup -setdnsservers '{}' 8.8.8.8 8.8.4.4"}}, {"description": "The curl utility is up to date or absent from the system.", "confidence": "required", "type": "regex match", "command": "curl --version", "expected_regex": ".*(command not found|7\\.48\\.0).*", "case_sensitive": "false", "fix": {"command": "brew update ; brew install curl ; brew upgrade curl ; brew link curl --force"}, "undo": "brew unlink curl"}, {"description": "FileVault file system encryption is enabled.", "confidence": "required", "reference": "https://github.com/drduh/OS-X-Security-and-Privacy-Guide", "type": "regex match", "command": "fdesetup status -verbose", "expected_regex": "^.*FileVault is On.*$", "case_sensitive": "false", "fix": {"manual": "1. Open System Preferences.\n2. Select \"Security & Privacy\"\n3. Select \"FileVault\".\n4. Click the \"Turn On FileVault\" button and follow the instructions.\n5. Decline to use iCloud or other Apple accounts for login. Instead, allow it to generate an offline decryption key. Store your decryption key somewhere safe so that you can decrypt your hard drive if something breaks, but prevent your enemies from acquiring yoru decryption key."}, "undo": ""}, {"description": "FileVault file system encryption is enabled at the root directory.", "confidence": "required", "reference": "https://github.com/drduh/OS-X-Security-and-Privacy-Guide", "type": "regex match", "command": "fdesetup status -verbose", "expected_regex": "^.*device path \\=\\s+.*$", "case_sensitive": "false", "fix": {"manual": "Sorry, no instructions are currently available to remediate this issue."}}, {"description": "The idle timer for screen saver activation is set to 10 minutes or less.", "confidence": "recommended", "reference": "https://github.com/SummitRoute/osxlockdown/blob/58697f5162fe9e43df7dc9b6b94ffa34b0e11d4f/commands.yaml", "type": "regex match", "command": "UUID=`ioreg -rd1 -c IOPlatformExpertDevice | grep \"IOPlatformUUID\" | sed -e 's/^.*\"\\(.*\\)\"$/\\1/'`; for i in $(find /Users -type d -maxdepth 1); do PREF=$i/Library/Preferences/ByHost/com.apple.screensaver.$UUID; if [ -e $PREF.plist ]; then TIMEOUT=$(defaults read $PREF.plist idleTime) && if [ $TIMEOUT -eq 0 ] || [ $TIMEOUT -gt 600 ]; then echo 1; fi; else echo 0; fi; done;", "expected_regex": "^(0\n*)+$", "case_sensitive": "false", "fix": {"command": "UUID=`ioreg -rd1 -c IOPlatformExpertDevice | grep \"IOPlatformUUID\" | sed -e 's/^.*\"\\(.*\\)\"$/\\1/'`; for i in $(find /Users -type d -maxdepth 1); do PREF=$i/Library/Preferences/ByHost/com.apple.screensaver.$UUID; if [ -e $PREF.plist ]; then defaults -currentHost write $PREF.plist idleTime -int 600; fi; done"}}, {"description": "The Safari application is currently closed.", "confidence": "required", "reference": "https://developer.apple.com/legacy/library/documentation/Darwin/Reference/ManPages/man1/defaults.1.html", "type": "exact match", "command": "ps ax | grep -c '/Applications/Safari.app/Contents/MacOS/Safari'", "expected_stdout": "2", "case_sensitive": "false", "fix": {"command": "killall \"Safari\" ; sleep 1"}}, {"description": "Safari will not auto-fill credit card data.", "confidence": "recommended", "type": "exact match", "command": "defaults -currentHost read ~/Library/Preferences/com.apple.Safari AutoFillCreditCardData", "expected_stdout": "0", "case_sensitive": "false", "fix": {"command": "defaults -currentHost write ~/Library/Preferences/com.apple.Safari AutoFillCreditCardData -bool false"}}, {"description": "Safari will not auto-fill your contact data.", "confidence": "recommended", "type": "exact match", "command": "defaults -currentHost read ~/Library/Preferences/com.apple.Safari AutoFillFromAddressBook", "expected_stdout": "0", "case_sensitive": "false", "fix": {"command": "defaults -currentHost write ~/Library/Preferences/com.apple.Safari AutoFillFromAddressBook -bool false"}}, {"description": "Safari will not auto-fill miscellaneous forms.", "confidence": "recommended", "type": "exact match", "command": "defaults -currentHost read ~/Library/Preferences/com.apple.Safari AutoFillMiscellaneousForms", "expected_stdout": "0", "case_sensitive": "false", "fix": {"command": "defaults -currentHost write ~/Library/Preferences/com.apple.Safari AutoFillMiscellaneousForms -bool false"}}, {"description": "Safari will not auto-fill usernames or passwords.", "confidence": "recommended", "type": "exact match", "command": "defaults -currentHost read ~/Library/Preferences/com.apple.Safari AutoFillPasswords", "expected_stdout": "0", "case_sensitive": "false", "fix": {"command": "defaults -currentHost write ~/Library/Preferences/com.apple.Safari AutoFillPasswords -bool false"}}, {"description": "Files downloaded in Safari are not automatically opened.", "confidence": "required", "type": "exact match", "command": "defaults -currentHost read ~/Library/Preferences/com.apple.Safari AutoOpenSafeDownloads", "expected_stdout": "0", "case_sensitive": "false", "fix": {"command": "defaults -currentHost write ~/Library/Preferences/com.apple.Safari AutoOpenSafeDownloads -bool false"}}, {"description": "Cookies and local storage are always blocked in Safari.", "confidence": "recommended", "type": "exact match", "command": "defaults -currentHost read ~/Library/Preferences/com.apple.Safari BlockStoragePolicy", "expected_stdout": "0", "case_sensitive": "false", "fix": {"command": "defaults -currentHost write ~/Library/Preferences/com.apple.Safari BlockStoragePolicy -bool false"}}, {"description": "Safari extensions are disabled.", "confidence": "required", "type": "exact match", "command": "defaults -currentHost read ~/Library/Preferences/com.apple.Safari ExtensionsEnabled", "expected_stdout": "0", "case_sensitive": "false", "fix": {"command": "defaults -currentHost write ~/Library/Preferences/com.apple.Safari ExtensionsEnabled -bool false"}}, {"description": "The Safari web browser will warn when visiting known fraudulent websites.", "confidence": "recommended", "type": "exact match", "command": "defaults -currentHost read ~/Library/Preferences/com.apple.Safari WarnAboutFraudulentWebsites", "expected_stdout": "1", "case_sensitive": "false", "fix": {"command": "defaults -currentHost write ~/Library/Preferences/com.apple.Safari WarnAboutFraudulentWebsites -bool true"}, "undo": "defaults -currentHost write ~/Library/Preferences/com.apple.Safari WarnAboutFraudulentWebsites -bool false"}, {"description": "JavaScript disabled in the Safari web browser.", "confidence": "recommended", "type": "exact match", "command": "defaults -currentHost read ~/Library/Preferences/com.apple.Safari com.apple.Safari.ContentPageGroupIdentifier.WebKit2JavaScriptEnabled", "expected_stdout": "0", "case_sensitive": "false", "fix": {"command": "defaults -currentHost write ~/Library/Preferences/com.apple.Safari com.apple.Safari.ContentPageGroupIdentifier.WebKit2JavaScriptEnabled -bool false"}, "undo": "defaults -currentHost write ~/Library/Preferences/com.apple.Safari com.apple.Safari.ContentPageGroupIdentifier.WebKit2JavaScriptEnabled -bool true"}, {"description": "JavaScript disabled in the Safari web browser (Legacy version).", "confidence": "recommended", "type": "exact match", "command": "defaults -currentHost read ~/Library/Preferences/com.apple.Safari WebKitJavaScriptEnabled", "expected_stdout": "0", "case_sensitive": "false", "fix": {"command": "defaults -currentHost write ~/Library/Preferences/com.apple.Safari WebKitJavaScriptEnabled -bool false"}, "undo": "defaults -currentHost write ~/Library/Preferences/com.apple.Safari WebKitJavaScriptEnabled -bool true"}, {"description": "Pop-up windows are blocked in the Safari web browser.", "confidence": "required", "type": "exact match", "command": "defaults -currentHost read ~/Library/Preferences/com.apple.Safari com.apple.Safari.ContentPageGroupIdentifier.WebKit2JavaScriptCanOpenWindowsAutomatically", "expected_stdout": "0", "case_sensitive": "false", "fix": {"command": "defaults -currentHost write ~/Library/Preferences/com.apple.Safari com.apple.Safari.ContentPageGroupIdentifier.WebKit2JavaScriptCanOpenWindowsAutomatically -bool false"}, "undo": "defaults -currentHost write ~/Library/Preferences/com.apple.Safari com.apple.Safari.ContentPageGroupIdentifier.WebKit2JavaScriptCanOpenWindowsAutomatically -bool true"}, {"description": "Pop-up windows are blocked in the Safari web browser (Legacy version).", "confidence": "required", "type": "exact match", "command": "defaults -currentHost read ~/Library/Preferences/com.apple.Safari WebKitJavaScriptCanOpenWindowsAutomatically", "expected_stdout": "0", "case_sensitive": "false", "fix": {"command": "defaults -currentHost write ~/Library/Preferences/com.apple.Safari WebKitJavaScriptCanOpenWindowsAutomatically -bool false"}, "undo": "defaults -currentHost write ~/Library/Preferences/com.apple.Safari WebKitJavaScriptCanOpenWindowsAutomatically -bool true"}, {"description": "The WebGL plug-in is disabled in the Safari web browser.", "confidence": "recommended", "type": "exact match", "command": "defaults -currentHost read ~/Library/Preferences/com.apple.Safari com.apple.Safari.ContentPageGroupIdentifier.WebKit2WebGLEnabled", "expected_stdout": "0", "case_sensitive": "false", "fix": {"command": "defaults -currentHost write ~/Library/Preferences/com.apple.Safari com.apple.Safari.ContentPageGroupIdentifier.WebKit2WebGLEnabled -bool false"}, "undo": "defaults -currentHost write ~/Library/Preferences/com.apple.Safari com.apple.Safari.ContentPageGroupIdentifier.WebKit2WebGLEnabled -bool true"}, {"description": "Plug-ins are disabled in the Safari web browser.", "confidence": "recommended", "type": "exact match", "command": "defaults -currentHost read ~/Library/Preferences/com.apple.Safari com.apple.Safari.ContentPageGroupIdentifier.WebKit2PluginsEnabled", "expected_stdout": "0", "case_sensitive": "false", "fix": {"command": "defaults -currentHost write ~/Library/Preferences/com.apple.Safari com.apple.Safari.ContentPageGroupIdentifier.WebKit2PluginsEnabled -bool false"}, "undo": "defaults -currentHost write ~/Library/Preferences/com.apple.Safari com.apple.Safari.ContentPageGroupIdentifier.WebKit2PluginsEnabled -bool true"}, {"description": "Plug-ins are disabled in the Safari web browser (Legacy version).", "confidence": "recommended", "type": "exact match", "command": "defaults -currentHost read ~/Library/Preferences/com.apple.Safari WebKitPluginsEnabled", "expected_stdout": "0", "case_sensitive": "false", "fix": {"command": "defaults -currentHost write ~/Library/Preferences/com.apple.Safari WebKitPluginsEnabled -bool false"}, "undo": "defaults -currentHost write ~/Library/Preferences/com.apple.Safari WebKitPluginsEnabled -bool true"}, {"description": "Plug-ins are blocked by default in the Safari web browser unless a site is explicitly added to a list of allowed sites.", "confidence": "required", "type": "exact match", "command": "defaults -currentHost read ~/Library/Preferences/com.apple.Safari PlugInFirstVisitPolicy", "expected_stdout": "PlugInPolicyBlock", "case_sensitive": "false", "fix": {"command": "defaults -currentHost write ~/Library/Preferences/com.apple.Safari PlugInFirstVisitPolicy PlugInPolicyBlock"}}, {"description": "The Java plug-in for Safari web browser is blocked unless a site is explicitly added to a list of allowed sites.", "confidence": "required", "type": "exact match", "command": "/usr/libexec/PlistBuddy -c \"Print :ManagedPlugInPolicies:com.oracle.java.JavaAppletPlugin:PlugInFirstVisitPolicy\" ~/Library/Preferences/com.apple.Safari.plist", "expected_stdout": "PlugInPolicyBlock", "case_sensitive": "false", "fix": {"command": "/usr/libexec/PlistBuddy -c \"Add :ManagedPlugInPolicies dict\" ~/Library/Preferences/com.apple.Safari.plist ; /usr/libexec/PlistBuddy -c \"Add :ManagedPlugInPolicies:com.oracle.java.JavaAppletPlugin dict\" ~/Library/Preferences/com.apple.Safari.plist ; /usr/libexec/PlistBuddy -c \"Add :ManagedPlugInPolicies:com.oracle.java.JavaAppletPlugin:PlugInFirstVisitPolicy string PlugInPolicyBlock\" ~/Library/Preferences/com.apple.Safari.plist; /usr/libexec/PlistBuddy -c \"Set :ManagedPlugInPolicies:com.oracle.java.JavaAppletPlugin:PlugInFirstVisitPolicy PlugInPolicyBlock\" ~/Library/Preferences/com.apple.Safari.plist"}}, {"description": "The Java plug-in is disabled in the Safari web browser.", "confidence": "required", "type": "exact match", "command": "defaults -currentHost read ~/Library/Preferences/com.apple.Safari com.apple.Safari.ContentPageGroupIdentifier.WebKit2JavaEnabled", "expected_stdout": "0", "case_sensitive": "false", "fix": {"command": "defaults -currentHost write ~/Library/Preferences/com.apple.Safari com.apple.Safari.ContentPageGroupIdentifier.WebKit2JavaEnabled -bool false"}, "undo": "defaults -currentHost write ~/Library/Preferences/com.apple.Safari com.apple.Safari.ContentPageGroupIdentifier.WebKit2JavaEnabled -bool true"}, {"description": "The Java plug-in is disabled in the Safari web browser (Legacy version).", "confidence": "required", "type": "exact match", "command": "defaults -currentHost read ~/Library/Preferences/com.apple.Safari WebKitJavaEnabled", "expected_stdout": "0", "case_sensitive": "false", "fix": {"command": "defaults -currentHost write ~/Library/Preferences/com.apple.Safari WebKitJavaEnabled -bool false"}, "undo": "defaults -currentHost write ~/Library/Preferences/com.apple.Safari WebKitJavaEnabled -bool true"}, {"description": "The Safari web browser is configured to treat SHA-1 certificates as insecure.", "confidence": "recommended", "type": "exact match", "command": "defaults -currentHost read ~/Library/Preferences/com.apple.Safari TreatSHA1CertificatesAsInsecure", "expected_stdout": "1", "case_sensitive": "false", "fix": {"command": "defaults -currentHost write ~/Library/Preferences/com.apple.Safari TreatSHA1CertificatesAsInsecure -bool true"}, "undo": "defaults -currentHost write ~/Library/Preferences/com.apple.Safari TreatSHA1CertificatesAsInsecure -bool false"}, {"description": "The Safari web browser will not pre-load webpages that rank highly as search matches.", "confidence": "recommended", "type": "exact match", "command": "defaults -currentHost read ~/Library/Preferences/com.apple.Safari PreloadTopHit", "expected_stdout": "0", "case_sensitive": "false", "fix": {"command": "defaults -currentHost write ~/Library/Preferences/com.apple.Safari PreloadTopHit -bool false"}, "undo": "defaults -currentHost write ~/Library/Preferences/com.apple.Safari PreloadTopHit -bool true"}, {"description": "The Safari web browser will not include search engine suggestions for text typed in the location bar.", "confidence": "required", "type": "exact match", "command": "defaults -currentHost read ~/Library/Preferences/com.apple.Safari SuppressSearchSuggestions", "expected_stdout": "1", "case_sensitive": "false", "fix": {"command": "defaults -currentHost write ~/Library/Preferences/com.apple.Safari SuppressSearchSuggestions -bool true"}, "undo": "defaults -currentHost write ~/Library/Preferences/com.apple.Safari SuppressSearchSuggestions -bool false"}, {"description": "The Safari web browser's search suggestions are disabled.", "confidence": "required", "type": "exact match", "command": "defaults -currentHost read ~/Library/Preferences/com.apple.Safari UniversalSearchEnabled", "expected_stdout": "0", "case_sensitive": "false", "fix": {"command": "defaults -currentHost write ~/Library/Preferences/com.apple.Safari UniversalSearchEnabled -bool false"}, "undo": "defaults -currentHost write ~/Library/Preferences/com.apple.Safari UniversalSearchEnabled -bool true"}, {"description": "The Safari web browser uses the Do-Not-Track HTTP header.", "confidence": "recommended", "type": "exact match", "command": "defaults -currentHost read ~/Library/Preferences/com.apple.Safari SendDoNotTrackHTTPHeader", "expected_stdout": "1", "case_sensitive": "false", "fix": {"command": "defaults -currentHost write ~/Library/Preferences/com.apple.Safari SendDoNotTrackHTTPHeader -bool true"}, "undo": "defaults -currentHost write ~/Library/Preferences/com.apple.Safari SendDoNotTrackHTTPHeader -bool false"}, {"description": "PDF viewing is disabled in the Safari web browser.", "confidence": "recommended", "type": "exact match", "command": "defaults -currentHost read ~/Library/Preferences/com.apple.Safari WebKitOmitPDFSupport", "expected_stdout": "1", "case_sensitive": "false", "fix": {"command": "defaults -currentHost write ~/Library/Preferences/com.apple.Safari WebKitOmitPDFSupport -bool true"}, "undo": ""}, {"description": "Full website addresses are disabled in the location bar of the Safari web browser.", "confidence": "required", "type": "exact match", "command": "defaults -currentHost read ~/Library/Preferences/com.apple.Safari ShowFullURLInSmartSearchField", "expected_stdout": "1", "case_sensitive": "false", "fix": {"command": "defaults -currentHost write ~/Library/Preferences/com.apple.Safari ShowFullURLInSmartSearchField -bool true"}, "undo": "defaults -currentHost write ~/Library/Preferences/com.apple.Safari ShowFullURLInSmartSearchField -bool false\""}, {"description": "The Mail application is currently closed.", "confidence": "required", "reference": "https://developer.apple.com/legacy/library/documentation/Darwin/Reference/ManPages/man1/defaults.1.html", "type": "exact match", "command": "ps ax | grep -c '/Applications/Mail.app/Contents/MacOS/Mail'", "expected_stdout": "2", "case_sensitive": "false", "fix": {"command": "killall \"Mail\" ; sleep 1"}}, {"description": "Apple Mail does not automatically load remote content in e-mails.", "confidence": "recommended", "type": "exact match", "command": "REMOTELOAD=$(defaults read ~/Library/Preferences/com.apple.mail-shared DisableURLLoading | grep 1) ; if [ ! -e $(ls ~/Library/Preferences/com.apple.mail-shared.plist) ] || [ -n \"$REMOTELOAD\" ]; then echo 1; else echo 0; fi", "expected_stdout": "1", "case_sensitive": "false", "fix": {"command": "defaults write ~/Library/Preferences/com.apple.mail-shared DisableURLLoading -bool true"}, "undo": "defaults write ~/Library/Preferences/com.apple.mail-shared DisableURLLoading -bool false"}, {"description": "Mail identified by Apple Mail as junk is sent to the Junk mailbox.", "confidence": "recommended", "type": "exact match", "command": "defaults -currentHost read ~/Library/Containers/com.apple.mail/Data/Library/Preferences/com.apple.mail JunkMailBehavior", "expected_stdout": "2", "case_sensitive": "false", "fix": {"command": "defaults -currentHost write ~/Library/Containers/com.apple.mail/Data/Library/Preferences/com.apple.mail JunkMailBehavior -int 2"}}, {"description": "New e-mails composed in Apple Mail are encrypted by GPGMail if the receiver's PGP is present in the keychain.", "confidence": "recommended", "type": "exact match", "command": "AUTOENCRYPT=$(defaults read ~/Library/Preferences/org.gpgtools.gpgmail EncryptNewEmailsByDefault | grep 1) ; if [ ! -e $(ls ~/Library/Preferences/org.gpgtools.gpgmail.plist) ] || [ -n \"$AUTOENCRYPT\" ]; then echo 1; else echo 0; fi", "expected_stdout": "1", "case_sensitive": "false", "fix": {"command": "defaults write ~/Library/Preferences/org.gpgtools.gpgmail.plist EncryptNewEmailsByDefault -bool true"}, "undo": "defaults write ~/Library/Preferences/org.gpgtools.gpgmail.plist EncryptNewEmailsByDefault -bool false"}, {"description": "New e-mails composed in Apple Mail and saved as drafts are encrypted by GPGMail.", "confidence": "required", "type": "exact match", "command": "AUTOENCRYPTDRAFTS=$(defaults read ~/Library/Preferences/org.gpgtools.gpgmail OptionallyEncryptDrafts | grep 1) ; if [ ! -e $(ls ~/Library/Preferences/org.gpgtools.gpgmail.plist) ] || [ -n \"$AUTOENCRYPTDRAFTS\" ]; then echo 1; else echo 0; fi", "expected_stdout": "1", "case_sensitive": "false", "fix": {"command": "defaults write ~/Library/Preferences/org.gpgtools.gpgmail.plist OptionallyEncryptDrafts -bool true"}, "undo": "defaults write ~/Library/Preferences/org.gpgtools.gpgmail.plist OptionallyEncryptDrafts -bool false"}, {"description": "New e-mails composed in Apple Mail are signed by GPGMail.", "confidence": "required", "type": "exact match", "command": "AUTOSIGN=$(defaults read ~/Library/Preferences/org.gpgtools.gpgmail SignNewEmailsByDefault | grep 1) ; if [ ! -e $(ls ~/Library/Preferences/org.gpgtools.gpgmail.plist) ] || [ -n \"$AUTOSIGN\" ]; then echo 1; else echo 0; fi", "expected_stdout": "1", "case_sensitive": "false", "fix": {"command": "defaults write ~/Library/Preferences/org.gpgtools.gpgmail.plist SignNewEmailsByDefault -bool true"}, "undo": "defaults write ~/Library/Preferences/org.gpgtools.gpgmail.plist SignNewEmailsByDefault -bool false"}, {"description": "Apple Mail with automatically check for updates to GPGMail.", "confidence": "required", "type": "exact match", "command": "AUTOCHECK=$(defaults read ~/Library/Preferences/org.gpgtools.gpgmail SUEnableAutomaticChecks | grep 1) ; if [ ! -e $(ls ~/Library/Preferences/org.gpgtools.gpgmail.plist) ] || [ -n \"$AUTOCHECK\" ]; then echo 1; else echo 0; fi", "expected_stdout": "1", "case_sensitive": "false", "fix": {"command": "defaults write ~/Library/Preferences/org.gpgtools.gpgmail.plist SUEnableAutomaticChecks -bool true"}, "undo": "defaults write ~/Library/Preferences/org.gpgtools.gpgmail.plist SUEnableAutomaticChecks -bool false"}, {"description": "The Google Chrome browser is currently closed.", "confidence": "required", "type": "exact match", "command": "ps ax | grep -c '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome'", "expected_stdout": "2", "case_sensitive": "false", "fix": {"command": "killall \"Google Chrome\" ; sleep 3"}}, {"description": "All Google Chrome web browser profiles prevent information leakage through navigation errors.", "confidence": "recommended", "type": "regex match", "command": "if [ ! -e \"/Applications/Google Chrome.app\" ]; then echo \"False\"; else find ~/Library/Application\\ Support/Google/Chrome -name \"Preferences\" -maxdepth 2 | xargs -I{} python ./scripts/chrome_defaults.py read '{}' alternate_error_pages.enabled ; fi", "expected_regex": "^(False\n?)+$", "case_sensitive": "false", "fix": {"command": "find ~/Library/Application\\ Support/Google/Chrome -name \"Preferences\" -maxdepth 2 | xargs -I{} python ./scripts/chrome_defaults.py write '{}' alternate_error_pages.enabled -bool false"}}, {"description": "All Google Chrome web browser profiles prevent information leakage through URL suggestions.", "confidence": "required", "type": "regex match", "command": "if [ ! -e \"/Applications/Google Chrome.app\" ]; then echo \"False\"; else find ~/Library/Application\\ Support/Google/Chrome -name \"Preferences\" -maxdepth 2 | xargs -I{} python ./scripts/chrome_defaults.py read '{}' search.suggest_enabled ; fi", "expected_regex": "^(False\n?)+$", "case_sensitive": "false", "fix": {"command": "find ~/Library/Application\\ Support/Google/Chrome -name \"Preferences\" -maxdepth 2 | xargs -I{} python ./scripts/chrome_defaults.py write '{}' search.suggest_enabled -bool false"}}, {"description": "All Google Chrome web browser profiles prevent information leakage through network prediction.", "confidence": "required", "type": "regex match", "command": "if [ ! -e \"/Applications/Google Chrome.app\" ]; then echo \"2\"; else find ~/Library/Application\\ Support/Google/Chrome -name \"Preferences\" -maxdepth 2 | xargs -I{} python ./scripts/chrome_defaults.py read '{}' net.network_prediction_options ; fi", "expected_regex": "^(2\n?)+$", "case_sensitive": "false", "fix": {"command": "find ~/Library/Application\\ Support/Google/Chrome -name \"Preferences\" -maxdepth 2 | xargs -I{} python ./scripts/chrome_defaults.py write '{}' net.network_prediction_options -int 2"}}, {"description": "All Google Chrome web browser profiles prevent information leakage through report security incidents to Google.", "confidence": "recommended", "type": "regex match", "command": "if [ ! -e \"/Applications/Google Chrome.app\" ]; then echo \"False\"; else find ~/Library/Application\\ Support/Google/Chrome -name \"Preferences\" -maxdepth 2 | xargs -I{} python ./scripts/chrome_defaults.py read '{}' safebrowsing.extended_reporting_enabled ; fi", "expected_regex": "^(False\n?)+$", "case_sensitive": "false", "fix": {"command": "find ~/Library/Application\\ Support/Google/Chrome -name \"Preferences\" -maxdepth 2 | xargs -I{} python ./scripts/chrome_defaults.py write '{}' safebrowsing.extended_reporting_enabled -bool false"}}, {"description": "All Google Chrome web browser profiles have Google Safe Browsing enabled.", "confidence": "recommended", "reference": "https://en.wikipedia.org/wiki/Google_Safe_Browsing", "type": "regex match", "command": "if [ ! -e \"/Applications/Google Chrome.app\" ]; then echo \"True\"; else find ~/Library/Application\\ Support/Google/Chrome -name \"Preferences\" -maxdepth 2 | xargs -I{} python ./scripts/chrome_defaults.py read '{}' safebrowsing.enabled ; fi", "expected_regex": "^(True\n?)+$", "case_sensitive": "false", "fix": {"command": "find ~/Library/Application\\ Support/Google/Chrome -name \"Preferences\" -maxdepth 2 | xargs -I{} python ./scripts/chrome_defaults.py write '{}' safebrowsing.enabled -bool true"}}, {"description": "All Google Chrome web browser profiles prevent information leakage through spell-checking network services.", "confidence": "recommended", "type": "regex match", "command": "if [ ! -e \"/Applications/Google Chrome.app\" ]; then echo \"False\"; else find ~/Library/Application\\ Support/Google/Chrome -name \"Preferences\" -maxdepth 2 | xargs -I{} python ./scripts/chrome_defaults.py read '{}' spellcheck.use_spelling_service ; fi", "expected_regex": "^(False\n?)+$", "case_sensitive": "false", "fix": {"command": "find ~/Library/Application\\ Support/Google/Chrome -name \"Preferences\" -maxdepth 2 | xargs -I{} python ./scripts/chrome_defaults.py write '{}' spellcheck.use_spelling_service -bool false"}}, {"description": "All Google Chrome web browser profiles prevent information leakage through reporting usage statistics to Google.", "confidence": "required", "type": "regex match", "command": "if [ ! -e \"/Applications/Google Chrome.app\" ]; then echo \"False\"; exit; fi; if [ -e \"$(ls ~/Library/Application\\ Support/Google/Chrome/Consent\\ To\\ Send\\ Stats)\" ]; then echo \"True\"; exit; fi ; echo $(python ./scripts/chrome_defaults.py read ~/Library/Application\\ Support/Google/Chrome/Local\\ State user_experience_metrics.reporting_enabled)", "expected_regex": ".*False$", "case_sensitive": "false", "fix": {"command": "rm ~/Library/Application\\ Support/Google/Chrome/Consent\\ To\\ Send\\ Stats ; python ./scripts/chrome_defaults.py write \"$(ls ~/Library/Application\\ Support/Google/Chrome/Local\\ State)\" user_experience_metrics.reporting_enabled -bool false"}}, {"description": "All Google Chrome web browser profiles use the Do-Not-Track HTTP header.", "confidence": "recommended", "type": "regex match", "command": "if [ ! -e \"/Applications/Google Chrome.app\" ]; then echo \"True\"; else find ~/Library/Application\\ Support/Google/Chrome -name \"Preferences\" -maxdepth 2 | xargs -I{} python ./scripts/chrome_defaults.py read '{}' enable_do_not_track ; fi", "expected_regex": "^(True\n?)+$", "case_sensitive": "false", "fix": {"command": "find ~/Library/Application\\ Support/Google/Chrome -name \"Preferences\" -maxdepth 2 | xargs -I{} python ./scripts/chrome_defaults.py write '{}' enable_do_not_track -bool true"}}, {"description": "All Google Chrome web browser profiles prevent pop-ups.", "confidence": "required", "type": "regex match", "command": "if [ ! -e \"/Applications/Google Chrome.app\" ]; then echo \"The attribute 'profile.default_content_setting_values.popups' does not exist\"; else find ~/Library/Application\\ Support/Google/Chrome -name \"Preferences\" -maxdepth 2 | xargs -I{} python ./scripts/chrome_defaults.py read '{}' profile.default_content_setting_values.popups ; fi", "expected_regex": "^(The attribute 'profile.default_content_setting_values.popups' does not exist\\n?)|(None\\n?)+$", "case_sensitive": "false", "fix": {"command": "find ~/Library/Application\\ Support/Google/Chrome -name \"Preferences\" -maxdepth 2 | xargs -I{} python ./scripts/chrome_defaults.py delete '{}' profile.default_content_setting_values.popups"}}, {"description": "All Google Chrome web browser profiles prevent geolocation by websites.", "confidence": "recommended", "type": "regex match", "command": "if [ ! -e \"/Applications/Google Chrome.app\" ]; then echo \"2\"; else find ~/Library/Application\\ Support/Google/Chrome -name \"Preferences\" -maxdepth 2 | xargs -I{} python ./scripts/chrome_defaults.py read '{}' profile.default_content_setting_values.geolocation ; fi", "expected_regex": "^(2\n?)+$", "case_sensitive": "false", "fix": {"command": "find ~/Library/Application\\ Support/Google/Chrome -name \"Preferences\" -maxdepth 2 | xargs -I{} python ./scripts/chrome_defaults.py write '{}' profile.default_content_setting_values.geolocation -int 2"}}, {"description": "All Google Chrome web browser profiles block unsandboxed plug-in software.", "confidence": "recommended", "reference": "http://superuser.com/questions/654595/adobe-flash-player-ppapi-vs-npapi-in-google-chrome", "type": "regex match", "command": "if [ ! -e \"/Applications/Google Chrome.app\" ]; then echo \"2\"; else find ~/Library/Application\\ Support/Google/Chrome -name \"Preferences\" -maxdepth 2 | xargs -I{} python ./scripts/chrome_defaults.py read '{}' profile.default_content_setting_values.ppapi_broker ; fi", "expected_regex": "^(2\n?)+$", "case_sensitive": "false", "fix": {"command": "find ~/Library/Application\\ Support/Google/Chrome -name \"Preferences\" -maxdepth 2 | xargs -I{} python ./scripts/chrome_defaults.py write '{}' profile.default_content_setting_values.ppapi_broker -int 2"}}, {"description": "All Google Chrome web browser profiles prevent filling personal information into forms automatically.", "confidence": "required", "type": "regex match", "command": "if [ ! -e \"/Applications/Google Chrome.app\" ]; then echo \"False\"; else find ~/Library/Application\\ Support/Google/Chrome -name \"Preferences\" -maxdepth 2 | xargs -I{} python ./scripts/chrome_defaults.py read '{}' autofill.enabled ; fi", "expected_regex": "^(False\n?)+$", "case_sensitive": "false", "fix": {"command": "find ~/Library/Application\\ Support/Google/Chrome -name \"Preferences\" -maxdepth 2 | xargs -I{} python ./scripts/chrome_defaults.py write '{}' autofill.enabled -bool false"}}, {"description": "All Google Chrome web browser profiles have disabled Password Manager.", "confidence": "recommended", "type": "regex match", "command": "if [ ! -e \"/Applications/Google Chrome.app\" ]; then echo \"False\"; else find ~/Library/Application\\ Support/Google/Chrome -name \"Preferences\" -maxdepth 2 | xargs -I{} python ./scripts/chrome_defaults.py read '{}' profile.password_manager_enabled ; fi", "expected_regex": "^(False\n?)+$", "case_sensitive": "false", "fix": {"command": "find ~/Library/Application\\ Support/Google/Chrome -name \"Preferences\" -maxdepth 2 | xargs -I{} python ./scripts/chrome_defaults.py write '{}' profile.password_manager_enabled -bool false"}}, {"description": "All Google Chrome web browser profiles have disabled automatic sign-in for stored passwords.", "confidence": "required", "type": "regex match", "command": "if [ ! -e \"/Applications/Google Chrome.app\" ]; then echo \"False\"; else find ~/Library/Application\\ Support/Google/Chrome -name \"Preferences\" -maxdepth 2 | xargs -I{} python ./scripts/chrome_defaults.py read '{}' credentials_enable_autosignin ; fi", "expected_regex": "^(False\n?)+$", "case_sensitive": "false", "fix": {"command": "find ~/Library/Application\\ Support/Google/Chrome -name \"Preferences\" -maxdepth 2 | xargs -I{} python ./scripts/chrome_defaults.py write '{}' credentials_enable_autosignin -bool false"}}, {"description": "All Google Chrome web browser profiles have disabled Google CloudPrint.", "confidence": "required", "type": "regex match", "command": "if [ ! -e \"/Applications/Google Chrome.app\" ]; then echo \"False\"; else find ~/Library/Application\\ Support/Google/Chrome -name \"Preferences\" -maxdepth 2 | xargs -I{} python ./scripts/chrome_defaults.py read '{}' local_discovery.notifications_enabled ; fi", "expected_regex": "^(False\n?)+$", "case_sensitive": "false", "fix": {"command": "find ~/Library/Application\\ Support/Google/Chrome -name \"Preferences\" -maxdepth 2 | xargs -I{} python ./scripts/chrome_defaults.py write '{}' local_discovery.notifications_enabled -bool false"}}, {"description": "All Google Chrome web browser profiles have disabled Flash cookies.", "confidence": "required", "reference": "https://en.wikipedia.org/wiki/Local_shared_object", "type": "regex match", "command": "if [ ! -e \"/Applications/Google Chrome.app\" ]; then echo \"False\"; else find ~/Library/Application\\ Support/Google/Chrome -name \"Preferences\" -maxdepth 2 | xargs -I{} python ./scripts/chrome_defaults.py read '{}' browser.clear_lso_data_enabled ; fi", "expected_regex": "^(False\n?)+$", "case_sensitive": "false", "fix": {"command": "find ~/Library/Application\\ Support/Google/Chrome -name \"Preferences\" -maxdepth 2 | xargs -I{} python ./scripts/chrome_defaults.py write '{}' browser.clear_lso_data_enabled -bool false"}}, {"description": "All Google Chrome web browser profiles have disabled the Chrome Pepper Flash Player plug-in.", "confidence": "required", "reference": "http://www.newtriks.com/2012/12/01/how-to-disable-the-chrome-pepper-flash-player/", "type": "regex match", "command": "if [ ! -e \"/Applications/Google Chrome.app\" ]; then echo \"False\"; else find ~/Library/Application\\ Support/Google/Chrome -name \"Preferences\" -maxdepth 2 | xargs -I{} python ./scripts/chrome_defaults.py read '{}' browser.pepper_flash_settings_enabled ; fi", "expected_regex": "^(False\n?)+$", "case_sensitive": "false", "fix": {"command": "find ~/Library/Application\\ Support/Google/Chrome -name \"Preferences\" -maxdepth 2 | xargs -I{} python ./scripts/chrome_defaults.py write '{}' browser.pepper_flash_settings_enabled -bool false"}}, {"description": "All Google Chrome web browser profiles have disabled the Adobe Shockwave Flash plug-in.", "confidence": "required", "type": "regex match", "command": "if [ ! -e \"/Applications/Google Chrome.app\" ]; then echo \"'enabled': False, 'name': 'Shockwave Flash'\"; else find ~/Library/Application\\ Support/Google/Chrome -name \"Preferences\" -maxdepth 2 | xargs -I{} python ./scripts/chrome_defaults.py read '{}' plugins.plugins_list ; fi", "expected_regex": "^(\\[[^\\[]+'enabled': False, 'name': 'Shockwave Flash'[^\\]]+\\]\\n?)+$", "case_sensitive": "false", "fix": {"command": "find ~/Library/Application\\ Support/Google/Chrome -name \"Preferences\" -maxdepth 2 | xargs -I{} ./scripts/chrome_flash.sh '{}'"}}, {"description": "All Google Chrome web browser profiles have disabled the Adobe Flash Player plug-in.", "confidence": "required", "type": "regex match", "command": "if [ ! -e \"/Applications/Google Chrome.app\" ]; then echo \"'enabled': False, 'name': 'Adobe Flash Player'\"; else find ~/Library/Application\\ Support/Google/Chrome -name \"Preferences\" -maxdepth 2 | xargs -I{} python ./scripts/chrome_defaults.py read '{}' plugins.plugins_list ; fi", "expected_regex": "^(\\[[^\\[]+'enabled': False, 'name': 'Adobe Flash Player'[^\\]]+\\]\\n?)+$", "case_sensitive": "false", "fix": {"command": "find ~/Library/Application\\ Support/Google/Chrome -name \"Preferences\" -maxdepth 2 | xargs -I{} ./scripts/chrome_flash.sh '{}'"}}, {"description": "All Google Chrome web browser profiles have disabled the Native Client plug-in.", "confidence": "required", "reference": "https://developer.chrome.com/native-client", "type": "regex match", "command": "if [ ! -e \"/Applications/Google Chrome.app\" ]; then echo \"'enabled': False, 'name': 'Native Client'\"; else find ~/Library/Application\\ Support/Google/Chrome -name \"Preferences\" -maxdepth 2 | xargs -I{} python ./scripts/chrome_defaults.py read '{}' plugins.plugins_list ; fi", "expected_regex": "^(\\[[^\\[]+'enabled': False, 'name': 'Native Client'[^\\]]+\\]\\n?)+$", "case_sensitive": "false", "fix": {"command": "find ~/Library/Application\\ Support/Google/Chrome -name \"Preferences\" -maxdepth 2 | xargs -I{} bash ./scripts/chrome_nativeclient.sh '{}'"}}, {"description": "All Google Chrome web browser profiles have disabled the Widevine Content Decryption Module plug-in.", "confidence": "recommended", "type": "regex match", "command": "if [ ! -e \"/Applications/Google Chrome.app\" ]; then echo \"'enabled': False, 'name': 'Widevine Content Decryption Module'\"; else find ~/Library/Application\\ Support/Google/Chrome -name \"Preferences\" -maxdepth 2 | xargs -I{} python ./scripts/chrome_defaults.py read '{}' plugins.plugins_list ; fi", "expected_regex": "^(\\[[^\\[]+'enabled': False, 'name': 'Widevine Content Decryption Module'[^\\]]+\\]\\n?)+$", "case_sensitive": "false", "fix": {"command": "find ~/Library/Application\\ Support/Google/Chrome -name \"Preferences\" -maxdepth 2 | xargs -I{} bash ./scripts/chrome_widevine.sh '{}'"}}, {"description": "All Google Chrome web browser profiles have enabled the uBlock Origin extension.", "confidence": "recommended", "type": "exact match", "command": "if [ ! -e \"/Applications/Google Chrome.app\" ]; then echo \"True\" ; exit ; fi ; DISABLEREASONS=$(find ~/Library/Application\\ Support/Google/Chrome -name \"Preferences\" -maxdepth 2 | xargs -I{} python ./scripts/chrome_defaults.py read '{}' extensions.settings.cjpalhdlnbpafiamejdnhcphjbkeiagm.disable_reasons | grep -v \"does not exist\" | grep -v \"not found\") ; if [[ -n $DISABLEREASONS ]] ; then echo \"False\" ; exit ; fi ; BADSTATE=$(find ~/Library/Application\\ Support/Google/Chrome -name \"Preferences\" -maxdepth 2 | grep -v \"Guest Profile\" | grep -v \"System Profile\" | xargs -I{} python ./scripts/chrome_defaults.py read '{}' extensions.settings.cjpalhdlnbpafiamejdnhcphjbkeiagm.state | grep -v \"1\") ; if [[ -n $BADSTATE ]] ; then echo \"False\" ; fi ; echo \"True\" ;", "expected_stdout": "True", "case_sensitive": "false", "fix": {"manual": "1. For each of your Chrome profiles, visit https://chrome.google.com/webstore/detail/ublock-origin/cjpalhdlnbpafiamejdnhcphjbkeiagm in Google Chrome.\n2. Select \"Add to Chrome\".\n3. Complete any required follow-up steps as instructed on the screen."}}, {"description": "All Google Chrome web browser profiles have enabled the Ghostery extension.", "confidence": "recommended", "type": "exact match", "command": "if [ ! -e \"/Applications/Google Chrome.app\" ]; then echo \"True\" ; exit ; fi ; DISABLEREASONS=$(find ~/Library/Application\\ Support/Google/Chrome -name \"Preferences\" -maxdepth 2 | xargs -I{} python ./scripts/chrome_defaults.py read '{}' extensions.settings.mlomiejdfkolichcflejclcbmpeaniij.disable_reasons | grep -v \"does not exist\" | grep -v \"not found\") ; if [[ -n $DISABLEREASONS ]] ; then echo \"False\" ; exit ; fi ; BADSTATE=$(find ~/Library/Application\\ Support/Google/Chrome -name \"Preferences\" -maxdepth 2 | grep -v \"Guest Profile\" | grep -v \"System Profile\" | xargs -I{} python ./scripts/chrome_defaults.py read '{}' extensions.settings.mlomiejdfkolichcflejclcbmpeaniij.state | grep -v \"1\") ; if [[ -n $BADSTATE ]] ; then echo \"False\" ; fi ; echo \"True\" ;", "expected_stdout": "True", "case_sensitive": "false", "fix": {"manual": "1. For each of your Chrome profiles, visit https://chrome.google.com/webstore/detail/ghostery/mlomiejdfkolichcflejclcbmpeaniij in Google Chrome.\n2. Select \"Add to Chrome\".\n3. Complete any required follow-up steps as instructed on the screen."}}, {"description": "All Google Chrome web browser profiles have enabled the ScriptSafe extension.", "confidence": "experimental", "type": "exact match", "command": "if [ ! -e \"/Applications/Google Chrome.app\" ]; then echo \"True\" ; exit ; fi ; DISABLEREASONS=$(find ~/Library/Application\\ Support/Google/Chrome -name \"Preferences\" -maxdepth 2 | xargs -I{} python ./scripts/chrome_defaults.py read '{}' extensions.settings.oiigbmnaadbkfbmpbfijlflahbdbdgdf.disable_reasons | grep -v \"does not exist\" | grep -v \"not found\") ; if [[ -n $DISABLEREASONS ]] ; then echo \"False\" ; exit ; fi ; BADSTATE=$(find ~/Library/Application\\ Support/Google/Chrome -name \"Preferences\" -maxdepth 2 | grep -v \"Guest Profile\" | grep -v \"System Profile\" | xargs -I{} python ./scripts/chrome_defaults.py read '{}' extensions.settings.oiigbmnaadbkfbmpbfijlflahbdbdgdf.state | grep -v \"1\") ; if [[ -n $BADSTATE ]] ; then echo \"False\" ; fi ; echo \"True\" ;", "expected_stdout": "True", "case_sensitive": "false", "fix": {"manual": "1. For each of your Chrome profiles, visit https://chrome.google.com/webstore/detail/scriptsafe/oiigbmnaadbkfbmpbfijlflahbdbdgdf in Google Chrome.\n2. Select \"Add to Chrome\".\n3. Complete any required follow-up steps as instructed on the screen."}}, {"description": "Google Chrome is the default web browser.", "confidence": "recommended", "type": "exact match", "command": "VERSIONER_PERL_PREFER_32_BIT=true perl -MMac::InternetConfig -le 'print +(GetICHelper \"http\")[1]'", "expected_stdout": "Google Chrome", "case_sensitive": "false", "fix": {"manual": "1. Install Google Chrome if not already installed.\n2. Open System Preferences.\n3. Select \"General\".\n4. Under \"Default web browser\", select \"Google Chrome\"."}}] \ No newline at end of file +[{"_comment": "DO NOT EDIT THIS FILE. THIS WAS AUTOMATICALLY GENERATED BY THE hjson_to_json.py SCRIPT. INSTEAD, EDIT THE osx-config.hjson FILE."}, {"description": "Homebrew is installed.", "confidence": "required", "tests": [{"type": "exact match", "command": "echo $(homebrew_is_installed)", "command_pass": "1", "command_fail": "0", "case_sensitive": "false"}], "fix": {"sudo_command": "/usr/bin/ruby ./scripts/homebrew_install_ed33f044812cc9c509a4d8e6997c44441b06dd4e1fc87f131ee9f319d77fcd50.rb", "manual": "Homebrew is a useful tool for installing and updating programs from the command line.\nThere are various things that can go wrong when attempting to install Homebrew.\nPlease review their installation guide here:\nhttps://github.com/Homebrew/brew/blob/master/share/doc/homebrew/Installation.md"}}, {"description": "Binaries installed to /usr/local/bin are preferred over those in /usr/bin (Note: If this check does not pass, other tests will fail)", "confidence": "required", "tests": [{"type": "exact match", "command": "bash ./scripts/check_usr_local_bin_pos.sh", "command_pass": 1, "command_fail": 0, "case_sensitive": false}], "fix": {"command": "python ./scripts/set_path_precedence.py \"/usr/local/bin\" \"/usr/bin\"", "manual": "1. Bring the Terminal application to the foreground if it is not already. You should see the word \"Terminal\" in the top left corner of your screen.\n2. Select Terminal->Quit\n3. Re-open the Terminal application and run the tool again; this check should now pass."}}, {"description": "Java Runtime Environment is up to date.", "confidence": "recommended", "tests": [{"type": "exact match", "command": "java_is_installed", "command_pass": 0, "case_sensitive": false}, {"type": "exact match", "command": "java -version 2>&1 >/dev/null | grep 'java version'", "command_pass": "java version \"1.8.0_102\"", "case_sensitive": false}], "fix": {"manual": "1. Your installation of Java is not up to date. You can either update it or remove it.\n2. To update Java, see: https://www.java.com/en/download/faq/java_mac.xml\n3. To remove Java, see: https://www.java.com/en/download/help/mac_uninstall_java.xml"}}, {"description": "The System Preferences application is currently closed.", "confidence": "required", "reference": "https://developer.apple.com/legacy/library/documentation/Darwin/Reference/ManPages/man1/defaults.1.html", "tests": [{"type": "exact match", "command": "ps ax | grep -c '/Applications/System Preferences.app/Contents/MacOS/System Preferences'", "command_pass": "2", "case_sensitive": "false"}], "fix": {"command": "killall \"System Preferences\" ; sleep 1"}}, {"description": "Current user is a non-admin account.", "confidence": "required", "tests": [{"type": "exact match", "command": "id -Gn | grep -c -w admin", "command_pass": "0", "case_sensitive": "false"}], "fix": {"manual": "1. For most of your work, you should be logged into a non-administrator account. If you've already set this up and you're just logged into your admin account in order to run this tool as prescribed, you can ignore this failed test.\n2. To create a new, non-admin user for most of your work: Open System Preferences.\n3. Select \"Users & Groups\".\n4. If necessary, click the lock icon in the lower left corner and provide your administrator credentials.\n5. Click the \"+\" to create a new user. Make sure the \"Allow user to administer this computer\" checkbox is un-checked for that user.\n6. You may also want to add your non-administrator user to a list of users who can use the \"sudo\" command within the Terminal application to briefly gain administrator-like credentials for special circumstances. See: http://osxdaily.com/2014/02/06/add-user-sudoers-file-mac/"}}, {"description": "The OSX application firewall is enabled (system-wide).", "confidence": "required", "reference": "https://github.com/drduh/OS-X-Security-and-Privacy-Guide", "tests": [{"type": "exact match", "command": "little_snitch_is_installed", "command_pass": 1, "case_sensitive": false}, {"type": "exact match", "command": "defaults -currentHost read /Library/Preferences/com.apple.alf globalstate", "command_pass": "1", "command_fail": "0", "case_sensitive": "false"}], "fix": {"command": "defaults -currentHost write /Library/Preferences/com.apple.alf globalstate -bool true", "sudo_command": "sudo defaults -currentHost write /Library/Preferences/com.apple.alf globalstate -bool true"}}, {"description": "The OSX application firewall is enabled (current user only).", "confidence": "required", "reference": "https://github.com/drduh/OS-X-Security-and-Privacy-Guide", "tests": [{"type": "exact match", "command": "little_snitch_is_installed", "command_pass": 1, "case_sensitive": false}, {"type": "exact match", "command": "defaults -currentHost read ~/Library/Preferences/com.apple.alf globalstate", "command_pass": "1", "command_fail": "0", "case_sensitive": "false"}], "fix": {"command": "defaults -currentHost write ~/Library/Preferences/com.apple.alf globalstate -bool true", "sudo_command": "sudo defaults -currentHost write ~/Library/Preferences/com.apple.alf globalstate -bool true"}}, {"description": "A password is required to wake the computer from sleep or screen saver (system-wide).", "confidence": "required", "reference": "https://github.com/SummitRoute/osxlockdown/blob/58697f5162fe9e43df7dc9b6b94ffa34b0e11d4f/commands.yaml", "tests": [{"type": "exact match", "command": "defaults read /Library/Preferences/com.apple.screensaver askForPassword", "command_pass": "1", "command_fail": "0", "case_sensitive": "false"}, {"type": "exact match", "command": "sudo defaults read /Library/Preferences/com.apple.screensaver askForPassword", "command_pass": "1", "command_fail": "0", "case_sensitive": "false"}], "fix": {"command": "defaults write /Library/Preferences/com.apple.screensaver askForPassword -bool true", "sudo_command": "sudo defaults write /Library/Preferences/com.apple.screensaver askForPassword -bool true"}}, {"description": "A password is required to wake the computer from sleep or screen saver (current user only).", "confidence": "required", "reference": "https://github.com/SummitRoute/osxlockdown/blob/58697f5162fe9e43df7dc9b6b94ffa34b0e11d4f/commands.yaml", "tests": [{"type": "exact match", "command": "defaults read ~/Library/Preferences/com.apple.screensaver askForPassword", "command_pass": "1", "case_sensitive": "false"}], "fix": {"command": "defaults write ~/Library/Preferences/com.apple.screensaver askForPassword -bool true"}}, {"description": "There is no delay between starting the screen saver and locking the machine (system-wide).", "confidence": "required", "reference": "https://github.com/SummitRoute/osxlockdown/blob/58697f5162fe9e43df7dc9b6b94ffa34b0e11d4f/commands.yaml", "tests": [{"type": "exact match", "command": "defaults -currentHost read /Library/Preferences/com.apple.screensaver askForPasswordDelay", "command_pass": "0", "command_fail": "1", "case_sensitive": "false"}, {"type": "exact match", "command": "sudo defaults -currentHost read /Library/Preferences/com.apple.screensaver askForPasswordDelay", "command_pass": "0", "command_fail": "1", "case_sensitive": "false"}], "fix": {"command": "defaults -currentHost write /Library/Preferences/com.apple.screensaver askForPasswordDelay -bool false", "sudo_command": "sudo defaults -currentHost write /Library/Preferences/com.apple.screensaver askForPasswordDelay -bool false"}, "undo": "defaults -currentHost write /Library/Preferences/com.apple.screensaver askForPasswordDelay -bool true"}, {"description": "There is no delay between starting the screen saver and locking the machine (current user only).", "confidence": "required", "reference": "https://github.com/SummitRoute/osxlockdown/blob/58697f5162fe9e43df7dc9b6b94ffa34b0e11d4f/commands.yaml", "tests": [{"type": "exact match", "command": "defaults -currentHost read ~/Library/Preferences/com.apple.screensaver askForPasswordDelay", "command_pass": "0", "command_fail": "1", "case_sensitive": "false"}], "fix": {"command": "defaults -currentHost write ~/Library/Preferences/com.apple.screensaver askForPasswordDelay -bool false"}, "undo": "defaults -currentHost write ~/Library/Preferences/com.apple.screensaver askForPasswordDelay -bool true"}, {"description": "Logging is enabled for the operating system.", "confidence": "required", "reference": "https://github.com/drduh/OS-X-Security-and-Privacy-Guide", "tests": [{"type": "exact match", "command": "defaults -currentHost read /Library/Preferences/com.apple.alf loggingenabled", "command_pass": "1", "command_fail": "0", "case_sensitive": "false"}], "fix": {"command": "defaults -currentHost write /Library/Preferences/com.apple.alf loggingenabled -bool true", "sudo_command": "sudo defaults -currentHost write /Library/Preferences/com.apple.alf loggingenabled -bool true"}}, {"description": "Homebrew analytics are disabled.", "confidence": "required", "reference": "https://github.com/Homebrew/brew/blob/master/share/doc/homebrew/Analytics.md", "tests": [{"type": "exact match", "command": "[[ -n $HOMEBREW_NO_ANALYTICS ]] && echo 1 || echo 0", "command_pass": "1", "command_fail": "0", "case_sensitive": "false"}], "fix": {"command": "grep -q 'export HOMEBREW_NO_ANALYTICS=1' ~/.profile || echo 'export HOMEBREW_NO_ANALYTICS=1' >> ~/.profile ; source ~/.profile", "manual": "1. Bring the Terminal application to the foreground if it is not already. You should see the word \"Terminal\" in the top left corner of your screen.\n2. Select Terminal->Quit\n3. Re-open the Terminal application and run the tool again; this check should now pass."}}, {"description": "Stealth mode is enabled for OSX: Computer does not respond to ICMP ping requests or connection attempts from a closed TCP/UDP port. (system-wide)", "confidence": "recommended", "reference": "https://github.com/drduh/OS-X-Security-and-Privacy-Guide", "tests": [{"type": "exact match", "command": "defaults -currentHost read /Library/Preferences/com.apple.alf stealthenabled", "command_pass": "1", "command_fail": "0", "case_sensitive": "false"}], "fix": {"command": "defaults write /Library/Preferences/com.apple.alf stealthenabled -bool true", "sudo_command": "sudo defaults write /Library/Preferences/com.apple.alf stealthenabled -bool true"}, "undo": "sudo defaults write /Library/Preferences/com.apple.alf stealthenabled -bool false"}, {"description": "Stealth mode is enabled for OSX: Computer does not respond to ICMP ping requests or connection attempts from a closed TCP/UDP port. (current user only)", "confidence": "recommended", "reference": "https://github.com/drduh/OS-X-Security-and-Privacy-Guide", "tests": [{"type": "exact match", "command": "defaults -currentHost read ~/Library/Preferences/com.apple.alf stealthenabled", "command_pass": "1", "command_fail": "0", "case_sensitive": "false"}], "fix": {"command": "defaults write ~/Library/Preferences/com.apple.alf stealthenabled -bool true", "sudo_command": "sudo defaults write /Library/Preferences/com.apple.alf stealthenabled -bool true"}, "undo": "defaults write ~/Library/Preferences/com.apple.alf stealthenabled -bool false"}, {"description": "Automatic whitelisting of Apple-signed applications through the firewall is disabled (system-wide).", "confidence": "required", "reference": "https://github.com/drduh/OS-X-Security-and-Privacy-Guide", "tests": [{"type": "exact match", "command": "defaults -currentHost read /Library/Preferences/com.apple.alf allowsignedenabled", "command_pass": "0", "command_fail": "1", "case_sensitive": "false"}], "fix": {"command": "defaults -currentHost write /Library/Preferences/com.apple.alf allowsignedenabled -bool false", "sudo_command": "sudo defaults -currentHost write /Library/Preferences/com.apple.alf allowsignedenabled -bool false"}, "undo": "sudo defaults -currentHost write /Library/Preferences/com.apple.alf allowsignedenabled -bool true"}, {"description": "Automatic whitelisting of Apple-signed applications through the firewall is disabled (current user only).", "confidence": "required", "reference": "https://github.com/drduh/OS-X-Security-and-Privacy-Guide", "tests": [{"type": "exact match", "command": "defaults -currentHost read ~/Library/Preferences/com.apple.alf allowsignedenabled", "command_pass": "0", "command_fail": "1", "case_sensitive": "false"}], "fix": {"command": "defaults -currentHost write ~/Library/Preferences/com.apple.alf allowsignedenabled -bool false"}, "undo": "sudo defaults -currentHost write /Library/Preferences/com.apple.alf allowsignedenabled -bool true"}, {"description": "Captive portal for connecting to new networks is disabled to prevent MITM attacks.", "confidence": "required", "reference": "https://github.com/drduh/OS-X-Security-and-Privacy-Guide", "tests": [{"type": "exact match", "command": "defaults -currentHost read /Library/Preferences/SystemConfiguration/com.apple.captive.control Active", "command_pass": "0", "command_fail": "1", "case_sensitive": "false"}], "fix": {"command": "defaults -currentHost write /Library/Preferences/SystemConfiguration/com.apple.captive.control Active -bool false", "sudo_command": "sudo defaults -currentHost write /Library/Preferences/SystemConfiguration/com.apple.captive.control Active -bool false"}, "undo": "sudo defaults -currentHost write /Library/Preferences/SystemConfiguration/com.apple.captive.control Active -bool true"}, {"description": "OpenSSL is up to date.", "confidence": "required", "reference": "https://github.com/drduh/OS-X-Security-and-Privacy-Guide", "tests": [{"type": "exact match", "command": "openssl version", "command_pass": "OpenSSL 1.0.2h 3 May 2016", "case_sensitive": "false"}], "fix": {"command": "brew update ; brew install openssl ; brew upgrade openssl ; bash ./scripts/set_openssl_latest_path.sh", "manual": "1. Bring the Terminal application to the foreground if it is not already. You should see the word \"Terminal\" in the top left corner of your screen.\n2. Select Terminal->Quit\n3. Re-open the Terminal application and run the tool again; this check should now pass."}}, {"description": "Hidden files are displayed in Finder.", "confidence": "recommended", "reference": "http://lifehacker.com/the-best-hidden-settings-you-can-unlock-with-os-xs-ter-1476627111", "tests": [{"type": "exact match", "command": "defaults -currentHost read /Library/Preferences/SystemConfiguration/com.apple.finder AppleShowAllFiles", "command_pass": "1", "command_fail": "0", "case_sensitive": "false"}], "fix": {"command": "defaults -currentHost write /Library/Preferences/SystemConfiguration/com.apple.finder AppleShowAllFiles -bool true && killall Dock", "sudo_command": "sudo defaults -currentHost write /Library/Preferences/SystemConfiguration/com.apple.finder AppleShowAllFiles -bool true && killall Dock"}, "undo": "defaults -currentHost write /Library/Preferences/SystemConfiguration/com.apple.finder AppleShowAllFiles -bool false && killall Dock"}, {"description": "All application software is currently up to date.", "confidence": "required", "reference": "https://github.com/SummitRoute/osxlockdown/", "tests": [{"type": "exact match", "command": "LASTUPDATE=$(defaults read /Library/Preferences/com.apple.SoftwareUpdate | grep LastSuccessfulDate | sed -e 's@^.* \"\\([0-9\\\\-]*\\) .*$@\\1@'); if [ \"$LASTUPDATE\" = \"$(date +%Y-%m-%d)\" ];then echo 1 && exit; fi; echo 0 && exit", "command_pass": "1", "command_fail": "0", "case_sensitive": "false"}], "fix": {"command": "softwareupdate -i -a", "sudo_command": "sudo softwareupdate -i -a"}}, {"description": "Automatic check for software updates is enabled.", "confidence": "required", "reference": "https://github.com/SummitRoute/osxlockdown/", "tests": [{"type": "exact match", "command": "sudo softwareupdate --schedule | grep -i 'Automatic check is on'", "command_pass": "Automatic check is on", "case_sensitive": "false"}], "fix": {"command": "softwareupdate --schedule on", "sudo_command": "sudo softwareupdate --schedule on"}}, {"description": "GateKeeper protection against untrusted applications is enabled.", "confidence": "required", "tests": [{"type": "exact match", "command": "spctl --status | grep -i 'assessments enabled'", "command_pass": "assessments enabled", "case_sensitive": "false"}], "fix": {"command": "spctl --master-enable", "sudo_command": "sudo spctl --master-enable"}, "undo": "sudo spctl --master-disable"}, {"description": "Bluetooth is disabled.", "confidence": "experimental", "tests": [{"type": "exact match", "command": "defaults read /Library/Preferences/com.apple.Bluetooth ControllerPowerState", "command_pass": "0", "command_fail": "1", "case_sensitive": "false"}, {"type": "exact match", "command": "sudo defaults read /Library/Preferences/com.apple.Bluetooth ControllerPowerState", "command_pass": "0", "command_fail": "1", "case_sensitive": "false"}], "fix": {"command": "defaults write /Library/Preferences/com.apple.Bluetooth ControllerPowerState -bool false; killall -HUP blued", "sudo_command": "sudo defaults write /Library/Preferences/com.apple.Bluetooth ControllerPowerState -bool false; sudo killall -HUP blued"}, "undo": "defaults write /Library/Preferences/com.apple.Bluetooth ControllerPowerState -bool true; killall -HUP blued"}, {"description": "The infrared receiver is disabled.", "confidence": "required", "tests": [{"type": "exact match", "command": "defaults read /Library/Preferences/com.apple.driver.AppleIRController DeviceEnabled", "command_pass": "0", "command_fail": "1", "case_sensitive": "false"}, {"type": "exact match", "command": "sudo defaults read /Library/Preferences/com.apple.driver.AppleIRController DeviceEnabled", "command_pass": "0", "command_fail": "1", "case_sensitive": "false"}], "fix": {"command": "defaults write /Library/Preferences/com.apple.driver.AppleIRController DeviceEnabled -bool false", "sudo_command": "sudo defaults write /Library/Preferences/com.apple.driver.AppleIRController DeviceEnabled -bool false"}, "undo": "defaults write /Library/Preferences/com.apple.driver.AppleIRController DeviceEnabled -bool true"}, {"description": "AirDrop file sharing is disabled.", "confidence": "required", "tests": [{"type": "exact match", "command": "defaults read com.apple.NetworkBrowser DisableAirDrop", "command_pass": "1", "command_fail": "0", "case_sensitive": "false"}, {"type": "exact match", "command": "sudo defaults read com.apple.NetworkBrowser DisableAirDrop", "command_pass": "1", "command_fail": "0", "case_sensitive": "false"}], "fix": {"command": "defaults_write_ignore_missing com.apple.NetworkBrowser DisableAirDrop -bool true"}, "undo": "defaults write com.apple.NetworkBrowser DisableAirDrop -bool false"}, {"description": "File sharing is disabled.", "confidence": "recommended", "reference": "https://github.com/SummitRoute/osxlockdown/blob/58697f5162fe9e43df7dc9b6b94ffa34b0e11d4f/commands.yaml", "tests": [{"type": "exact match", "command": "if [ -n \"$(launchctl list | egrep AppleFileServer)\" ]; then exit 1; fi; if [ -n \"$(grep -i array /Library/Preferences/SystemConfiguration/com.apple.smb.server.plist)\" ]; then echo 1; exit; fi; echo 0; exit", "command_pass": "0", "command_fail": "1", "case_sensitive": "false"}], "fix": {"command": "launchctl unload -w /System/Library/LaunchDaemons/com.apple.AppleFileServer.plist; launchctl unload -w /System/Library/LaunchDaemons/com.apple.smbd.plist"}}, {"description": "Printer sharing is disabled.", "confidence": "required", "reference": "https://github.com/SummitRoute/osxlockdown/blob/58697f5162fe9e43df7dc9b6b94ffa34b0e11d4f/commands.yaml", "tests": [{"type": "exact match", "command": "if [ -n \"$(system_profiler SPPrintersDataType | grep Shared | grep Yes)\" ]; then echo 1; exit; fi; if [ -n \"$(system_profiler SPPrintersDataType | grep 'System Printer Sharing: Yes')\" ]; then echo 1; exit; fi; echo 0; exit", "command_pass": "0", "command_fail": "1", "case_sensitive": "false"}], "fix": {"command": "cupsctl --no-share-printers"}}, {"description": "Remote login is disabled.", "confidence": "required", "tests": [{"type": "exact match", "command": "systemsetup -getremotelogin", "command_pass": "Remote Login: Off", "case_sensitive": "false"}, {"type": "exact match", "command": "sudo systemsetup -getremotelogin", "command_pass": "Remote Login: Off", "case_sensitive": "false"}], "fix": {"command": "systemsetup -f -setremotelogin off", "sudo_command": "sudo systemsetup -f -setremotelogin off"}, "undo": "sudo systemsetup -f -setremotelogin on"}, {"description": "Remote Management is disabled.", "confidence": "required", "tests": [{"type": "exact match", "command": "if [ -n \"$(ps -ef | egrep \"/System/Library/CoreServices/RemoteManagement/ARDAgent.app/Contents/MacOS/[A]RDAgent\")\" ]; then echo 1; exit; fi; echo 0; exit", "command_pass": "0", "command_fail": "1", "case_sensitive": "false"}], "fix": {"command": "/System/Library/CoreServices/RemoteManagement/ARDAgent.app/Contents/Resources/kickstart -deactivate -stop", "sudo_command": "sudo /System/Library/CoreServices/RemoteManagement/ARDAgent.app/Contents/Resources/kickstart -deactivate -stop"}}, {"description": "Remote Apple events are disabled.", "confidence": "required", "reference": "https://github.com/SummitRoute/osxlockdown/blob/58697f5162fe9e43df7dc9b6b94ffa34b0e11d4f/commands.yaml", "tests": [{"type": "exact match", "command": "systemsetup -getremoteappleevents", "command_pass": "Remote Apple Events: Off", "case_sensitive": "false"}, {"type": "exact match", "command": "sudo systemsetup -getremoteappleevents", "command_pass": "Remote Apple Events: Off", "case_sensitive": "false"}], "fix": {"command": "systemsetup -setremoteappleevents off", "sudo_command": "systemsetup -setremoteappleevents off"}, "undo": "sudo systemsetup -setremoteappleevents on"}, {"description": "Internet Sharing is disabled on all network interfaces.", "confidence": "required", "reference": "https://github.com/SummitRoute/osxlockdown/blob/58697f5162fe9e43df7dc9b6b94ffa34b0e11d4f/commands.yaml", "tests": [{"type": "exact match", "command": "defaults read /Library/Preferences/SystemConfiguration/com.apple.nat NAT | grep -c 'Enabled = 1'", "command_pass": "0", "case_sensitive": "false"}], "fix": {"command": "defaults write /Library/Preferences/SystemConfiguration/com.apple.nat NAT -dict-add Enabled -bool false", "sudo_command": "sudo defaults write /Library/Preferences/SystemConfiguration/com.apple.nat NAT -dict-add Enabled -bool false"}}, {"description": "Wake on Network Access feature is disabled.", "confidence": "required", "tests": [{"type": "exact match", "command": "systemsetup getwakeonnetworkaccess", "command_pass": "Wake On Network Access: Off", "case_sensitive": "false"}, {"type": "exact match", "command": "sudo systemsetup getwakeonnetworkaccess", "command_pass": "Wake On Network Access: Off", "case_sensitive": "false"}], "fix": {"command": "systemsetup -setwakeonnetworkaccess off", "sudo_command": "sudo systemsetup -setwakeonnetworkaccess off"}, "undo": "sudo systemsetup -setwakeonnetworkaccess on"}, {"description": "Automatic setting of time and date is disabled.", "confidence": "recommended", "tests": [{"type": "exact match", "command": "systemsetup getusingnetworktime", "command_pass": "Network Time: Off", "command_fail": "Network Time: On", "case_sensitive": "false"}, {"type": "exact match", "command": "sudo systemsetup getusingnetworktime", "command_pass": "Network Time: Off", "command_fail": "Network Time: On", "case_sensitive": "false"}], "fix": {"command": "systemsetup setusingnetworktime off", "sudo_command": "sudo systemsetup setusingnetworktime off"}, "undo": "sudo systemsetup setusingnetworktime on"}, {"description": "IPv6 is disabled on all network interfaces.", "confidence": "recommended", "reference": "https://github.com/SummitRoute/osxlockdown/blob/58697f5162fe9e43df7dc9b6b94ffa34b0e11d4f/commands.yaml", "tests": [{"type": "exact match", "command": "networksetup -listallnetworkservices | while read i; do SUPPORT=$(networksetup -getinfo \"$i\" | grep \"IPv6: Automatic\") && if [ -n \"$SUPPORT\" ]; then echo 1; fi; done; echo 0; exit", "command_pass": "0", "case_sensitive": "false"}], "fix": {"command": "networksetup -listallnetworkservices | while read i; do SUPPORT=$(networksetup -getinfo \"$i\" | grep \"IPv6: Automatic\") && if [ -n \"$SUPPORT\" ]; then networksetup -setv6off \"$i\"; fi; done;"}}, {"description": "An administrator password is required to change system-wide preferences.", "confidence": "required", "reference": "https://github.com/SummitRoute/osxlockdown/blob/58697f5162fe9e43df7dc9b6b94ffa34b0e11d4f/commands.yaml", "tests": [{"type": "exact match", "command": "if [ -n \"$(security authorizationdb read system.preferences 2> /dev/null | grep -A1 shared | grep -E '(true|false)' | grep 'false')\" ]; then echo 0; else echo 1; fi", "command_pass": "0", "command_fail": "1", "case_sensitive": "false"}], "fix": {"command": "security authorizationdb read system.preferences > /tmp/system.preferences.plist &&/usr/libexec/PlistBuddy -c \"Set :shared false\" /tmp/system.preferences.plist && security authorizationdb write system.preferences < /tmp/system.preferences.plist"}}, {"description": "Documents are not stored to iCloud Drive by default. (May be mistaken if iCloud is disabled)", "confidence": "required", "reference": "http://mjtsai.com/blog/2014/10/26/yosemite-uploads-unsaved-documents-and-recent-addresses-to-icloud/", "tests": [{"type": "exact match", "command": "defaults read NSGlobalDomain NSDocumentSaveNewDocumentsToCloud", "command_pass": "0", "command_fail": "1", "case_sensitive": "false"}], "fix": {"command": "defaults write NSGlobalDomain NSDocumentSaveNewDocumentsToCloud -bool false"}, "undo": "defaults write NSGlobalDomain NSDocumentSaveNewDocumentsToCloud -bool true"}, {"description": "The File Vault key is protected when going to standby mode.", "confidence": "experimental", "reference": "https://github.com/drduh/OS-X-Security-and-Privacy-Guide", "tests": [{"type": "exact match", "command": "bash ./scripts/DestroyFVKeyOnStandby_check.sh", "command_pass": "1", "command_fail": "0", "case_sensitive": "false"}], "fix": {"command": "pmset -a destroyfvkeyonstandby 1 ; pmset -a hibernatemode 25 ; pmset -a powernap 0 ; pmset -a standby 0 ; pmset -a standbydelay 0; pmset -a autopoweroff 0", "sudo_command": "sudo pmset -a destroyfvkeyonstandby 1 ; sudo pmset -a hibernatemode 25 ; sudo pmset -a powernap 0 ; sudo pmset -a standby 0 ; sudo pmset -a standbydelay 0; sudo pmset -a autopoweroff 0"}}, {"description": "The system will store a copy of memory to persistent storage, and will remove power to memory.", "confidence": "recommended", "reference": "https://github.com/drduh/OS-X-Security-and-Privacy-Guide", "tests": [{"type": "regex match", "command": "pmset -g", "command_pass": ".*hibernatemode\\s+25.*", "case_sensitive": "false"}], "fix": {"command": "pmset -a hibernatemode 25", "sudo_command": "sudo pmset -a hibernatemode 25"}}, {"description": "git is up to date or is not installed", "confidence": "required", "tests": [{"type": "regex match", "command": "git --version", "command_pass": ".*(command not found|2\\.9\\.3).*", "case_sensitive": "false"}], "fix": {"command": "brew update ; brew install git ; brew upgrade git ; python ./scripts/set_path_precedence.py \"/usr/local/bin\" \"/usr/bin\"", "manual": "1. Bring the Terminal application to the foreground if it is not already. You should see the word \"Terminal\" in the top left corner of your screen.\n2. Select Terminal->Quit\n3. Re-open the Terminal application and run the tool again; this check should now pass."}}, {"description": "Apple Push Notifications are disabled.", "confidence": "recommended", "reference": "https://github.com/drduh/OS-X-Security-and-Privacy-Guide", "tests": [{"type": "regex match", "command": "launchctl list", "command_pass": "^((?!com\\.apple\\.apsd).)*$", "case_sensitive": "false"}, {"type": "regex match", "command": "sudo launchctl list", "command_pass": "^((?!com\\.apple\\.apsd).)*$", "case_sensitive": "false"}], "fix": {"command": "launchctl unload -w /System/Library/LaunchDaemons/com.apple.apsd.plist", "sudo_command": "sudo launchctl unload -w /System/Library/LaunchDaemons/com.apple.apsd.plist"}, "undo": "sudo launchctl load -w /System/Library/LaunchDaemons/com.apple.apsd.plist"}, {"description": "Google DNS servers are used by default on all network interfaces.", "confidence": "recommended", "tests": [{"type": "regex match", "command": "networksetup listallnetworkservices | grep -v 'An asterisk' | xargs -I{} networksetup -getdnsservers '{}' ", "command_pass": "^(8\\.8\\.8\\.8\\n8\\.8\\.4\\.4\n*)+$", "case_sensitive": "false"}], "fix": {"sudo_command": "sudo bash ./scripts/use_google_dns.sh"}}, {"description": "The curl utility is up to date or absent from the system.", "confidence": "required", "tests": [{"type": "regex match", "command": "curl --version", "command_pass": ".*(command not found|7\\.50\\.1).*", "case_sensitive": "false"}], "fix": {"command": "brew update ; brew install curl ; brew upgrade curl ; python ./scripts/set_path_precedence.py \"/usr/local/bin\" \"/usr/bin\""}, "undo": "brew unlink curl"}, {"description": "FileVault file system encryption is enabled.", "confidence": "required", "reference": "https://github.com/drduh/OS-X-Security-and-Privacy-Guide", "tests": [{"type": "regex match", "command": "fdesetup status -verbose", "command_pass": "^.*FileVault is On.*$", "case_sensitive": "false"}], "fix": {"manual": "1. Open System Preferences.\n2. Select \"Security & Privacy\"\n3. Select \"FileVault\".\n4. Click the \"Turn On FileVault\" button and follow the instructions.\n5. Decline to use iCloud or other Apple accounts for login. Instead, allow it to generate an offline decryption key. Store your decryption key somewhere safe so that you can decrypt your hard drive if something breaks, but prevent your enemies from acquiring yoru decryption key."}, "undo": ""}, {"description": "FileVault file system encryption is enabled at the root directory.", "confidence": "required", "reference": "https://github.com/drduh/OS-X-Security-and-Privacy-Guide", "tests": [{"type": "regex match", "command": "fdesetup status -verbose", "command_pass": "^.*device path \\=\\s+.*$", "case_sensitive": "false"}], "fix": {"manual": "Sorry, no instructions are currently available to remediate this issue."}}, {"description": "The idle timer for screen saver activation is set to 10 minutes or less.", "confidence": "recommended", "reference": "https://github.com/SummitRoute/osxlockdown/blob/58697f5162fe9e43df7dc9b6b94ffa34b0e11d4f/commands.yaml", "tests": [{"type": "regex match", "command": "UUID=`ioreg -rd1 -c IOPlatformExpertDevice | grep \"IOPlatformUUID\" | sed -e 's/^.*\"\\(.*\\)\"$/\\1/'`; for i in $(find /Users -type d -maxdepth 1); do PREF=$i/Library/Preferences/ByHost/com.apple.screensaver.$UUID; if [ -e $PREF.plist ]; then TIMEOUT=$(defaults read $PREF.plist idleTime) && if [ $TIMEOUT -eq 0 ] || [ $TIMEOUT -gt 600 ]; then echo 1; fi; else echo 0; fi; done;", "command_pass": "^(0\n*)+$", "case_sensitive": "false"}], "fix": {"command": "UUID=`ioreg -rd1 -c IOPlatformExpertDevice | grep \"IOPlatformUUID\" | sed -e 's/^.*\"\\(.*\\)\"$/\\1/'`; for i in $(find /Users -type d -maxdepth 1); do PREF=$i/Library/Preferences/ByHost/com.apple.screensaver.$UUID; if [ -e $PREF.plist ]; then defaults -currentHost write $PREF.plist idleTime -int 600; fi; done"}}, {"description": "System Integrity Protection (SIP) is enabled.", "confidence": "required", "reference": "https://github.com/drduh/OS-X-Security-and-Privacy-Guide#system-integrity-protection", "tests": [{"type": "exact match", "command": "is_el_capitan", "command_pass": 0, "case_sensitive": false}, {"type": "exact match", "command": "csrutil status", "command_pass": "System Integrity Protection status: enabled.", "case_sensitive": false}], "fix": {"manual": "1. SIP should be enabled by default on your El Capitan machine. You must boot into \"Recovery OS\" in order to use the \"csrutil enable\" command. See: https://derflounder.wordpress.com/2015/10/01/system-integrity-protection-adding-another-layer-to-apples-security-model/"}}, {"description": "The Safari application is currently closed.", "confidence": "required", "reference": "https://developer.apple.com/legacy/library/documentation/Darwin/Reference/ManPages/man1/defaults.1.html", "tests": [{"type": "exact match", "command": "ps ax | grep -c '/Applications/Safari.app/Contents/MacOS/Safari'", "command_pass": "2", "case_sensitive": "false"}], "fix": {"command": "killall \"Safari\" ; sleep 1"}}, {"description": "Safari will not auto-fill credit card data.", "confidence": "recommended", "tests": [{"type": "exact match", "command": "defaults -currentHost read ~/Library/Preferences/com.apple.Safari AutoFillCreditCardData", "command_pass": "0", "command_fail": "1", "case_sensitive": "false"}], "fix": {"command": "defaults -currentHost write ~/Library/Preferences/com.apple.Safari AutoFillCreditCardData -bool false"}}, {"description": "Safari will not auto-fill your contact data.", "confidence": "recommended", "tests": [{"type": "exact match", "command": "defaults -currentHost read ~/Library/Preferences/com.apple.Safari AutoFillFromAddressBook", "command_pass": "0", "command_fail": "1", "case_sensitive": "false"}], "fix": {"command": "defaults -currentHost write ~/Library/Preferences/com.apple.Safari AutoFillFromAddressBook -bool false"}}, {"description": "Safari will not auto-fill miscellaneous forms.", "confidence": "recommended", "tests": [{"type": "exact match", "command": "defaults -currentHost read ~/Library/Preferences/com.apple.Safari AutoFillMiscellaneousForms", "command_pass": "0", "command_fail": "1", "case_sensitive": "false"}], "fix": {"command": "defaults -currentHost write ~/Library/Preferences/com.apple.Safari AutoFillMiscellaneousForms -bool false"}}, {"description": "Safari will not auto-fill usernames or passwords.", "confidence": "recommended", "tests": [{"type": "exact match", "command": "defaults -currentHost read ~/Library/Preferences/com.apple.Safari AutoFillPasswords", "command_pass": "0", "command_fail": "1", "case_sensitive": "false"}], "fix": {"command": "defaults -currentHost write ~/Library/Preferences/com.apple.Safari AutoFillPasswords -bool false"}}, {"description": "Files downloaded in Safari are not automatically opened.", "confidence": "required", "tests": [{"type": "exact match", "command": "defaults -currentHost read ~/Library/Preferences/com.apple.Safari AutoOpenSafeDownloads", "command_pass": "0", "command_fail": "1", "case_sensitive": "false"}], "fix": {"command": "defaults -currentHost write ~/Library/Preferences/com.apple.Safari AutoOpenSafeDownloads -bool false"}}, {"description": "Cookies and local storage are always blocked in Safari.", "confidence": "recommended", "tests": [{"type": "exact match", "command": "defaults -currentHost read ~/Library/Preferences/com.apple.Safari BlockStoragePolicy", "command_pass": "0", "command_fail": "1", "case_sensitive": "false"}], "fix": {"command": "defaults -currentHost write ~/Library/Preferences/com.apple.Safari BlockStoragePolicy -bool false"}}, {"description": "Safari extensions are disabled.", "confidence": "required", "tests": [{"type": "exact match", "command": "defaults -currentHost read ~/Library/Preferences/com.apple.Safari ExtensionsEnabled", "command_pass": "0", "command_fail": "1", "case_sensitive": "false"}], "fix": {"command": "defaults -currentHost write ~/Library/Preferences/com.apple.Safari ExtensionsEnabled -bool false"}}, {"description": "The Safari web browser will warn when visiting known fraudulent websites.", "confidence": "recommended", "tests": [{"type": "exact match", "command": "defaults -currentHost read ~/Library/Preferences/com.apple.Safari WarnAboutFraudulentWebsites", "command_pass": "1", "command_fail": "0", "case_sensitive": "false"}], "fix": {"command": "defaults -currentHost write ~/Library/Preferences/com.apple.Safari WarnAboutFraudulentWebsites -bool true"}, "undo": "defaults -currentHost write ~/Library/Preferences/com.apple.Safari WarnAboutFraudulentWebsites -bool false"}, {"description": "JavaScript is disabled in the Safari web browser.", "confidence": "recommended", "tests": [{"type": "exact match", "command": "defaults -currentHost read ~/Library/Preferences/com.apple.Safari com.apple.Safari.ContentPageGroupIdentifier.WebKit2JavaScriptEnabled", "command_pass": "0", "command_fail": "1", "case_sensitive": "false"}], "fix": {"command": "defaults -currentHost write ~/Library/Preferences/com.apple.Safari com.apple.Safari.ContentPageGroupIdentifier.WebKit2JavaScriptEnabled -bool false"}, "undo": "defaults -currentHost write ~/Library/Preferences/com.apple.Safari com.apple.Safari.ContentPageGroupIdentifier.WebKit2JavaScriptEnabled -bool true"}, {"description": "JavaScript is disabled in the Safari web browser (Legacy version).", "confidence": "recommended", "tests": [{"type": "exact match", "command": "defaults -currentHost read ~/Library/Preferences/com.apple.Safari WebKitJavaScriptEnabled", "command_pass": "0", "command_fail": "1", "case_sensitive": "false"}], "fix": {"command": "defaults -currentHost write ~/Library/Preferences/com.apple.Safari WebKitJavaScriptEnabled -bool false"}, "undo": "defaults -currentHost write ~/Library/Preferences/com.apple.Safari WebKitJavaScriptEnabled -bool true"}, {"description": "Pop-up windows are blocked in the Safari web browser.", "confidence": "required", "tests": [{"type": "exact match", "command": "defaults -currentHost read ~/Library/Preferences/com.apple.Safari com.apple.Safari.ContentPageGroupIdentifier.WebKit2JavaScriptCanOpenWindowsAutomatically", "command_pass": "0", "command_fail": "1", "case_sensitive": "false"}], "fix": {"command": "defaults -currentHost write ~/Library/Preferences/com.apple.Safari com.apple.Safari.ContentPageGroupIdentifier.WebKit2JavaScriptCanOpenWindowsAutomatically -bool false"}, "undo": "defaults -currentHost write ~/Library/Preferences/com.apple.Safari com.apple.Safari.ContentPageGroupIdentifier.WebKit2JavaScriptCanOpenWindowsAutomatically -bool true"}, {"description": "Pop-up windows are blocked in the Safari web browser (Legacy version).", "confidence": "required", "tests": [{"type": "exact match", "command": "defaults -currentHost read ~/Library/Preferences/com.apple.Safari WebKitJavaScriptCanOpenWindowsAutomatically", "command_pass": "0", "command_fail": "1", "case_sensitive": "false"}], "fix": {"command": "defaults -currentHost write ~/Library/Preferences/com.apple.Safari WebKitJavaScriptCanOpenWindowsAutomatically -bool false"}, "undo": "defaults -currentHost write ~/Library/Preferences/com.apple.Safari WebKitJavaScriptCanOpenWindowsAutomatically -bool true"}, {"description": "The WebGL plug-in is disabled in the Safari web browser.", "confidence": "recommended", "tests": [{"type": "exact match", "command": "defaults -currentHost read ~/Library/Preferences/com.apple.Safari com.apple.Safari.ContentPageGroupIdentifier.WebKit2WebGLEnabled", "command_pass": "0", "command_fail": "1", "case_sensitive": "false"}], "fix": {"command": "defaults -currentHost write ~/Library/Preferences/com.apple.Safari com.apple.Safari.ContentPageGroupIdentifier.WebKit2WebGLEnabled -bool false"}, "undo": "defaults -currentHost write ~/Library/Preferences/com.apple.Safari com.apple.Safari.ContentPageGroupIdentifier.WebKit2WebGLEnabled -bool true"}, {"description": "Plug-ins are disabled in the Safari web browser.", "confidence": "recommended", "tests": [{"type": "exact match", "command": "defaults -currentHost read ~/Library/Preferences/com.apple.Safari com.apple.Safari.ContentPageGroupIdentifier.WebKit2PluginsEnabled", "command_pass": "0", "command_fail": "1", "case_sensitive": "false"}], "fix": {"command": "defaults -currentHost write ~/Library/Preferences/com.apple.Safari com.apple.Safari.ContentPageGroupIdentifier.WebKit2PluginsEnabled -bool false"}, "undo": "defaults -currentHost write ~/Library/Preferences/com.apple.Safari com.apple.Safari.ContentPageGroupIdentifier.WebKit2PluginsEnabled -bool true"}, {"description": "Plug-ins are disabled in the Safari web browser (Legacy version).", "confidence": "recommended", "tests": [{"type": "exact match", "command": "defaults -currentHost read ~/Library/Preferences/com.apple.Safari WebKitPluginsEnabled", "command_pass": "0", "command_fail": "1", "case_sensitive": "false"}], "fix": {"command": "defaults -currentHost write ~/Library/Preferences/com.apple.Safari WebKitPluginsEnabled -bool false"}, "undo": "defaults -currentHost write ~/Library/Preferences/com.apple.Safari WebKitPluginsEnabled -bool true"}, {"description": "Plug-ins are blocked by default in the Safari web browser unless a site is explicitly added to a list of allowed sites.", "confidence": "required", "tests": [{"type": "exact match", "command": "defaults -currentHost read ~/Library/Preferences/com.apple.Safari PlugInFirstVisitPolicy", "command_pass": "PlugInPolicyBlock", "case_sensitive": "false"}], "fix": {"command": "defaults -currentHost write ~/Library/Preferences/com.apple.Safari PlugInFirstVisitPolicy PlugInPolicyBlock"}}, {"description": "The Java plug-in for Safari web browser is blocked unless a site is explicitly added to a list of allowed sites.", "confidence": "required", "tests": [{"type": "exact match", "command": "/usr/libexec/PlistBuddy -c \"Print :ManagedPlugInPolicies:com.oracle.java.JavaAppletPlugin:PlugInFirstVisitPolicy\" ~/Library/Preferences/com.apple.Safari.plist", "command_pass": "PlugInPolicyBlock", "case_sensitive": "false"}], "fix": {"command": "/usr/libexec/PlistBuddy -c \"Add :ManagedPlugInPolicies dict\" ~/Library/Preferences/com.apple.Safari.plist ; /usr/libexec/PlistBuddy -c \"Add :ManagedPlugInPolicies:com.oracle.java.JavaAppletPlugin dict\" ~/Library/Preferences/com.apple.Safari.plist ; /usr/libexec/PlistBuddy -c \"Add :ManagedPlugInPolicies:com.oracle.java.JavaAppletPlugin:PlugInFirstVisitPolicy string PlugInPolicyBlock\" ~/Library/Preferences/com.apple.Safari.plist; /usr/libexec/PlistBuddy -c \"Set :ManagedPlugInPolicies:com.oracle.java.JavaAppletPlugin:PlugInFirstVisitPolicy PlugInPolicyBlock\" ~/Library/Preferences/com.apple.Safari.plist"}}, {"description": "The Java plug-in is disabled in the Safari web browser.", "confidence": "required", "tests": [{"type": "exact match", "command": "defaults -currentHost read ~/Library/Preferences/com.apple.Safari com.apple.Safari.ContentPageGroupIdentifier.WebKit2JavaEnabled", "command_pass": "0", "command_fail": "1", "case_sensitive": "false"}], "fix": {"command": "defaults -currentHost write ~/Library/Preferences/com.apple.Safari com.apple.Safari.ContentPageGroupIdentifier.WebKit2JavaEnabled -bool false"}, "undo": "defaults -currentHost write ~/Library/Preferences/com.apple.Safari com.apple.Safari.ContentPageGroupIdentifier.WebKit2JavaEnabled -bool true"}, {"description": "The Java plug-in is disabled in the Safari web browser (Legacy version).", "confidence": "required", "tests": [{"type": "exact match", "command": "defaults -currentHost read ~/Library/Preferences/com.apple.Safari WebKitJavaEnabled", "command_pass": "0", "command_fail": "1", "case_sensitive": "false"}], "fix": {"command": "defaults -currentHost write ~/Library/Preferences/com.apple.Safari WebKitJavaEnabled -bool false"}, "undo": "defaults -currentHost write ~/Library/Preferences/com.apple.Safari WebKitJavaEnabled -bool true"}, {"description": "The Safari web browser is configured to treat SHA-1 certificates as insecure.", "confidence": "recommended", "tests": [{"type": "exact match", "command": "defaults -currentHost read ~/Library/Preferences/com.apple.Safari TreatSHA1CertificatesAsInsecure", "command_pass": "1", "command_fail": "0", "case_sensitive": "false"}], "fix": {"command": "defaults -currentHost write ~/Library/Preferences/com.apple.Safari TreatSHA1CertificatesAsInsecure -bool true"}, "undo": "defaults -currentHost write ~/Library/Preferences/com.apple.Safari TreatSHA1CertificatesAsInsecure -bool false"}, {"description": "The Safari web browser will not pre-load webpages that rank highly as search matches.", "confidence": "recommended", "tests": [{"type": "exact match", "command": "defaults -currentHost read ~/Library/Preferences/com.apple.Safari PreloadTopHit", "command_pass": "0", "command_fail": "1", "case_sensitive": "false"}], "fix": {"command": "defaults -currentHost write ~/Library/Preferences/com.apple.Safari PreloadTopHit -bool false"}, "undo": "defaults -currentHost write ~/Library/Preferences/com.apple.Safari PreloadTopHit -bool true"}, {"description": "The Safari web browser will not include search engine suggestions for text typed in the location bar.", "confidence": "required", "tests": [{"type": "exact match", "command": "defaults -currentHost read ~/Library/Preferences/com.apple.Safari SuppressSearchSuggestions", "command_pass": "1", "command_fail": "0", "case_sensitive": "false"}], "fix": {"command": "defaults -currentHost write ~/Library/Preferences/com.apple.Safari SuppressSearchSuggestions -bool true"}, "undo": "defaults -currentHost write ~/Library/Preferences/com.apple.Safari SuppressSearchSuggestions -bool false"}, {"description": "The Safari web browser's search suggestions are disabled.", "confidence": "required", "tests": [{"type": "exact match", "command": "defaults -currentHost read ~/Library/Preferences/com.apple.Safari UniversalSearchEnabled", "command_pass": "0", "command_fail": "1", "case_sensitive": "false"}], "fix": {"command": "defaults -currentHost write ~/Library/Preferences/com.apple.Safari UniversalSearchEnabled -bool false"}, "undo": "defaults -currentHost write ~/Library/Preferences/com.apple.Safari UniversalSearchEnabled -bool true"}, {"description": "The Safari web browser uses the Do-Not-Track HTTP header.", "confidence": "recommended", "tests": [{"type": "exact match", "command": "defaults -currentHost read ~/Library/Preferences/com.apple.Safari SendDoNotTrackHTTPHeader", "command_pass": "1", "command_fail": "0", "case_sensitive": "false"}], "fix": {"command": "defaults -currentHost write ~/Library/Preferences/com.apple.Safari SendDoNotTrackHTTPHeader -bool true"}, "undo": "defaults -currentHost write ~/Library/Preferences/com.apple.Safari SendDoNotTrackHTTPHeader -bool false"}, {"description": "PDF viewing is disabled in the Safari web browser.", "confidence": "recommended", "tests": [{"type": "exact match", "command": "defaults -currentHost read ~/Library/Preferences/com.apple.Safari WebKitOmitPDFSupport", "command_pass": "1", "command_fail": "0", "case_sensitive": "false"}], "fix": {"command": "defaults -currentHost write ~/Library/Preferences/com.apple.Safari WebKitOmitPDFSupport -bool true"}, "undo": ""}, {"description": "Full website addresses are displayed in the location bar of the Safari web browser.", "confidence": "required", "tests": [{"type": "exact match", "command": "defaults -currentHost read ~/Library/Preferences/com.apple.Safari ShowFullURLInSmartSearchField", "command_pass": "1", "command_fail": "0", "case_sensitive": "false"}], "fix": {"command": "defaults -currentHost write ~/Library/Preferences/com.apple.Safari ShowFullURLInSmartSearchField -bool true"}, "undo": "defaults -currentHost write ~/Library/Preferences/com.apple.Safari ShowFullURLInSmartSearchField -bool false\""}, {"description": "The Mail application is currently closed.", "confidence": "required", "reference": "https://developer.apple.com/legacy/library/documentation/Darwin/Reference/ManPages/man1/defaults.1.html", "tests": [{"type": "exact match", "command": "ps ax | grep -c '/Applications/Mail.app/Contents/MacOS/Mail'", "command_pass": 2, "case_sensitive": false}], "fix": {"command": "killall \"Mail\" ; sleep 1"}}, {"description": "Apple Mail does not automatically load remote content in e-mails.", "confidence": "recommended", "tests": [{"type": "exact match", "command": "apple_mail_in_use", "command_pass": 0, "case_sensitive": false}, {"type": "exact match", "command": "defaults read ~/Library/Preferences/com.apple.mail-shared DisableURLLoading", "command_pass": 1, "command_fail": 0, "case_sensitive": false}], "fix": {"command": "defaults write ~/Library/Preferences/com.apple.mail-shared DisableURLLoading -bool true"}, "undo": "defaults write ~/Library/Preferences/com.apple.mail-shared DisableURLLoading -bool false"}, {"description": "Mail identified by Apple Mail as junk is sent to the Junk mailbox.", "confidence": "recommended", "tests": [{"type": "exact match", "command": "apple_mail_in_use", "command_pass": 0, "case_sensitive": false}, {"type": "exact match", "command": "defaults -currentHost read ~/Library/Containers/com.apple.mail/Data/Library/Preferences/com.apple.mail JunkMailBehavior", "command_pass": 2, "case_sensitive": false}], "fix": {"command": "defaults -currentHost write ~/Library/Containers/com.apple.mail/Data/Library/Preferences/com.apple.mail JunkMailBehavior -int 2"}}, {"description": "GPGMail is in use.", "confidence": "recommended", "tests": [{"type": "exact match", "command": "gpg_mail_in_use", "command_pass": 1, "command_fail": 0, "case_sensitive": false}], "fix": {"manual": "1. Visit https://gpgtools.org/ and install GPG Suite. This tool can be used to encrypted and sign emails sent to other PGP users."}}, {"description": "New e-mails composed in Apple Mail are encrypted by GPGMail if the receiver's PGP is present in the keychain.", "confidence": "recommended", "tests": [{"type": "exact match", "command": "apple_mail_in_use", "command_pass": 0, "case_sensitive": false}, {"type": "exact match", "command": "gpg_mail_in_use", "command_pass": 0, "case_sensitive": false}, {"type": "exact match", "command": "defaults read ~/Library/Preferences/org.gpgtools.gpgmail EncryptNewEmailsByDefault", "command_pass": 1, "command_fail": 0, "case_sensitive": false}], "fix": {"command": "defaults write ~/Library/Preferences/org.gpgtools.gpgmail.plist EncryptNewEmailsByDefault -bool true"}, "undo": "defaults write ~/Library/Preferences/org.gpgtools.gpgmail.plist EncryptNewEmailsByDefault -bool false"}, {"description": "New e-mails composed in Apple Mail and saved as drafts are encrypted by GPGMail.", "confidence": "required", "tests": [{"type": "exact match", "command": "apple_mail_in_use", "command_pass": 0, "case_sensitive": false}, {"type": "exact match", "command": "gpg_mail_in_use", "command_pass": 0, "case_sensitive": false}, {"type": "exact match", "command": "defaults read ~/Library/Preferences/org.gpgtools.gpgmail OptionallyEncryptDrafts", "command_pass": 1, "command_fail": 0, "case_sensitive": false}], "fix": {"command": "defaults write ~/Library/Preferences/org.gpgtools.gpgmail.plist OptionallyEncryptDrafts -bool true"}, "undo": "defaults write ~/Library/Preferences/org.gpgtools.gpgmail.plist OptionallyEncryptDrafts -bool false"}, {"description": "New e-mails composed in Apple Mail are signed by GPGMail.", "confidence": "required", "tests": [{"type": "exact match", "command": "apple_mail_in_use", "command_pass": 0, "case_sensitive": false}, {"type": "exact match", "command": "gpg_mail_in_use", "command_pass": 0, "case_sensitive": false}, {"type": "exact match", "command": "defaults read ~/Library/Preferences/org.gpgtools.gpgmail SignNewEmailsByDefault", "command_pass": 1, "command_fail": 0, "case_sensitive": false}], "fix": {"command": "defaults write ~/Library/Preferences/org.gpgtools.gpgmail.plist SignNewEmailsByDefault -bool true"}, "undo": "defaults write ~/Library/Preferences/org.gpgtools.gpgmail.plist SignNewEmailsByDefault -bool false"}, {"description": "Apple Mail automatically checks for updates to GPGMail.", "confidence": "required", "tests": [{"type": "exact match", "command": "apple_mail_in_use", "command_pass": 0, "case_sensitive": false}, {"type": "exact match", "command": "gpg_mail_in_use", "command_pass": 0, "case_sensitive": false}, {"type": "exact match", "command": "defaults read ~/Library/Preferences/org.gpgtools.gpgmail SUEnableAutomaticChecks", "command_pass": 1, "command_fail": 0, "case_sensitive": false}], "fix": {"command": "defaults write ~/Library/Preferences/org.gpgtools.gpgmail.plist SUEnableAutomaticChecks -bool true"}, "undo": "defaults write ~/Library/Preferences/org.gpgtools.gpgmail.plist SUEnableAutomaticChecks -bool false"}, {"description": "The Google Chrome browser is currently closed.", "confidence": "required", "tests": [{"type": "exact match", "command": "chrome_is_installed", "command_pass": 0, "case_sensitive": false}, {"type": "exact match", "command": "ps ax | grep -c 'Google Chrome.app'", "command_pass": 2, "case_sensitive": false}], "fix": {"command": "killall \"Google Chrome\" ; sleep 3"}}, {"description": "All Google Chrome web browser profiles prevent information leakage through navigation errors.", "confidence": "recommended", "tests": [{"type": "exact match", "command": "chrome_is_installed", "command_pass": 0, "case_sensitive": false}, {"type": "regex match", "command": "find ~/Library/Application\\ Support/Google/Chrome -name \"Preferences\" -maxdepth 2 | xargs -I{} python ./scripts/chrome_defaults.py read '{}' alternate_error_pages.enabled", "command_pass": "^(False\n?)+$", "case_sensitive": "false"}], "fix": {"command": "find ~/Library/Application\\ Support/Google/Chrome -name \"Preferences\" -maxdepth 2 | xargs -I{} python ./scripts/chrome_defaults.py write '{}' alternate_error_pages.enabled -bool false"}}, {"description": "All Google Chrome web browser profiles prevent information leakage through URL suggestions.", "confidence": "required", "tests": [{"type": "exact match", "command": "chrome_is_installed", "command_pass": 0, "case_sensitive": false}, {"type": "regex match", "command": "find ~/Library/Application\\ Support/Google/Chrome -name \"Preferences\" -maxdepth 2 | xargs -I{} python ./scripts/chrome_defaults.py read '{}' search.suggest_enabled", "command_pass": "^(False\n?)+$", "case_sensitive": "false"}], "fix": {"command": "find ~/Library/Application\\ Support/Google/Chrome -name \"Preferences\" -maxdepth 2 | xargs -I{} python ./scripts/chrome_defaults.py write '{}' search.suggest_enabled -bool false"}}, {"description": "All Google Chrome web browser profiles prevent information leakage through network prediction.", "confidence": "required", "tests": [{"type": "exact match", "command": "chrome_is_installed", "command_pass": 0, "case_sensitive": false}, {"type": "regex match", "command": "find ~/Library/Application\\ Support/Google/Chrome -name \"Preferences\" -maxdepth 2 | xargs -I{} python ./scripts/chrome_defaults.py read '{}' net.network_prediction_options", "command_pass": "^(2\n?)+$", "case_sensitive": "false"}], "fix": {"command": "find ~/Library/Application\\ Support/Google/Chrome -name \"Preferences\" -maxdepth 2 | xargs -I{} python ./scripts/chrome_defaults.py write '{}' net.network_prediction_options -int 2"}}, {"description": "All Google Chrome web browser profiles prevent information leakage by blocking security incidents reports to Google.", "confidence": "recommended", "tests": [{"type": "exact match", "command": "chrome_is_installed", "command_pass": 0, "case_sensitive": false}, {"type": "regex match", "command": "find ~/Library/Application\\ Support/Google/Chrome -name \"Preferences\" -maxdepth 2 | xargs -I{} python ./scripts/chrome_defaults.py read '{}' safebrowsing.extended_reporting_enabled", "command_pass": "^(False\n?)+$", "case_sensitive": "false"}], "fix": {"command": "find ~/Library/Application\\ Support/Google/Chrome -name \"Preferences\" -maxdepth 2 | xargs -I{} python ./scripts/chrome_defaults.py write '{}' safebrowsing.extended_reporting_enabled -bool false"}}, {"description": "All Google Chrome web browser profiles have Google Safe Browsing enabled.", "confidence": "recommended", "reference": "https://en.wikipedia.org/wiki/Google_Safe_Browsing", "tests": [{"type": "exact match", "command": "chrome_is_installed", "command_pass": 0, "case_sensitive": false}, {"type": "regex match", "command": "find ~/Library/Application\\ Support/Google/Chrome -name \"Preferences\" -maxdepth 2 | xargs -I{} python ./scripts/chrome_defaults.py read '{}' safebrowsing.enabled", "command_pass": "^(True\n?)+$", "case_sensitive": "false"}], "fix": {"command": "find ~/Library/Application\\ Support/Google/Chrome -name \"Preferences\" -maxdepth 2 | xargs -I{} python ./scripts/chrome_defaults.py write '{}' safebrowsing.enabled -bool true"}}, {"description": "All Google Chrome web browser profiles prevent information leakage through spell-checking network services.", "confidence": "recommended", "tests": [{"type": "exact match", "command": "chrome_is_installed", "command_pass": 0, "case_sensitive": false}, {"type": "regex match", "command": "find ~/Library/Application\\ Support/Google/Chrome -name \"Preferences\" -maxdepth 2 | xargs -I{} python ./scripts/chrome_defaults.py read '{}' spellcheck.use_spelling_service", "command_pass": "^(False\n?)+$", "case_sensitive": "false"}], "fix": {"command": "find ~/Library/Application\\ Support/Google/Chrome -name \"Preferences\" -maxdepth 2 | xargs -I{} python ./scripts/chrome_defaults.py write '{}' spellcheck.use_spelling_service -bool false"}}, {"description": "All Google Chrome web browser profiles prevent information leakage through reporting usage statistics to Google.", "confidence": "required", "tests": [{"type": "exact match", "command": "chrome_is_installed", "command_pass": 0, "case_sensitive": false}, {"type": "regex match", "command": "if [ -e \"$(ls ~/Library/Application\\ Support/Google/Chrome/Consent\\ To\\ Send\\ Stats)\" ]; then echo \"True\"; exit; fi ; echo $(python ./scripts/chrome_defaults.py read ~/Library/Application\\ Support/Google/Chrome/Local\\ State user_experience_metrics.reporting_enabled)", "command_pass": ".*False$", "case_sensitive": "false"}], "fix": {"command": "rm ~/Library/Application\\ Support/Google/Chrome/Consent\\ To\\ Send\\ Stats ; python ./scripts/chrome_defaults.py write \"$(ls ~/Library/Application\\ Support/Google/Chrome/Local\\ State)\" user_experience_metrics.reporting_enabled -bool false"}}, {"description": "All Google Chrome web browser profiles use the Do-Not-Track HTTP header.", "confidence": "recommended", "tests": [{"type": "exact match", "command": "chrome_is_installed", "command_pass": 0, "case_sensitive": false}, {"type": "regex match", "command": "find ~/Library/Application\\ Support/Google/Chrome -name \"Preferences\" -maxdepth 2 | xargs -I{} python ./scripts/chrome_defaults.py read '{}' enable_do_not_track", "command_pass": "^(True\n?)+$", "case_sensitive": "false"}], "fix": {"command": "find ~/Library/Application\\ Support/Google/Chrome -name \"Preferences\" -maxdepth 2 | xargs -I{} python ./scripts/chrome_defaults.py write '{}' enable_do_not_track -bool true"}}, {"description": "All Google Chrome web browser profiles prevent pop-ups.", "confidence": "required", "tests": [{"type": "exact match", "command": "chrome_is_installed", "command_pass": 0, "case_sensitive": false}, {"type": "regex match", "command": "find ~/Library/Application\\ Support/Google/Chrome -name \"Preferences\" -maxdepth 2 | xargs -I{} python ./scripts/chrome_defaults.py read '{}' profile.default_content_setting_values.popups", "command_pass": "^((The attribute 'profile.default_content_setting_values.popups' does not exist in '[^']+'\\.\\n?)|(None\\n?))+$", "case_sensitive": "false"}], "fix": {"command": "find ~/Library/Application\\ Support/Google/Chrome -name \"Preferences\" -maxdepth 2 | xargs -I{} python ./scripts/chrome_defaults.py delete '{}' profile.default_content_setting_values.popups"}}, {"description": "All Google Chrome web browser profiles prevent geolocation by websites.", "confidence": "recommended", "tests": [{"type": "exact match", "command": "chrome_is_installed", "command_pass": 0, "case_sensitive": false}, {"type": "regex match", "command": "find ~/Library/Application\\ Support/Google/Chrome -name \"Preferences\" -maxdepth 2 | xargs -I{} python ./scripts/chrome_defaults.py read '{}' profile.default_content_setting_values.geolocation", "command_pass": "^(2\n?)+$", "case_sensitive": "false"}], "fix": {"command": "find ~/Library/Application\\ Support/Google/Chrome -name \"Preferences\" -maxdepth 2 | xargs -I{} python ./scripts/chrome_defaults.py write '{}' profile.default_content_setting_values.geolocation -int 2"}}, {"description": "All Google Chrome web browser profiles block unsandboxed plug-in software.", "confidence": "recommended", "reference": "http://superuser.com/questions/654595/adobe-flash-player-ppapi-vs-npapi-in-google-chrome", "tests": [{"type": "exact match", "command": "chrome_is_installed", "command_pass": 0, "case_sensitive": false}, {"type": "regex match", "command": "find ~/Library/Application\\ Support/Google/Chrome -name \"Preferences\" -maxdepth 2 | xargs -I{} python ./scripts/chrome_defaults.py read '{}' profile.default_content_setting_values.ppapi_broker", "command_pass": "^(2\n?)+$", "case_sensitive": "false"}], "fix": {"command": "find ~/Library/Application\\ Support/Google/Chrome -name \"Preferences\" -maxdepth 2 | xargs -I{} python ./scripts/chrome_defaults.py write '{}' profile.default_content_setting_values.ppapi_broker -int 2"}}, {"description": "All Google Chrome web browser profiles prevent filling personal information into forms automatically.", "confidence": "required", "tests": [{"type": "exact match", "command": "chrome_is_installed", "command_pass": 0, "case_sensitive": false}, {"type": "regex match", "command": "find ~/Library/Application\\ Support/Google/Chrome -name \"Preferences\" -maxdepth 2 | xargs -I{} python ./scripts/chrome_defaults.py read '{}' autofill.enabled", "command_pass": "^(False\n?)+$", "case_sensitive": "false"}], "fix": {"command": "find ~/Library/Application\\ Support/Google/Chrome -name \"Preferences\" -maxdepth 2 | xargs -I{} python ./scripts/chrome_defaults.py write '{}' autofill.enabled -bool false"}}, {"description": "All Google Chrome web browser profiles have disabled Password Manager.", "confidence": "recommended", "tests": [{"type": "exact match", "command": "chrome_is_installed", "command_pass": 0, "case_sensitive": false}, {"type": "regex match", "command": "find ~/Library/Application\\ Support/Google/Chrome -name \"Preferences\" -maxdepth 2 | xargs -I{} python ./scripts/chrome_defaults.py read '{}' profile.password_manager_enabled", "command_pass": "^(False\n?)+$", "case_sensitive": "false"}], "fix": {"command": "find ~/Library/Application\\ Support/Google/Chrome -name \"Preferences\" -maxdepth 2 | xargs -I{} python ./scripts/chrome_defaults.py write '{}' profile.password_manager_enabled -bool false"}}, {"description": "All Google Chrome web browser profiles have disabled automatic sign-in for stored passwords.", "confidence": "required", "tests": [{"type": "exact match", "command": "chrome_is_installed", "command_pass": 0, "case_sensitive": false}, {"type": "regex match", "command": "find ~/Library/Application\\ Support/Google/Chrome -name \"Preferences\" -maxdepth 2 | xargs -I{} python ./scripts/chrome_defaults.py read '{}' credentials_enable_autosignin", "command_pass": "^(False\n?)+$", "case_sensitive": "false"}], "fix": {"command": "find ~/Library/Application\\ Support/Google/Chrome -name \"Preferences\" -maxdepth 2 | xargs -I{} python ./scripts/chrome_defaults.py write '{}' credentials_enable_autosignin -bool false"}}, {"description": "All Google Chrome web browser profiles have disabled Google CloudPrint.", "confidence": "required", "tests": [{"type": "exact match", "command": "chrome_is_installed", "command_pass": 0, "case_sensitive": false}, {"type": "regex match", "command": "find ~/Library/Application\\ Support/Google/Chrome -name \"Preferences\" -maxdepth 2 | xargs -I{} python ./scripts/chrome_defaults.py read '{}' local_discovery.notifications_enabled", "command_pass": "^(False\n?)+$", "case_sensitive": "false"}], "fix": {"command": "find ~/Library/Application\\ Support/Google/Chrome -name \"Preferences\" -maxdepth 2 | xargs -I{} python ./scripts/chrome_defaults.py write '{}' local_discovery.notifications_enabled -bool false"}}, {"description": "All Google Chrome web browser profiles block Flash cookies.", "confidence": "required", "reference": "https://en.wikipedia.org/wiki/Local_shared_object", "tests": [{"type": "exact match", "command": "chrome_is_installed", "command_pass": 0, "case_sensitive": false}, {"type": "regex match", "command": "find ~/Library/Application\\ Support/Google/Chrome -name \"Preferences\" -maxdepth 2 | xargs -I{} python ./scripts/chrome_defaults.py read '{}' browser.clear_lso_data_enabled", "command_pass": "^(False\n?)+$", "case_sensitive": "false"}], "fix": {"command": "find ~/Library/Application\\ Support/Google/Chrome -name \"Preferences\" -maxdepth 2 | xargs -I{} python ./scripts/chrome_defaults.py write '{}' browser.clear_lso_data_enabled -bool false"}}, {"description": "All Google Chrome web browser profiles have disabled the Chrome Pepper Flash Player plug-in.", "confidence": "required", "reference": "http://www.newtriks.com/2012/12/01/how-to-disable-the-chrome-pepper-flash-player/", "tests": [{"type": "exact match", "command": "chrome_is_installed", "command_pass": 0, "case_sensitive": false}, {"type": "regex match", "command": "find ~/Library/Application\\ Support/Google/Chrome -name \"Preferences\" -maxdepth 2 | xargs -I{} python ./scripts/chrome_defaults.py read '{}' browser.pepper_flash_settings_enabled", "command_pass": "^(False\n?)+$", "case_sensitive": "false"}], "fix": {"command": "find ~/Library/Application\\ Support/Google/Chrome -name \"Preferences\" -maxdepth 2 | xargs -I{} python ./scripts/chrome_defaults.py write '{}' browser.pepper_flash_settings_enabled -bool false"}}, {"description": "All Google Chrome web browser profiles have disabled the Adobe Shockwave Flash plug-in.", "confidence": "required", "tests": [{"type": "exact match", "command": "chrome_is_installed", "command_pass": 0, "case_sensitive": false}, {"type": "regex match", "command": "find ~/Library/Application\\ Support/Google/Chrome -name \"Preferences\" -maxdepth 2 | xargs -I{} python ./scripts/chrome_defaults.py read '{}' plugins.plugins_list", "command_pass": "^(\\[[^\\[]+'enabled': False, 'name': 'Shockwave Flash'[^\\]]+\\]\\n?)+$", "case_sensitive": "false"}], "fix": {"command": "find ~/Library/Application\\ Support/Google/Chrome -name \"Preferences\" -maxdepth 2 | xargs -I{} ./scripts/chrome_flash.sh '{}'"}}, {"description": "All Google Chrome web browser profiles have disabled the Adobe Flash Player plug-in.", "confidence": "required", "tests": [{"type": "exact match", "command": "chrome_is_installed", "command_pass": 0, "case_sensitive": false}, {"type": "regex match", "command": "find ~/Library/Application\\ Support/Google/Chrome -name \"Preferences\" -maxdepth 2 | xargs -I{} python ./scripts/chrome_defaults.py read '{}' plugins.plugins_list", "command_pass": "^(\\[[^\\[]+'enabled': False, 'name': 'Adobe Flash Player'[^\\]]+\\]\\n?)+$", "case_sensitive": "false"}], "fix": {"command": "find ~/Library/Application\\ Support/Google/Chrome -name \"Preferences\" -maxdepth 2 | xargs -I{} ./scripts/chrome_flash.sh '{}'"}}, {"description": "All Google Chrome web browser profiles have disabled the Native Client plug-in.", "confidence": "required", "reference": "https://developer.chrome.com/native-client", "tests": [{"type": "exact match", "command": "chrome_is_installed", "command_pass": 0, "case_sensitive": false}, {"type": "regex match", "command": "find ~/Library/Application\\ Support/Google/Chrome -name \"Preferences\" -maxdepth 2 | xargs -I{} python ./scripts/chrome_defaults.py read '{}' plugins.plugins_list", "command_pass": "^(\\[[^\\[]+'enabled': False, 'name': 'Native Client'[^\\]]+\\]\\n?)+$", "case_sensitive": "false"}], "fix": {"command": "find ~/Library/Application\\ Support/Google/Chrome -name \"Preferences\" -maxdepth 2 | xargs -I{} bash ./scripts/chrome_nativeclient.sh '{}'"}}, {"description": "All Google Chrome web browser profiles have disabled the Widevine Content Decryption Module plug-in.", "confidence": "recommended", "tests": [{"type": "exact match", "command": "chrome_is_installed", "command_pass": 0, "case_sensitive": false}, {"type": "regex match", "command": "find ~/Library/Application\\ Support/Google/Chrome -name \"Preferences\" -maxdepth 2 | xargs -I{} python ./scripts/chrome_defaults.py read '{}' plugins.plugins_list", "command_pass": "^(\\[[^\\[]+'enabled': False, 'name': 'Widevine Content Decryption Module'[^\\]]+\\]\\n?)+$", "case_sensitive": "false"}], "fix": {"command": "find ~/Library/Application\\ Support/Google/Chrome -name \"Preferences\" -maxdepth 2 | xargs -I{} bash ./scripts/chrome_widevine.sh '{}'"}}, {"description": "All Google Chrome web browser profiles have enabled the uBlock Origin extension.", "confidence": "recommended", "tests": [{"type": "exact match", "command": "chrome_is_installed", "command_pass": 0, "case_sensitive": false}, {"type": "exact match", "command": "DISABLEREASONS=$(find ~/Library/Application\\ Support/Google/Chrome -name \"Preferences\" -maxdepth 2 | xargs -I{} python ./scripts/chrome_defaults.py read '{}' extensions.settings.cjpalhdlnbpafiamejdnhcphjbkeiagm.disable_reasons | grep -v \"does not exist\" | grep -v \"not found\") ; if [[ -n $DISABLEREASONS ]] ; then echo \"False\" ; exit ; fi ; BADSTATE=$(find ~/Library/Application\\ Support/Google/Chrome -name \"Preferences\" -maxdepth 2 | grep -v \"Guest Profile\" | grep -v \"System Profile\" | xargs -I{} python ./scripts/chrome_defaults.py read '{}' extensions.settings.cjpalhdlnbpafiamejdnhcphjbkeiagm.state | grep -v \"1\") ; if [[ -n $BADSTATE ]] ; then echo \"False\" ; fi ; echo \"True\" ;", "command_pass": "True", "case_sensitive": "false"}], "fix": {"manual": "1. For each of your Chrome profiles, visit https://chrome.google.com/webstore/detail/ublock-origin/cjpalhdlnbpafiamejdnhcphjbkeiagm in Google Chrome.\n2. Select \"Add to Chrome\".\n3. Complete any required follow-up steps as instructed on the screen."}}, {"description": "All Google Chrome web browser profiles have enabled the Ghostery extension.", "confidence": "recommended", "tests": [{"type": "exact match", "command": "chrome_is_installed", "command_pass": 0, "case_sensitive": false}, {"type": "exact match", "command": "DISABLEREASONS=$(find ~/Library/Application\\ Support/Google/Chrome -name \"Preferences\" -maxdepth 2 | xargs -I{} python ./scripts/chrome_defaults.py read '{}' extensions.settings.mlomiejdfkolichcflejclcbmpeaniij.disable_reasons | grep -v \"does not exist\" | grep -v \"not found\") ; if [[ -n $DISABLEREASONS ]] ; then echo \"False\" ; exit ; fi ; BADSTATE=$(find ~/Library/Application\\ Support/Google/Chrome -name \"Preferences\" -maxdepth 2 | grep -v \"Guest Profile\" | grep -v \"System Profile\" | xargs -I{} python ./scripts/chrome_defaults.py read '{}' extensions.settings.mlomiejdfkolichcflejclcbmpeaniij.state | grep -v \"1\") ; if [[ -n $BADSTATE ]] ; then echo \"False\" ; fi ; echo \"True\" ;", "command_pass": "True", "case_sensitive": "false"}], "fix": {"manual": "1. For each of your Chrome profiles, visit https://chrome.google.com/webstore/detail/ghostery/mlomiejdfkolichcflejclcbmpeaniij in Google Chrome.\n2. Select \"Add to Chrome\".\n3. Complete any required follow-up steps as instructed on the screen."}}, {"description": "All Google Chrome web browser profiles have enabled the ScriptSafe extension.", "confidence": "experimental", "tests": [{"type": "exact match", "command": "chrome_is_installed", "command_pass": 0, "case_sensitive": false}, {"type": "exact match", "command": "DISABLEREASONS=$(find ~/Library/Application\\ Support/Google/Chrome -name \"Preferences\" -maxdepth 2 | xargs -I{} python ./scripts/chrome_defaults.py read '{}' extensions.settings.oiigbmnaadbkfbmpbfijlflahbdbdgdf.disable_reasons | grep -v \"does not exist\" | grep -v \"not found\") ; if [[ -n $DISABLEREASONS ]] ; then echo \"False\" ; exit ; fi ; BADSTATE=$(find ~/Library/Application\\ Support/Google/Chrome -name \"Preferences\" -maxdepth 2 | grep -v \"Guest Profile\" | grep -v \"System Profile\" | xargs -I{} python ./scripts/chrome_defaults.py read '{}' extensions.settings.oiigbmnaadbkfbmpbfijlflahbdbdgdf.state | grep -v \"1\") ; if [[ -n $BADSTATE ]] ; then echo \"False\" ; fi ; echo \"True\" ;", "command_pass": "True", "case_sensitive": "false"}], "fix": {"manual": "1. For each of your Chrome profiles, visit https://chrome.google.com/webstore/detail/scriptsafe/oiigbmnaadbkfbmpbfijlflahbdbdgdf in Google Chrome.\n2. Select \"Add to Chrome\".\n3. Complete any required follow-up steps as instructed on the screen."}}, {"description": "Google Chrome is the default web browser.", "confidence": "recommended", "tests": [{"type": "exact match", "command": "VERSIONER_PERL_PREFER_32_BIT=true perl -MMac::InternetConfig -le 'print +(GetICHelper \"http\")[1]'", "command_pass": "Google Chrome", "case_sensitive": "false"}], "fix": {"manual": "1. Install Google Chrome if not already installed.\n2. Open System Preferences.\n3. Select \"General\".\n4. Under \"Default web browser\", select \"Google Chrome\"."}}, {"description": "OSX/Keydnap malware is not present.", "confidence": "required", "reference": "http://www.welivesecurity.com/2016/08/30/osxkeydnap-spreads-via-signed-transmission-application/", "tests": [{"type": "exact match", "command": "if [ -e \"/Applications/Transmission.app/Contents/Resources/License.rtf\" ] ; then echo 1 ; else echo 0 ; fi", "command_fail": 1, "case_sensitive": false}, {"type": "exact match", "command": "if [ -e \"/Volumes/Transmission/Transmission.app/Contents/Resources/License.rtf\" ] ; then echo 1 ; else echo 0 ; fi", "command_fail": 1, "case_sensitive": false}, {"type": "exact match", "command": "if [ -e \"$HOME/Library/Application Support/com.apple.iCloud.sync.daemon/icloudsyncd\" ] ; then echo 1 ; else echo 0 ; fi", "command_fail": 1, "case_sensitive": false}, {"type": "exact match", "command": "if [ -e \"$HOME/Library/Application Support/com.apple.iCloud.sync.daemon/process.id\" ] ; then echo 1 ; else echo 0 ; fi", "command_fail": 1, "case_sensitive": false}, {"type": "exact match", "command": "if [ -e \"$HOME/Library/LaunchAgents/com.apple.iCloud.sync.daemon.plist\" ] ; then echo 1 ; else echo 0 ; fi", "command_fail": 1, "case_sensitive": false}, {"type": "exact match", "command": "if [ -e \"/Library/Application Support/com.apple.iCloud.sync.daemon/\" ] ; then echo 1 ; else echo 0 ; fi", "command_fail": 1, "case_sensitive": false}, {"type": "exact match", "command": "if [ -e \"/Library/Application Support/com.apple.iCloud.sync.daemon/\" ] ; then echo 1 ; else echo 0 ; fi", "command_pass": 0, "command_fail": 1, "case_sensitive": false}], "fix": {"manual": "1. One or more of the files associated with the OSX/Keydnap malware was found. Please report this to the authors of osx-config-check via GitHub (https://github.com/kristovatlas/osx-config-check) or Twitter (https://twitter.com/kristovatlas).\n2. Refer to this link: http://www.welivesecurity.com/2016/08/30/osxkeydnap-spreads-via-signed-transmission-application/"}}] \ No newline at end of file diff --git a/scripts/DestroyFVKeyOnStandby_check.sh b/scripts/DestroyFVKeyOnStandby_check.sh new file mode 100644 index 0000000..e69d9a5 --- /dev/null +++ b/scripts/DestroyFVKeyOnStandby_check.sh @@ -0,0 +1,20 @@ +#!/bin/bash +# Description: Checks various configuration settings related to the +# "DestroyFVKeyOnStandby" setting. +# See: https://github.com/drduh/OS-X-Security-and-Privacy-Guide/issues/124 +# +# Usage: DestroyFVKeyOnStandby_check.sh + + +VALUE1=$(pmset -g | grep -i "DestroyFVKeyOnStandby" | cut -f 3) +VALUE2=$(pmset -g | grep "hibernatemode" | cut -d " " -f 10) +VALUE3=$(pmset -g | grep "powernap" | cut -d " " -f 15) +VALUE4=$(pmset -g | grep "standby " | cut -d " " -f 16) +VALUE5=$(pmset -g | grep "standbydelay" | cut -d " " -f 11) +VALUE6=$(pmset -g | grep "autopoweroff " | cut -d " " -f 11) + +if [ "$VALUE1" = "1" ] && [ "$VALUE2" = "25" ] && [ "$VALUE3" = "0" ] && [ "$VALUE4" = "0" ] && [ "$VALUE5" = "0" ] && [ "$VALUE6" = "0" ] ; then + echo "1" +else + echo "0" +fi diff --git a/scripts/api.sh b/scripts/api.sh new file mode 100644 index 0000000..a2dbad4 --- /dev/null +++ b/scripts/api.sh @@ -0,0 +1,128 @@ +#!/bin/bash +# Description: Contains functions that serve as an API for osx-config-check and +# which maximize code reuse of bash script. +# All functions added to this file should be simple and easy to review for +# security. + +# Other bash scripts can use these functions by sourcing this file and invoking +# the functions as if they were commands. Example: +# source ./scripts/api.sh ; if [ $(homebrew_is_installed) = "1" ] ; then echo "pass" ; else echo "fail" ; fi +# OR +# source ./scripts/api.sh ; echo $(homebrew_is_installed) + +function homebrew_is_installed { + TEST=$(which brew) + if [ -n "$TEST" ] ; then + TEST=$(brew --version | grep Homebrew) + if [ -n "$TEST" ] ; then + echo 1 + else + echo 0 + fi + else + echo 0 + fi +} + +function chrome_is_installed { + #detects whether Google Chrome is installed + TEST=$(mdfind kMDItemCFBundleIdentifier = 'com.google.Chrome') + if [ -n "$TEST" ] ; then + echo 1 + else + echo 0 + fi +} + +function java_is_installed { + #detects whether JRE/JDK is installed or osx's placeholder is sitting there, + #waiting to annoy us with pop-up windows if 'java' is invoked + JAVA_WHICH=$(which java) + LINK=$(readlink "$JAVA_WHICH") + if [ "$LINK" = "/System/Library/Frameworks/JavaVM.framework/Versions/Current/Commands/java" ] ; then + #fake java binary + echo 0 + else + IS_JAVA=$(java -version 2>&1 >/dev/null | grep -c 'java version') + if [ "$IS_JAVA" = "1" ] ; then + echo 1 + else + echo 0 + fi + fi +} + +function little_snitch_is_installed { + RUNNING=$(pgrep "Little Snitch Daemon") + if [ -n "$RUNNING" ]; then + echo 1 + else + echo 0 + fi +} + +function apple_mail_in_use { + #I use "ls" here to resolve the "~" symbol to the fully qualified file path + #that "test" requires. + IN_USE=$(ls ~/Library/Preferences/com.apple.mail-shared.plist) + if [ -e $IN_USE ]; then + echo 1 + else + echo 0 + fi +} + +function gpg_mail_in_use { + #I use "ls" here to resolve the "~" symbol to the fully qualified file path + #that "test" requires. + IN_USE=$(ls ~/Library/Preferences/org.gpgtools.gpgmail.plist) + if [ -e $IN_USE ]; then + echo 1 + else + echo 0 + fi +} + +function is_el_capitan { + #Detects whether this system is El Capitan + SW_VERSION=$(sw_vers -productVersion) + if [[ $SW_VERSION =~ 10.11.[0-9]+ ]] ; then + echo 1 + else + echo 0 + fi +} + +function does_defaults_domain_exist { + DOMAIN=$1 + READ_VAL=$(defaults read $DOMAIN 2>&1 | tail -n 1 ) + if [[ $READ_VAL =~ "Domain $DOMAIN does not exist" ]]; then + echo 0 + else + echo 1 + fi +} +export -f does_defaults_domain_exist + +function defaults_write_ignore_missing { + #Usage: defaults_write_ignore_missing mydomain key -type value + #e.g.: defaults_write_ignore_missing com.apple.NetworkBrowser DisableAirDrop -bool true + #Writes to the specified domain using the 'defaults' utility, but will + #initialize the domain with a blank plist value if the domain does not + #already exist. + DOMAIN=$1 + KEY=$2 + DATA_TYPE=$3 + VAL=$4 + + DOMAIN_EXISTS=$(does_defaults_domain_exist $DOMAIN) + if [ "$DOMAIN_EXISTS" = "0" ]; then + defaults write $DOMAIN '{"osxconfig-reserved" = 1;}' + DOMAIN_EXISTS=$(does_defaults_domain_exist $DOMAIN) + if [ "$DOMAIN_EXISTS" = "0" ]; then + echo "Could not successfully create the specified domain." + exit + fi + fi + defaults write $DOMAIN $KEY $DATA_TYPE $VAL +} diff --git a/scripts/check_usr_local_bin_pos.sh b/scripts/check_usr_local_bin_pos.sh new file mode 100644 index 0000000..260323e --- /dev/null +++ b/scripts/check_usr_local_bin_pos.sh @@ -0,0 +1,13 @@ +#!/bin/bash +# Description: Checks the position of /usr/local/bin relative to /usr/bin/ in +# the $PATH environment variable. If /usr/bin/local is first, this will echo +# the value "1", otherwise it will echo "0" + +UB_POS=$(echo $PATH | awk '{print index($1, "/usr/bin")}') +ULB_POS=$(echo $PATH | awk '{print index($1, "/usr/local/bin")}') + +if [ "$ULB_POS" -eq "0" ] || [ "$ULB_POS" -gt "$UB_POS" ] ; then + echo 0 +else + echo 1 +fi diff --git a/scripts/homebrew_install_ed33f044812cc9c509a4d8e6997c44441b06dd4e1fc87f131ee9f319d77fcd50.rb b/scripts/homebrew_install_ed33f044812cc9c509a4d8e6997c44441b06dd4e1fc87f131ee9f319d77fcd50.rb new file mode 100644 index 0000000..982f310 --- /dev/null +++ b/scripts/homebrew_install_ed33f044812cc9c509a4d8e6997c44441b06dd4e1fc87f131ee9f319d77fcd50.rb @@ -0,0 +1,280 @@ +#!/System/Library/Frameworks/Ruby.framework/Versions/Current/usr/bin/ruby +# This script installs to /usr/local only. To install elsewhere you can just +# untar https://github.com/Homebrew/brew/tarball/master anywhere you like or +# change the value of HOMEBREW_PREFIX. +HOMEBREW_PREFIX = "/usr/local".freeze +HOMEBREW_CACHE = "#{ENV["HOME"]}/Library/Caches/Homebrew".freeze +BREW_REPO = "https://github.com/Homebrew/brew".freeze +CORE_TAP_REPO = "https://github.com/Homebrew/homebrew-core".freeze + +# no analytics during installation +ENV["HOMEBREW_NO_ANALYTICS_THIS_RUN"] = "1" + +module Tty extend self + def blue; bold 34; end + def white; bold 39; end + def red; underline 31; end + def reset; escape 0; end + def bold n; escape "1;#{n}" end + def underline n; escape "4;#{n}" end + def escape n; "\033[#{n}m" if STDOUT.tty? end +end + +class Array + def shell_s + cp = dup + first = cp.shift + cp.map{ |arg| arg.gsub " ", "\\ " }.unshift(first) * " " + end +end + +def ohai *args + puts "#{Tty.blue}==>#{Tty.white} #{args.shell_s}#{Tty.reset}" +end + +def warn warning + puts "#{Tty.red}Warning#{Tty.reset}: #{warning.chomp}" +end + +def system *args + abort "Failed during: #{args.shell_s}" unless Kernel.system(*args) +end + +def sudo *args + ohai "/usr/bin/sudo", *args + system "/usr/bin/sudo", *args +end + +def getc # NOTE only tested on OS X + system "/bin/stty raw -echo" + if STDIN.respond_to?(:getbyte) + STDIN.getbyte + else + STDIN.getc + end +ensure + system "/bin/stty -raw echo" +end + +class Version + include Comparable + attr_reader :parts + + def initialize(str) + @parts = str.split(".").map { |i| i.to_i } + end + + def <=>(other) + parts <=> self.class.new(other).parts + end +end + +def macos_version + @macos_version ||= Version.new(`/usr/bin/sw_vers -productVersion`.chomp[/10\.\d+/]) +end + +def should_install_command_line_tools? + return false if macos_version < "10.9" + developer_dir = `/usr/bin/xcode-select -print-path 2>/dev/null`.chomp + developer_dir.empty? || !File.exist?("#{developer_dir}/usr/bin/git") +end + +def git + @git ||= if ENV['GIT'] and File.executable? ENV['GIT'] + ENV['GIT'] + elsif Kernel.system '/usr/bin/which -s git' + 'git' + else + exe = `xcrun -find git 2>/dev/null`.chomp + exe if $? && $?.success? && !exe.empty? && File.executable?(exe) + end + + return unless @git + # Github only supports HTTPS fetches on 1.7.10 or later: + # https://help.github.com/articles/https-cloning-errors + `#{@git} --version` =~ /git version (\d\.\d+\.\d+)/ + return if $1.nil? or Version.new($1) < "1.7.10" + + @git +end + +def chmod?(d) + File.directory?(d) && !(File.readable?(d) && File.writable?(d) && File.executable?(d)) +end + +def chown?(d) + !File.owned?(d) +end + +def chgrp?(d) + !File.grpowned?(d) +end + +# Invalidate sudo timestamp before exiting +at_exit { Kernel.system "/usr/bin/sudo", "-k" } + +# The block form of Dir.chdir fails later if Dir.CWD doesn't exist which I +# guess is fair enough. Also sudo prints a warning message for no good reason +Dir.chdir "/usr" + +####################################################################### script +abort "See Linuxbrew: http://linuxbrew.sh/" if /linux/i === RUBY_PLATFORM +abort "MacOS too old, see: https://github.com/mistydemeo/tigerbrew" if macos_version < "10.6" +abort "Don't run this as root!" if Process.uid == 0 +abort <<-EOABORT unless `dsmemberutil checkmembership -U "#{ENV['USER']}" -G admin`.include? "user is a member" +This script requires the user #{ENV['USER']} to be an Administrator. If this +sucks for you then you can install Homebrew in your home directory or however +you please; please refer to our homepage. If you still want to use this script +set your user to be an Administrator in System Preferences or `su' to a +non-root user with Administrator privileges. +EOABORT +contents = Dir.glob(HOMEBREW_PREFIX+"*/{*,.git*}").join(" ").gsub!(%r{#{HOMEBREW_PREFIX}/}, "") +abort <<-EOABORT unless Dir["#{HOMEBREW_PREFIX}/.git/*"].empty? +It appears Homebrew is already installed. If your intent is to reinstall you +should do the following before running this installer again: + ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/uninstall)" +The current contents of #{HOMEBREW_PREFIX} are #{contents} +EOABORT +# Tests will fail if the prefix exists, but we don't have execution +# permissions. Abort in this case. +abort <<-EOABORT if File.directory? HOMEBREW_PREFIX and not File.executable? HOMEBREW_PREFIX +The Homebrew prefix, #{HOMEBREW_PREFIX}, exists but is not searchable. If this is +not intentional, please restore the default permissions and try running the +installer again: + sudo chmod 775 #{HOMEBREW_PREFIX} +EOABORT + +ohai "This script will install:" +puts "#{HOMEBREW_PREFIX}/bin/brew" +puts "#{HOMEBREW_PREFIX}/Library/..." +puts "#{HOMEBREW_PREFIX}/share/doc/homebrew" +puts "#{HOMEBREW_PREFIX}/share/man/man1/brew.1" +puts "#{HOMEBREW_PREFIX}/share/zsh/site-functions/_brew" +puts "#{HOMEBREW_PREFIX}/etc/bash_completion.d/brew" + +chmods = %w( . bin etc etc/bash_completion.d include lib lib/pkgconfig Library sbin share var var/log share/locale share/man + share/man/man1 share/man/man2 share/man/man3 share/man/man4 + share/man/man5 share/man/man6 share/man/man7 share/man/man8 + share/info share/doc share/aclocal share/zsh share/zsh/site-functions ). + map { |d| File.join(HOMEBREW_PREFIX, d) }.select { |d| chmod?(d) } +chowns = chmods.select { |d| chown?(d) } +chgrps = chmods.select { |d| chgrp?(d) } + +unless chmods.empty? + ohai "The following directories will be made group writable:" + puts(*chmods) +end +unless chowns.empty? + ohai "The following directories will have their owner set to #{Tty.underline 39}#{ENV['USER']}#{Tty.reset}:" + puts(*chowns) +end +unless chgrps.empty? + ohai "The following directories will have their group set to #{Tty.underline 39}admin#{Tty.reset}:" + puts(*chgrps) +end + +if File.directory? HOMEBREW_PREFIX + sudo "/bin/chmod", "g+rwx", *chmods unless chmods.empty? + sudo "/usr/sbin/chown", ENV['USER'], *chowns unless chowns.empty? + sudo "/usr/bin/chgrp", "admin", *chgrps unless chgrps.empty? +else + sudo "/bin/mkdir", "-p", HOMEBREW_PREFIX + sudo "/bin/chmod", "g+rwx", HOMEBREW_PREFIX + # the group is set to wheel by default for some reason + sudo "/usr/sbin/chown", "#{ENV['USER']}:admin", HOMEBREW_PREFIX +end + +sudo "/bin/mkdir", "-p", HOMEBREW_CACHE unless File.directory? HOMEBREW_CACHE +sudo "/bin/chmod", "g+rwx", HOMEBREW_CACHE if chmod? HOMEBREW_CACHE +sudo "/usr/sbin/chown", ENV['USER'], HOMEBREW_CACHE if chown? HOMEBREW_CACHE +sudo "/usr/bin/chgrp", "admin", HOMEBREW_CACHE if chgrp? HOMEBREW_CACHE + +if should_install_command_line_tools? + ohai "Searching online for the Command Line Tools" + # This temporary file prompts the 'softwareupdate' utility to list the Command Line Tools + clt_placeholder = "/tmp/.com.apple.dt.CommandLineTools.installondemand.in-progress" + sudo "/usr/bin/touch", clt_placeholder + clt_label = `softwareupdate -l | grep -B 1 -E "Command Line (Developer|Tools)" | awk -F"*" '/^ +\\*/ {print $2}' | sed 's/^ *//' | head -n1`.chomp + ohai "Installing #{clt_label}" + sudo "/usr/sbin/softwareupdate", "-i", clt_label + sudo "/bin/rm", "-f", clt_placeholder + sudo "/usr/bin/xcode-select", "--switch", "/Library/Developer/CommandLineTools" +end + +# Headless install may have failed, so fallback to original 'xcode-select' method +if should_install_command_line_tools? + if STDIN.tty? + ohai "Installing the Command Line Tools (expect a GUI popup):" + sudo "/usr/bin/xcode-select", "--install" + puts "Press any key when the installation has completed." + getc + sudo "/usr/bin/xcode-select", "--switch", "/Library/Developer/CommandLineTools" + else + abort "Error: Cannot proceed with manual Command Line Tools install without user input!" + end +end + +abort <<-EOABORT if `/usr/bin/xcrun clang 2>&1` =~ /license/ && !$?.success? +You have not agreed to the Xcode license. +Before running the installer again please agree to the license by opening +Xcode.app or running: + sudo xcodebuild -license +EOABORT + +ohai "Downloading and installing Homebrew..." +Dir.chdir HOMEBREW_PREFIX do + if git + # we do it in four steps to avoid merge errors when reinstalling + system git, "init", "-q" + + # "git remote add" will fail if the remote is defined in the global config + system git, "config", "remote.origin.url", BREW_REPO + system git, "config", "remote.origin.fetch", "+refs/heads/*:refs/remotes/origin/*" + + # ensure we don't munge line endings on checkout + system git, "config", "core.autocrlf", "false" + + args = git, "fetch", "origin", "master:refs/remotes/origin/master", "-n" + args << "--depth=1" unless ARGV.include?("--full") || !ENV["HOMEBREW_DEVELOPER"].nil? + system(*args) + + system git, "reset", "--hard", "origin/master" + + system "#{HOMEBREW_PREFIX}/bin/brew", "tap", "homebrew/core" + else + # -m to stop tar erroring out if it can't modify the mtime for root owned directories + # pipefail to cause the exit status from curl to propagate if it fails + curl_flags = "fsSL" + core_tap = "#{HOMEBREW_PREFIX}/Library/Taps/homebrew/homebrew-core" + system "/bin/bash -o pipefail -c '/usr/bin/curl -#{curl_flags} #{BREW_REPO}/tarball/master | /usr/bin/tar xz -m --strip 1'" + + system "/bin/mkdir", "-p", core_tap + Dir.chdir core_tap do + system "/bin/bash -o pipefail -c '/usr/bin/curl -#{curl_flags} #{CORE_TAP_REPO}/tarball/master | /usr/bin/tar xz -m --strip 1'" + end + end +end + +warn "#{HOMEBREW_PREFIX}/bin is not in your PATH." unless ENV['PATH'].split(':').include? "#{HOMEBREW_PREFIX}/bin" + +ohai "Installation successful!" +ohai "Next steps" + +if macos_version < "10.9" and macos_version > "10.6" + `/usr/bin/cc --version 2> /dev/null` =~ %r[clang-(\d{2,})] + version = $1.to_i + puts "Install the #{Tty.white}Command Line Tools for Xcode#{Tty.reset}: https://developer.apple.com/downloads" if version < 425 +else + puts "Install #{Tty.white}Xcode#{Tty.reset}: https://developer.apple.com/xcode" unless File.exist? "/usr/bin/cc" +end + +puts "Run `brew help` to get started" +puts "Further documentation: https://git.io/brew-docs" +ohai "Homebrew has enabled anonymous aggregate user behaviour analytics" +puts "Read the analytics documentation (and how to opt-out) here:" +puts " https://git.io/brew-analytics" +if git + Dir.chdir HOMEBREW_PREFIX do + system git, "config", "--local", "--replace-all", "homebrew.analyticsmessage", "true" + end +end diff --git a/scripts/set_openssl_latest_path.sh b/scripts/set_openssl_latest_path.sh new file mode 100644 index 0000000..e147eec --- /dev/null +++ b/scripts/set_openssl_latest_path.sh @@ -0,0 +1,16 @@ +#!/bin/bash +# Description: Sets the position of the most recent version of openssl in the +# PATH environment variable + +# set working directory to the one containing this script so it can find other +# scripts. +cd "$(dirname "$0")" + +OPENSSL_LATEST_PATH=$(find /usr/local/Cellar/openssl -name "bin" -maxdepth 2 -type d | sort -nr | head -n 1) + +if [ -n "$OPENSSL_LATEST_PATH" ] ; then + echo "Attempting to fix..." + python ./set_path_precedence.py "$OPENSSL_LATEST_PATH" "/usr/bin" +else + echo "Could not find Homebrew installation of OpenSSL." +fi diff --git a/scripts/set_path_precedence.py b/scripts/set_path_precedence.py new file mode 100644 index 0000000..6ff5578 --- /dev/null +++ b/scripts/set_path_precedence.py @@ -0,0 +1,69 @@ +"""Enforces a specific order for two directories in the PATH environment var. + +This is enforced by modifying the bash profile file stored at ~/.profile +""" + +import sys +import re +import os + +ENABLE_DEBUG_PRINT = False +PROFILE_FILENAME = os.path.expanduser('~/.profile') + +class BrokenOrderError(Exception): + """There's something wrong with the order of commands in .profile """ + pass + +def _main(): + assert len(sys.argv) == 3 + dir_1 = str(sys.argv[1]) + dir_2 = str(sys.argv[2]) + + dprint("%s %s" % (dir_1, dir_2)) + + if _is_path_good(dir_1, dir_2): + dprint("Path was good") + return + + #scan profile to ensure PATH is not already set to desired value + profile = [] + with open(PROFILE_FILENAME, 'r') as profile_read: + profile = profile_read.readlines() + + found_intended_path = False + + for line in profile: + #ignore commented out lines + if re.search(line, r'^\s*#.*$') is not None: + continue + + if _is_path_set_in_line(line, dir_1): + dprint("Found line that sets intended path: %s" % line) + found_intended_path = True + + if found_intended_path and _is_path_set_in_line(line, dir_2): + #a later export declaration has overriden what we wanted, panic D-: + raise BrokenOrderError + + if not found_intended_path: + new_path_entry = "\nexport PATH=%s:$PATH\n" % dir_1 + with open(PROFILE_FILENAME, 'a') as profile_append: + profile_append.write(new_path_entry) + +def _is_path_good(dir_1, dir_2): + return _is_match(os.environ['PATH'], r'.*%s.*%s.*' % (dir_1, dir_2)) + +def _is_match(string, pattern): + return re.compile(pattern).search(string) is not None + +def _is_path_set_in_line(line, dir_1): + passing_path_entry = r'^.*PATH=%s.*$' % dir_1 + return _is_match(line, passing_path_entry) + +def dprint(data): + """Print debug data, if enabled.""" + if ENABLE_DEBUG_PRINT: + print "DEBUG: %s" % data + +if __name__ == '__main__': + _main() diff --git a/scripts/use_google_dns.sh b/scripts/use_google_dns.sh new file mode 100644 index 0000000..e812069 --- /dev/null +++ b/scripts/use_google_dns.sh @@ -0,0 +1,36 @@ +#!/bin/bash +# Description: Sets all network interfaces to use Google DNS servers, but only +# for the network interfaces that are not compliant. + +function non_google_dns { + INTERFACE=$1 + if [ "$INTERFACE" = "An asterisk (*) denotes that a network service is disabled." ]; then + echo 0 + else + DNS=$(networksetup -getdnsservers "$INTERFACE" | tr -d "\n") + if [ "$DNS" != "8.8.8.88.8.4.4" ]; then + echo 1 + else + echo 0 + fi + fi +} +export -f non_google_dns + +function set_google_dns { + INTERFACE=$1 + sudo networksetup -setdnsservers "$INTERFACE" 8.8.8.8 8.8.4.4 +} +export -f set_google_dns + + +function process { + INTERFACE=$1 + IS_NON_GOOGLE_DNS=$(non_google_dns "$INTERFACE") + if [ "$IS_NON_GOOGLE_DNS" = "1" ]; then + set_google_dns "$INTERFACE" + fi +} +export -f process + +networksetup listallnetworkservices | xargs -I{} bash -c 'process "{}"'