How to Check PKFail Vulnerability on Linux with Shell Script

System firmware vulnerabilities pose significant risks to device integrity, especially in environments where security compliance and trust are non-negotiable. The PKFail vulnerability, recently disclosed in several major advisories, affects the Platform Key (PK) used in Secure Boot processes. This makes it critical for IT professionals and Managed Service Providers (MSPs) to validate whether devices are operating with trusted Secure Boot configurations. Fortunately, with the help of a well-designed shell script, you can learn how to check PKFail Vulnerability on Linux, as this process can be automated and integrated into existing IT management workflows.

Background

The PKFail vulnerability (BRLY-2024-005) stems from compromised or untrusted Platform Keys embedded in UEFI Secure Boot firmware. The use of compromised keys can render Secure Boot protections ineffective, exposing systems to potential rootkit or bootkit infections.

Vendors like Intel and Supermicro have acknowledged the issue and advised customers to inspect system keys for indicators like “DO NOT TRUST” or “DO NOT SHIP.” For IT teams managing fleets of devices, particularly in compliance-heavy sectors, manually checking each endpoint is impractical. This is where automation with a shell script becomes invaluable.

The script in focus addresses this need by automating the process of checking the Secure Boot PK for untrusted certificate names and optionally saving the result to a NinjaOne custom field. It provides a repeatable, lightweight way to detect potential exposure to PKFail.

The Script

#!/usr/bin/env bash

# Description: Checks for the PKFail vulnerability.
# By using this script, you indicate your acceptance of the following legal terms as well as our Terms of Use at https://www.ninjaone.com/terms-of-use.
# Ownership Rights: NinjaOne owns and will continue to own all right, title, and interest in and to the script (including the copyright). NinjaOne is giving you a limited license to use the script in accordance with these legal terms. 
# Use Limitation: You may only use the script for your legitimate personal or internal business purposes, and you may not share the script with another party. 
# Republication Prohibition: Under no circumstances are you permitted to re-publish the script in any script library or website belonging to or under the control of any other software provider. 
# Warranty Disclaimer: The script is provided “as is” and “as available”, without warranty of any kind. NinjaOne makes no promise or guarantee that the script will be free from defects or that it will meet your specific needs or expectations. 
# Assumption of Risk: Your use of the script is at your own risk. You acknowledge that there are certain inherent risks in using the script, and you understand and assume each of those risks. 
# Waiver and Release: You will not hold NinjaOne responsible for any adverse or unintended consequences resulting from your use of the script, and you waive any legal or equitable rights or remedies you may have against NinjaOne relating to your use of the script. 
# EULA: If you are a NinjaOne customer, your use of the script is subject to the End User License Agreement applicable to you (EULA).
#
# Release Notes: Initial Release
#
# Checks keys for CNs with 'DO NOT TRUST' or 'DO NOT SHIP' and can save the result to a custom field.
# Requires the efitools package to be installed.
#
# Usage: [--customfield|-c <CustomFieldName>]
#
# Example:
#   --customfield "SecureBootPK"
#
#   [Info] Secure Boot is Trusted
#   [Info] Custom field value set successfully
#
# Example:
#   --customfield "SecureBootPK"
#
#   [Alert] Secure Boot is Not Trusted
#   [Info] Custom field value set successfully
#
# Links:
#     https://github.com/binarly-io/Vulnerability-REsearch/blob/main/PKfail/BRLY-2024-005.md
#     https://www.intel.com/content/www/us/en/security-center/announcement/intel-security-announcement-2024-07-25-001.html
#     https://www.supermicro.com/en/support/security_PKFAIL_Jul_2024
#

# These are all our preset parameter defaults. You can set these = to something if you would prefer the script defaults to a certain parameter value.
_arg_customfield=

# Help text function for when invalid input is encountered
print_help() {
    printf '\n\n%s\n\n' 'Usage: [--customfield|-c <arg>] [--help|-h]'
    printf '%s\n' 'Preset Parameter: --customfield "SecureBootPK"'
    printf '\t%s\n' "Name of a custom field to save the PKFail status to with either Trusted or Not Trusted."
}

# Determines whether or not help text is necessary and routes the output to stderr
die() {
    local _ret="${2:-1}"
    test "${_PRINT_HELP:-no}" = yes && print_help >&2
    echo "$1" >&2
    exit "${_ret}"
}

