Report apps that use Location Services

Who’s Watching? Auditing macOS Location Services with Intune.

Last Updated on February 9, 2025 by Oktay Sari

In my ongoing mission to strengthen macOS device security with Microsoft Intune, today I’m focusing on macOS Location Services, and 2 recommendations from the CIS Level 2 benchmarks for macOS devices. We’ll explore recommendation 2.6.1.2 Ensure ‘Show Location Icon in Control Center when System Services Request Your Location’ Is Enabled and recommendation 2.6.1.3 Audit Location Services Access. I’m still working on the full Level 2 benchmarks and will soon update my Github with a lot of other scripts to help out. In the meantime, have a look at my previous post about securing macOS devices with custom security baselines based on CIS.

These two CIS recommendations don’t just beef up security, but they also bring transparency to the table, giving users and admins a front-row seat to see who’s snooping around for location data. So buckle up, because we’re about to explore why these settings matter, how to deploy them with Intune, and the nifty scripts I’ve cooked up to make your life easier.

Why Bother with Location Services Management

Sometimes, diving into specific configurations isn’t just about immediate usability, it’s about curiosity and discovery. I wanted to see what could be done, how far I could push configurations, and what insights could be gained from managing Location Services on macOS. Exploring these settings allowed me to understand the balance between privacy and control, and see how Intune could be leveraged to enhance visibility and security. It wasn’t just about whether these settings were necessary for every environment. This post is more about learning and personal development.

recommendation 2.6.1.2: Ensuring Visibility with Location Icons

When macOS system services or apps request location data, it’s crucial that users are notified via a visible icon in the Control Center. This fosters trust and ensures users are aware of location tracking activities, preventing any hidden processes from going unnoticed.

recommendation 2.6.1.3: Auditing Location Services Access

Many macOS features rely on Location Services to offer tailored information, from setting time zones and displaying local weather to enabling Find My Mac. Let’s face it, your macOS apps love knowing where you are. While location services add convenience, they can also pose privacy risks, particularly in sensitive environments like government or healthcare sectors.

By auditing which apps have access to Location Services, organizations can maintain a balance between usability and data security. If your devices are hanging out in sensitive spots (think government buildings or top-secret lairs), you’ll want to keep a close eye on who’s accessing that data.

Deploying the scripts with Intune

To streamline the management of Location Services settings, I’ve developed three scripts that can be deployed with Microsoft Intune. Here’s a breakdown of each script and its role in enhancing security.

1. Enabling the Location Services Icon

First up, we’re making sure that Location Services Icon shows up when system services or apps request your location. Just make sure you don’t blink….you might miss the action.

Although this one should make users aware of location services being used, it’s way up in the menu bar and it only lights up in color for just a few seconds… Anyway, I guess it’s better than nothing.

Script Overview:

  • Checks if the relevant plist file (com.apple.locationmenu.plist) exists.
  • Enables the ‘Show Location Icon’ setting if it is not already active.
  • Logs all actions for auditing purposes.
#!/bin/bash
#set -x
# -------------------------------------------------------------------------------------------------------------------------------
# Script to Ensure 'Show Location Icon in Control Center when System Services Request Your Location' Is Enabled
# CIS Benchmark Level 2 - 2.6.1.2 Ensure 'Show Location Icon in Control Center when System Services Request Your Location' Is Enabled
# -------------------------------------------------------------------------------------------------------------------------------
#
# -------------------------------------------------------------------------------------------------------------------------------
# WARNING: This script only works if you deploy it as a collection of scripts. You will need 3 scripts for this to work:
# 1- EnableLocationServiceIcon (optional but recommended)
# 2- audit_apps_using_Locationservices.sh
# 3- report_apps_using_Locationservices
# -------------------------------------------------------------------------------------------------------------------------------
#
# DISCLAIMER:
# This script is provided "as is" without warranties or guarantees of any kind. While it has been created to fulfill specific functions
# and has worked effectively for my personal requirements, its performance may vary in different environments or use-cases.
# Users are advised to employ this script at their own discretion and risk.
# No responsibility will be assumed for any direct, indirect, incidental, or consequential damages that may arise from its use.
# -------------------------------------------------------------------------------------------------------------------------------
#
# ALWAYS TEST it in a controlled environment before deploying it in your production environment!
#
# -------------------------------------------------------------------------------------------------------------------------------
# AUTHOR: Oktay Sari
# https://allthingscloud.blog
# https://github.com/oktay-sari/
#
# NOTE:
# This script is by no means perfect. I'm not an expert bash programmer.
# If you think you have a good idea to further enhance this script, then please reach out.
#
# SCRIPT VERSION/HISTORY:
# 06-02-2025 - Oktay Sari - Script version 1.0
#
# ROADMAP/WISHLIST:
#
# Requirements:
# MDM to deploy script
# -------------------------------------------------------------------------------------------------------------------------------

