Using JXA in Jamf Pro Scripts and Extension Attributes

Quick follow-up to my earlier guide on using JavaScript for Automation.

There must be something in the air that put the topic of JXA on the minds of the Apple community. Armin Briegel shared a great roundup of recent JXA work, and the #scripting channel on the MacAdmins Slack team is full of folks discussing new and old discoveries.

Here are a handful of additional tips.

Excutable JXA scripts

You can run JXA directly by including the JavaScript language flag in a script's shebang, like this:

#!/usr/bin/osascript -l JavaScript

function run() {
	var app = Application.currentApplication();
	app.includeStandardAdditions = true;
	return app.systemInfo().cpuType;

Save the file with a name and extension you like. I've been using .scpt, which is the convention suggested by Apple's own Script Editor application. Something like cputype.scpt will work just fine.

Mark the file as executable by running chmod +x cputype.scpt. Then, you can run it on your system by simply calling ./cputype.scpt

This will output the CPU architecture of the computer, for example ARM64E or Intel x86-64...

JXA in Jamf Pro Scripts

You can drop a JXA script directly in Jamf Pro without any modification. As long as you include the JavaScript shebang outlined above, you're good to go.

You do not necessarily need to wrap JXA in a shell script. It might make sense to "shell out" to a JXA function from a shell script for some use cases, but it is not a requirement.

Jamf supports non-compiled AppleScript files natively, and you can use them in your Policies like any other script.

JXA in Jamf Pro Extension Attributes

Same deal; specify the Script type for the Extension Attribute, and include the JavaScript language flag shebang. Ensure your function returns the required <result></result> wrapper surrounding the output. You can do that with simple string concatenation using the plus operator, like this:

#!/usr/bin/osascript -l JavaScript

function run() {
	var app = Application.currentApplication();
	app.includeStandardAdditions = true;
	return "<result>" + app.systemInfo().cpuType + "</result>";

This will output <result>ARM64E</result>, for example, which will show up on your computer's inventory record during the next device inventory.


That's it. Hopefully this helps you store and run JavaScript for Automation scripts.

How to Parse JSON on the macOS Command Line Without External Tools Using JavaScript for Automation

JSON – JavaScript Object Notation – is the lingua franca for shipping data between systems. Everything from software APIs to web services commonly support, and typically default to, outputting data in JSON format.

Because of its ubiquity, you're bound to run into a need to manipulate a chunk of JSON in the course of managing your fleet.

For example, you might run a shell script on your Macs that instructs them to read data from an external system via its API using curl. That external system returns a big ol' heap of JSON, but you need to extract only a single data point from that payload, then act on that value.

This is somewhat of a challenge in the shell because macOS does not include any native or pre-installed tools to help you hack down that JSON. Administrators often resort to workarounds like shelling out to Python or using sed and awk to approximate parsing.

However, another, native solution is right there in the name: use JavaScript.

How to Disable iCloud Private Relay in macOS Monterey

Apple recently introduced iCloud Private Relay as an additional benefit for iCloud+ subscribers. The feature routes Safari web browsing (and some other insecure Internet traffic) through a semi-anonymizing service to reduce third parties' ability to profile and track individual users.

However, it may be necessary in some environments to disable iCloud Private Relay. The feature may interfere with management controls, prevent required traffic auditing, or complicate troubleshooting procedures.

Apple provides a guide to prepare your network or service for iCloud Private Relay, but it's also possible to disable the feature using a Restrictions Configuration Profile.

Personal Notes for Autumn 2021

I haven't posted in the last six months because I've been pretty busy. I have three pieces of personal news to share about what I've been up to.

  1. My wife and I welcomed our daughter to the world. Becoming her father is the biggest privilege of my life, and she teaches me daily how to be a better person.

    She is also – objectively – the best baby ever.

  2. I started a new role at Lyft. My primary focus is managing our global fleet of Apple devices, and helping build the world's best transportation. I'm really enjoying the new challenges, and I'm fortunate to be part of an awesome team.

    This will obviate some references in older articles where I discussed technical implementations at my previous employer. My goal in future articles is to write more "evergreen" pieces that are more broadly applicable.

  3. I redesigned this site. My goals were to increase the focus on the articles and improve legibility on mobile devices. The site also supports both "light" and "dark" color palettes that adapt to your system-wide preference. For boring reasons, I changed the static site software I use from Hugo to Zola. I hope you enjoy the new look.

More to follow soon!