# Grabbing the parameters and parsing through them.
parse_commandline() {
    while test $# -gt 0; do
        _key="$1"
        case "$_key" in
        --customfield | -c)
            test $# -lt 2 && die "Missing value for the optional argument '$_key'." 1
            _arg_customfield="$2"
            shift
            ;;
        --customfield=*)
            _arg_customfield="${_key##--customfield=}"
            ;;
        --help | -h)
            _PRINT_HELP=yes die 0
            ;;
        *)
            _PRINT_HELP=yes die "FATAL ERROR: Got an unexpected argument '$1'" 1
            ;;
        esac
        shift
    done
}

SetCustomField() {
    local _Name=$1
    local _Value=$2
    if [ -f "${NINJA_DATA_PATH}/ninjarmm-cli" ]; then
        if [ -x "${NINJA_DATA_PATH}/ninjarmm-cli" ]; then
            if "$NINJA_DATA_PATH"/ninjarmm-cli get "$_Name" >/dev/null; then
                # check if the value is greater than 10000 characters
                if [ ${#_Value} -gt 10000 ]; then
                    echo "[Warn] Custom field value is greater than 10000 characters"
                fi
                if ! echo "${_Value::10000}" | "$NINJA_DATA_PATH"/ninjarmm-cli set --stdin "$_Name"; then
                    echo "[Warn] Failed to set custom field"
                else
                    echo "[Info] Custom field value set successfully"
                fi
            else
                echo "[Warn] Custom Field ($_Name) does not exist or agent does not have permission to access it"
            fi
        else
            echo "[Warn] ninjarmm-cli is not executable"
        fi
    else
        echo "[Warn] ninjarmm-cli does not exist"
    fi
}

parse_commandline "$@"

# If script form is used replace commandline arguments
if [[ -n $customFieldName ]] && [[ "${customFieldName}" != "null" ]]; then
    _arg_customfield="$customFieldName"
fi

if ! [ -d "/sys/firmware/efi" ]; then
    die "[Error] System is not running in UEFI mode." 1
fi

# Check that efi-readvar is installed
if ! command -v efi-readvar &>/dev/null; then
    die "[Error] efi-readvar is not installed. Please install efitools and try again." 1
fi

_trusted="Not Trusted"

# Check if Secure Boot is supported on the system and if it is, output the result
output=$(efi-readvar -v PK)
if [[ -n $output ]]; then
    if [[ "$output" == *"DO NOT TRUST"* ]] || [[ "$output" == *"DO NOT SHIP"* ]]; then
        echo "[Alert] Secure Boot is Not Trusted"
    else
        echo "[Info] Secure Boot is Trusted"
        _trusted="Trusted"
    fi
else
    die "efi-readvar returned no output. Secure Boot is not enabled or supported on this system." 1
fi

# Check if the custom field is set and if it is, output the result
if [[ -n $_arg_customfield ]]; then
    SetCustomField "${_arg_customfield}" "${_trusted}"
fi

 

Detailed Breakdown

This shell script is purpose-built to:

  1. Validate Input Parameters
    It accepts an optional –customfield argument that specifies a NinjaOne custom field to store the result.
  2. Check for UEFI Mode
    It ensures the system is booted in UEFI mode by verifying the presence of /sys/firmware/efi.
  3. Verify Prerequisites
    It checks for the efi-readvar utility (part of the efitools package), which is required to read UEFI variable contents.
  4. Read and Analyze the Platform Key (PK)
    The script uses efi-readvar -v PK to fetch the current Platform Key from firmware. It scans the output for disqualifying phrases like “DO NOT TRUST” or “DO NOT SHIP.”
  5. Determine Trust Status
    If either phrase is found, the script outputs an alert indicating the Platform Key is not trusted. Otherwise, it confirms that the Secure Boot configuration is trusted.
  6. Optional Result Persistence
    If a valid custom field is provided and ninjarmm-cli is available and executable, the script sets the field value to either “Trusted” or “Not Trusted,” providing a reliable record for later auditing or alerting.

Potential Use Cases

Case Study: Remote Compliance Check in a Healthcare MSP Environment

A healthcare-focused MSP managing over 500 endpoints across clinics needs to verify Secure Boot integrity for HIPAA compliance. Rolling out this script via NinjaOne’s automation platform, the MSP pushes a scheduled task that executes the script weekly. Results are stored in a custom field named SecureBootPK, providing centralized visibility across the entire device fleet. This allows IT leadership to quickly identify and remediate machines with compromised PKs—without manually touching each device.

Comparisons

Manual Inspection

Without a script, technicians would need to boot into UEFI firmware settings or run efi-readvar manually on each endpoint. This is both time-consuming and error-prone.

Other Tools

Tools like Microsoft’s Secure Boot configuration toolset are available, but they are Windows-centric and may not cover Linux environments. The shell script described here provides a lightweight, platform-specific solution for Linux systems.

FAQs

Q: What is PKFail?

A: PKFail refers to a vulnerability where the Platform Key used in Secure Boot includes identifiers like “DO NOT TRUST,” indicating it may be insecure or tampered with.

Q: What if my system doesn’t support Secure Boot?

A: The script will exit with an error if /sys/firmware/efi is not present, indicating the system is not in UEFI mode.

Q: What happens if the custom field doesn’t exist in NinjaOne?

A: The script gracefully handles this by issuing a warning. It checks whether ninjarmm-cli can access and set the field before attempting to update it.

Q: Can this script be used on non-NinjaOne-managed systems?

A: Yes. The core functionality works independently of NinjaOne. The custom field portion is optional.

Implications

The results of this script carry serious weight in an IT security context. A “Not Trusted” result indicates a high-risk system that could bypass Secure Boot protections, potentially allowing malware to persist below the OS level. This can lead to data breaches, compliance failures, or operational downtime.

Worse, undetected PKFail vulnerabilities in production environments can serve as a beachhead for advanced persistent threats (APTs), especially in critical infrastructure and enterprise environments.

Recommendations

  • Automate the Check
    Integrate the script into your RMM or compliance workflows for continuous validation.
  • Educate Your Team
    Ensure technicians understand the significance of PK integrity and know how to act on the script’s output.
  • Verify efi-readvar Availability
    Pre-deploy efitools on all managed systems to ensure the script functions as expected.
  • Use Descriptive Custom Field Names
    Label custom fields clearly (e.g., SecureBootPKStatus) to avoid confusion in multi-field environments.

Final Thoughts

For IT professionals and MSPs leveraging NinjaOne, this script serves as a lightweight but powerful tool for security validation. By combining UEFI variable analysis with custom field reporting, teams gain actionable insights into Secure Boot status across distributed Linux systems.

This is a prime example of how custom scripting within NinjaOne can deliver targeted, automated solutions to emerging cybersecurity challenges. As firmware-based vulnerabilities grow more sophisticated, tools like this enable proactive defense—ensuring trust starts at the boot level.

Next Steps

Building an efficient and effective IT team requires a centralized solution that acts as your core service delivery tool. NinjaOne enables IT teams to monitor, manage, secure, and support all their devices, wherever they are, without the need for complex on-premises infrastructure.

Learn more about NinjaOne Remote Script Deployment, check out a live tour, or start your free trial of the NinjaOne platform.

Categories:

You might also like

×

See NinjaOne in action!

By submitting this form, I accept NinjaOne's privacy policy.

NinjaOne Terms & Conditions

By clicking the “I Accept” button below, you indicate your acceptance of the following legal terms as well as our Terms of Use:

  • Ownership Rights: NinjaOne owns and will continue to own all right, title, and interest in and to the script (including the copyright). NinjaOne is giving you a limited license to use the script in accordance with these legal terms.
  • Use Limitation: You may only use the script for your legitimate personal or internal business purposes, and you may not share the script with another party.
  • Republication Prohibition: Under no circumstances are you permitted to re-publish the script in any script library belonging to or under the control of any other software provider.
  • Warranty Disclaimer: The script is provided “as is” and “as available”, without warranty of any kind. NinjaOne makes no promise or guarantee that the script will be free from defects or that it will meet your specific needs or expectations.
  • Assumption of Risk: Your use of the script is at your own risk. You acknowledge that there are certain inherent risks in using the script, and you understand and assume each of those risks.
  • Waiver and Release: You will not hold NinjaOne responsible for any adverse or unintended consequences resulting from your use of the script, and you waive any legal or equitable rights or remedies you may have against NinjaOne relating to your use of the script.
  • EULA: If you are a NinjaOne customer, your use of the script is subject to the End User License Agreement applicable to you (EULA).