# Define variables
appname="EnableLocationIcon"
logandmetadir="/Library/Logs/Microsoft/IntuneScripts/$appname"
log="$logandmetadir/$appname.log"
plist_path="/Library/Preferences/com.apple.locationmenu.plist"

# Check if the log directory has been created
if [ -d "$logandmetadir" ]; then
    echo "$(date) | Log directory already exists - $logandmetadir"
else
    echo "$(date) | Creating log directory - $logandmetadir"
    mkdir -p $logandmetadir
fi

# Start logging
exec &> >(tee -a "$log")

# Begin Script Body
echo ""
echo "##############################################################"
echo "# $(date) | Starting running of script $appname"
echo "##############################################################"
echo ""

# Function to enable 'Show Location Icon for System Services'
function enable_location_icon {
    echo "$(date) | Checking if $plist_path exists."

    if [ -f "$plist_path" ]; then
        echo "$(date) | $plist_path exists. Checking current setting."
        current_setting=$(/usr/bin/defaults read "$plist_path" ShowSystemServices 2>/dev/null)

        if [[ "$current_setting" == "1" ]]; then
            echo "$(date) | 'Show Location Icon' is already enabled. No changes made."
        else
            echo "$(date) | 'Show Location Icon' is disabled or not set. Enabling now."
            /usr/bin/defaults write "$plist_path" ShowSystemServices -bool true
            chown root:wheel "$plist_path"
            chmod 644 "$plist_path"

            # Verify the change
            verify_setting=$(/usr/bin/defaults read "$plist_path" ShowSystemServices)
            if [[ "$verify_setting" == "1" ]]; then
                echo "$(date) | Successfully enabled 'Show Location Icon'."
            else
                echo "$(date) | Failed to enable 'Show Location Icon'. Please check manually."
            fi
        fi
    else
        echo "$(date) | $plist_path does not exist. Creating and enabling setting."
        /usr/bin/defaults write "$plist_path" ShowSystemServices -bool true
        chown root:wheel "$plist_path"
        chmod 644 "$plist_path"

        # Verify the change
        verify_setting=$(/usr/bin/defaults read "$plist_path" ShowSystemServices)
        if [[ "$verify_setting" == "1" ]]; then
            echo "$(date) | Successfully created $plist_path and enabled 'Show Location Icon'."
        else
            echo "$(date) | Failed to create $plist_path or enable 'Show Location Icon'. Please check manually."
        fi
    fi
}

# Execute the function
enable_location_icon

echo "$(date) | Script completed. 'Show Location Icon' setting has been applied."

2. Auditing Apps Using Location Services

This script audits all apps that have accessed Location Services and compiles them into a readable plist file. It’ s like the detective in our script trio. It provides administrators with a clear overview of which apps are utilizing location data.

Script Overview:

  • Converts the clients.plist from binary to XML for easier parsing.
  • Extracts bundle IDs of apps authorized to use Location Services.
  • Resolves bundle IDs to app names and writes them to a plist file (com.company.locationapps.plist).
#!/bin/bash
#set -x
# -------------------------------------------------------------------------------------------------------------------------------
#
# -------------------------------------------------------------------------------------------------------------------------------
# WARNING: This script only works if you deploy it as a collection of scripts. You will need 3 scripts for this to work:
# 1- EnableLocationServiceIcon (optional but recommended)
# 2- audit_apps_using_Locationservices.sh
# 3- report_apps_using_Locationservices
# -------------------------------------------------------------------------------------------------------------------------------
#
# DISCLAIMER:
# This script is provided "as is" without warranties or guarantees of any kind. While it has been created to fulfill specific functions
# and has worked effectively for my personal requirements, its performance may vary in different environments or use-cases.
# Users are advised to employ this script at their own discretion and risk.
# No responsibility will be assumed for any direct, indirect, incidental, or consequential damages that may arise from its use.
# -------------------------------------------------------------------------------------------------------------------------------
# ALWAYS TEST it in a controlled environment before deploying it in your production environment!
#
# -------------------------------------------------------------------------------------------------------------------------------
# AUTHOR: Oktay Sari
# https://allthingscloud.blog
# https://github.com/oktay-sari/
#
# NOTE:
# This script is by no means perfect. I'm not an expert bash programmer.
# If you think you have a good idea to further enhance this script, then please reach out.
#
# SCRIPT VERSION/HISTORY:
# 06-02-2025 - Oktay Sari - Script version 1.0
#
# ROADMAP/WISHLIST:
#
# Requirements:
# MDM to deploy script
#
# Why use plist files instead of log files?
# -------------------------------------------------------------------------------------------------------------------------------
# Plist files offer structured, standardized data storage that integrates natively with macOS and MDM solutions like Intune.
# They allow for consistent parsing and structured reporting, making them ideal for environments where data integrity and
# easy retrieval are critical. Unlike log files, which are unstructured and prone to formatting inconsistencies,
# plist files maintain a predictable format that ensures compatibility with automated systems.
# -------------------------------------------------------------------------------------------------------------------------------
# Define variables
# Path to the Location Services database and temporary XML file
LS_DB="/var/db/locationd/clients.plist"
XML_DB="/tmp/clients.xml"
OUTPUT_FILE="/Library/Preferences/com.company.locationapps.plist"

# Step 1: Check if the Location Services database exists
if [ ! -f "$LS_DB" ]; then
    echo "Location Services Database not found at $LS_DB"
    exit 1
fi

# Step 2: Convert the binary plist to an XML format
# This is necessary because the original plist is in a binary format, which is not human-readable and cannot be easily parsed.
# Converting it to XML allows us to extract and manipulate the data more effectively.
plutil -convert xml1 -o "$XML_DB" "$LS_DB"

# Step 3: Initialize an empty array to store the names of authorized apps
authorized_apps=()

# Step 4: Filter out non-UTF-8 characters and parse authorized apps
while IFS= read -r bundle_id; do
    echo "Processing bundle ID: $bundle_id"
    app_path=$(mdfind "kMDItemCFBundleIdentifier == '$bundle_id'" | head -n 1)
    if [ -n "$app_path" ]; then
        app_name=$(mdls -name kMDItemDisplayName -raw "$app_path")
        if [ -z "$app_name" ]; then
            app_name=$(mdls -name kMDItemCFBundleName -raw "$app_path")
        fi
        if [ -z "$app_name" ]; then
            app_name=$(mdls -name kMDItemFSName -raw "$app_path")
        fi

        if [ -n "$app_name" ]; then
            echo "Found app: $app_name ($bundle_id)"
            authorized_apps+=("$app_name ($bundle_id)")
        else
            echo "Found app path but no display name for $bundle_id"
            authorized_apps+=("$bundle_id (No app display name found)")
        fi
    else
        echo "No app path found for $bundle_id"
        authorized_apps+=("$bundle_id (No app display name found)")
    fi

done < <(
    /usr/libexec/PlistBuddy -c "Print" "$XML_DB" | iconv -f UTF-8 -t UTF-8//IGNORE | 
    awk '
        BEGIN { authorized = 0; bundle_id = "" }
        /BundleId =/ { bundle_id = $3 }
        /Authorized = true/ {
            if (bundle_id != "") {
                print bundle_id
                bundle_id = ""
            } else {
                authorized = 1
            }
        }
        /^[^ ]/ {
            if (authorized && bundle_id != "") {
                print bundle_id
                authorized = 0
                bundle_id = ""
            }
        }
    '
)

# Step 5: Debugging - Check if the output file exists before creating a new one
# This step ensures we're aware if an existing plist file is already present. This can help in troubleshooting or verifying that the script is running as expected.
if ls -l "$OUTPUT_FILE"; then
    echo "DEBUG: File is visible to the script."
else
    echo "DEBUG: File is NOT visible to the script."
fi

# Step 6: Ensure the output file is freshly created on every run
# Removing the old plist ensures that no outdated or duplicate data remains. This guarantees that the plist only contains the most current information.
if [ -f "$OUTPUT_FILE" ]; then
    echo "Existing plist found. Removing it to create a fresh one."
    rm "$OUTPUT_FILE"
else
    echo "File Doesn't Exist, Will Create: $OUTPUT_FILE"
fi

# Step 7: Create a new plist with the required structure
# We initialize the plist with an 'AuthorizedApps' array to store the list of apps. This structure is required for consistent data formatting.
echo "Creating new plist file at $OUTPUT_FILE"
/usr/libexec/PlistBuddy -c "Add :AuthorizedApps array" "$OUTPUT_FILE"

# Step 8: Set permissions to ensure future detection and access
# Setting appropriate permissions ensures the file is readable and writable by system processes that may need to access or update it.
chmod 644 "$OUTPUT_FILE"
chown root:wheel "$OUTPUT_FILE"

# Confirm permissions to verify that they were set correctly
ls -l "$OUTPUT_FILE"

# Step 9: Populate the plist with the authorized apps
for app in "${authorized_apps[@]}"; do
    echo "Adding to plist: $app"
    /usr/libexec/PlistBuddy -c "Add :AuthorizedApps: string $app" "$OUTPUT_FILE"
done

# Step 10: Final confirmation message
echo "Location Services apps have been written to $OUTPUT_FILE"

3. Reporting Apps Using Location Services

Last but not least, we’ve got the reporter. This custom attribute script is designed for reporting purposes within Intune. It reads the plist file generated by the audit script and outputs the list of apps using Location Services.

A screenshot of a computer AI-generated content may be incorrect.

Script Overview:

  • Reads from com.company.locationapps.plist.
  • Outputs the list of authorized apps to the console for reporting in Intune.
#!/bin/bash
#set -x
# -------------------------------------------------------------------------------------------------------------------------------
# WARNING: This script only works if you deploy it as a collection of scripts. You will need 3 scripts for this to work:
# 1- EnableLocationServiceIcon (optional but recommended)
# 2- audit_apps_using_Locationservices.sh
# 3- report_apps_using_Locationservices
# -------------------------------------------------------------------------------------------------------------------------------
#
# DISCLAIMER:
# This script is provided "as is" without warranties or guarantees of any kind. While it has been created to fulfill specific functions
# and has worked effectively for my personal requirements, its performance may vary in different environments or use-cases.
# Users are advised to employ this script at their own discretion and risk.
# No responsibility will be assumed for any direct, indirect, incidental, or consequential damages that may arise from its use.
# -------------------------------------------------------------------------------------------------------------------------------
#
# ALWAYS TEST it in a controlled environment before deploying it in your production environment!
#
# -------------------------------------------------------------------------------------------------------------------------------
# AUTHOR: Oktay Sari
# https://allthingscloud.blog
# https://github.com/oktay-sari/
#
# NOTE:
# This script is by no means perfect. I'm not an expert bash programmer.
# If you think you have a good idea to further enhance this script, then please reach out.
#
# SCRIPT VERSION/HISTORY:
# 06-02-2025 - Oktay Sari - Script version 1.0
#
# ROADMAP/WISHLIST:
#
# Requirements:
# MDM to deploy script
# -------------------------------------------------------------------------------------------------------------------------------

# Define variables

OUTPUT_FILE="/Library/Preferences/com.company.locationapps.plist"

if [ -f "$OUTPUT_FILE" ]; then
    authorized_apps=$(defaults read "$OUTPUT_FILE" AuthorizedApps)
    echo "Authorized Apps: $authorized_apps"
else
    echo "No apps found using Location Services."
fi

Privacy Considerations

While auditing Location Services access is crucial for maintaining security, it’s important to acknowledge potential privacy concerns. Listing all applications that access location data could inadvertently expose sensitive information about how a user interacts with their device. It’s like peeking into a user’s diary. It’s useful, but let’s tread carefully.

Potential Privacy Risks:

  • User Concerns: Even with the best intentions, users might feel uneasy knowing administrators can see which apps are accessing their location.
  • Data Sensitivity: In certain environments, revealing specific app names could unintentionally disclose sensitive details.

Mitigation Strategies:

  • Visibility in Intune Device Blade: It’s worth noting that apps are already visible in the Intune device blade. However, additional custom reporting might raise further concerns.
  • Anonymizing Data: Future script enhancements could focus on anonymizing this data. For instance, instead of listing actual app names in custom attributes, we could report only the number of apps using Location Services. This approach maintains oversight while respecting individual privacy.

Future Script Enhancements

The scripts are great, but there’s always room to level up. Here are a few ideas to take things to the next level:

  1. Anonymized Reporting: Modify the reporting script to display only the count of apps using Location Services rather than their names. This offers a high-level overview without compromising privacy.
  2. Granular Permissions: Introduce logic to differentiate between system services and third-party apps, providing more nuanced reporting.
  3. Automated Alerts: Notify administrators when new apps request location access.
  4. Scheduled Audits: Automate the auditing process to run at regular intervals, ensuring continuous monitoring without administrative overhead.
  5. Keep a list of approved apps and alert only on unknown/not approved apps

Deploying via Microsoft Intune

Step-by-Step Deployment Guide:

  1. Upload the Scripts to Intune:
    • Navigate to Devices > macOS > Scripts in Microsoft Intune.
    • Add the first 2 script individually, ensuring they are assigned to the appropriate device groups.
    • Navigate to Devices > macOS > Custom Attributes, upload the reporting script and assign that one to your devices too.
  2. Monitor Deployment:
    • Use Intune’s reporting features to verify successful script execution.
    • The reporting scripts will provide feedback on which apps are accessing Location Services.
  3. Adjust Policies as Needed:
    • Based on audit results, adjust app permissions or inform users about potential privacy implications.

Conclusion

Managing Location Services on macOS isn’t just about locking things down—it’s about striking a balance between security and usability. With the Location Services Icon showing who’s watching, and audits keeping tabs on app behavior, you’re in full control without going full-on surveillance mode.

But remember, with great power comes great responsibility. Keep privacy in mind, anonymize when possible, and always stay transparent with your users. Adoption and communication can help address these challenges effectively.

Stay tuned for more insights as we continue to explore and implement CIS Level 2 benchmarks for macOS with Microsoft Intune. If you have any suggestions or improvements for these scripts, feel free to reach out or contribute via GitHub.

5 1 vote
Article Rating

Oktay Sari

#Microsoft365 | #Intune |#MEM | #Security | Father | #Diver | #RC Pilot & #Magician in spare time | Microsoft MVP

Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

1 Comment
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
trackback

[…] This suite helps you track which apps are trying to pull a GPS stalker move on your devices. Here’s a full blog post explaining what what it does:Who’s Watching? Auditing macOS Location Services with Intune […]