Skip to content

Instantly share code, notes, and snippets.

@lazymutt
Last active May 3, 2023 08:01
Show Gist options
  • Save lazymutt/5a3e7b3631b073db5529722f857f54aa to your computer and use it in GitHub Desktop.
Save lazymutt/5a3e7b3631b073db5529722f857f54aa to your computer and use it in GitHub Desktop.
parses update versions, some managed by `sudo softwareupdate --background-critical`, ported from an applescript found at https://www.jamf.com/jamf-nation/discussions/19111/xprotect-status-extension-attribute
#!/usr/bin/python
# Copyright (c) 2019 University of Utah Student Computing Labs. ################
# All Rights Reserved.
#
# Permission to use, copy, modify, and distribute this software and
# its documentation for any purpose and without fee is hereby granted,
# provided that the above copyright notice appears in all copies and
# that both that copyright notice and this permission notice appear
# in supporting documentation, and that the name of The University
# of Utah not be used in advertising or publicity pertaining to
# distribution of the software without specific, written prior
# permission. This software is supplied as is without expressed or
# implied warranties of any kind.
################################################################################
# report_critical_update_versions.py ###########################################
# 07/12/19, v0.4, [email protected]
#
# works with Python 2 or 3
#
# more of a learning experience than a useful product.
# ported from an applescript found here:
# https://www.jamf.com/jamf-nation/discussions/19111/xprotect-status-extension-attribute
# parses update versions, some managed by `sudo softwareupdate --background-critical`
#
################################################################################
from __future__ import print_function
import datetime
import os
import subprocess
import sys
def main():
# format for update description:
# update title, file for date calculation, file for version discovery, version command to use
py2 = False
py3 = False
if sys.version_info[0] == 2:
py2 = True
elif sys.version_info[0] == 3:
py3 = True
updates = [
["XProtect", "/System/Library/CoreServices/XProtect.bundle/Contents/Resources/XProtect.meta.plist", "/System/Library/CoreServices/XProtect.bundle/Contents/Resources/XProtect.meta.plist", "Version"],
["Gatekeeper", "/private/var/db/gkopaque.bundle/Contents/version.plist", "/private/var/db/gkopaque.bundle/Contents/version.plist", "CFBundleShortVersionString"],
["SIP", "/System/Library/Sandbox/Compatibility.bundle/Contents/version.plist", "/System/Library/Sandbox/Compatibility.bundle/Contents/version.plist", "CFBundleShortVersionString"],
["MRT", "/System/Library/CoreServices/MRT.app/Contents/version.plist", "/System/Library/CoreServices/MRT.app/Contents/version", "CFBundleShortVersionString"],
["Core Suggestions", "/System/Library/Intelligent Suggestions/Assets.suggestionsassets/Contents/version.plist", "/System/Library/Intelligent Suggestions/Assets.suggestionsassets/Contents/version.plist", "CFBundleShortVersionString"],
["Incompatible Kernel Ext.", "/System/Library/Extensions/AppleKextExcludeList.kext/Contents/version.plist", "/System/Library/Extensions/AppleKextExcludeList.kext/Contents/version", "CFBundleShortVersionString"],
["Chinese Word List", "/usr/share/mecabra/updates/com.apple.inputmethod.SCIM.bundle/Contents/version.plist", "/usr/share/mecabra/updates/com.apple.inputmethod.SCIM.bundle/Contents/info", "SUVersionString"],
["Core LSKD (dkrl)", "/usr/share/kdrl.bundle/info.plist", "/usr/share/kdrl.bundle/info", "CFBundleVersion"]
]
print("-" * 50)
print("| {:<24} | {} | {:>6}|".format("Name", "Dated", "Version"))
for _, data in enumerate(updates):
print("|" + "-" * 26 + "+" + "-" * 12 + "+" + "-" * 8 + "|")
version_number = ""
try:
mod_time = datetime.datetime.fromtimestamp(os.path.getmtime(data[1]))
formatted_modtime = mod_time.strftime('%Y.%m.%d')
try:
version_string = subprocess.check_output(["defaults", "read", data[2], data[3]])
if py2:
version_number = version_string.strip()
if py3:
version_number = str(version_string.strip(), 'utf-8')
except Exception as this_exception:
print(this_exception)
print("| {:<24} | {} | {:>6} |".format(data[0], formatted_modtime, version_number))
except OSError:
formatted_modtime = "Deprecated/missing."
print("| {:<24} | {} |".format(data[0], formatted_modtime))
print("-" * 50)
if __name__ == '__main__':
main()
@lazymutt
Copy link
Author

Sample output:

Name                     Date      Version
__________________________________________
XProtect                 2017.01.17   2087
Gatekeeper               2016.12.15    107
SIP                      2015.10.23   12.0
MRT                      2017.01.17   1.14
Core Suggestions         2017.01.03    778
Incompatible Kernel Ext. 2016.11.29 11.6.1
Chinese Word List        2016.08.24   4.22
Core LSKD (dkrl)         2014.06.24      8

@torinkwok
Copy link

Thank you Todd! Here's a Swift version written by me.

@lazymutt
Copy link
Author

Sample output of new release:

--------------------------------------------------
| Name                     | Dated      | Version|
|--------------------------+------------+--------|
| XProtect                 | 2019.04.26 |   2103 |
|--------------------------+------------+--------|
| Gatekeeper               | 2019.07.12 |    172 |
|--------------------------+------------+--------|
| SIP                      | 2019.02.22 |   15.0 |
|--------------------------+------------+--------|
| MRT                      | 2019.07.15 |   1.46 |
|--------------------------+------------+--------|
| Core Suggestions         | Deprecated/missing. |
|--------------------------+------------+--------|
| Incompatible Kernel Ext. | 2019.04.10 | 14.5.1 |
|--------------------------+------------+--------|
| Chinese Word List        | Deprecated/missing. |
|--------------------------+------------+--------|
| Core LSKD (dkrl)         | 2019.02.28 |      8 |
--------------------------------------------------

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment