{"id":19070,"date":"2026-04-30T09:35:50","date_gmt":"2026-04-30T09:35:50","guid":{"rendered":"https:\/\/truehost.com\/support\/?p=19070"},"modified":"2026-05-06T10:38:09","modified_gmt":"2026-05-06T10:38:09","slug":"cpanel-security-patch-truehost-cloud-client-guide","status":"publish","type":"post","link":"https:\/\/www.truehost.com\/support\/cpanel-security-patch-truehost-cloud-client-guide\/","title":{"rendered":"cPanel Security Patch"},"content":{"rendered":"\n<p>Truehost Cloud &nbsp;\u00b7&nbsp; cPanel VPS Security Advisory<\/p>\n\n\n\n<h1 class=\"wp-block-heading\">Critical cPanel Security Patch \u2014 Required Actions for Your VPS<\/h1>\n\n\n\n<p>A serious security vulnerability has been identified in cPanel. This guide walks you through exactly what to do to protect your server.<\/p>\n\n\n\n<p>Published: April 30, 2026 &nbsp;\u00b7&nbsp; Affected: cPanel all versions after 11.40 &nbsp;\u00b7&nbsp; Truehost Cloud<\/p>\n\n\n\n<p>\ud83d\udea8 <strong>Urgent Security Alert:<\/strong> A critical authentication bypass vulnerability has been identified in cPanel affecting all versions after 11.40. If left unpatched, an attacker can bypass your login screen and gain full administrative control of your server \u2014 including all hosted websites, databases, and email accounts. <strong>Apply the patch immediately by following the steps in this guide.<\/strong><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">In This Guide<\/h2>\n\n\n\n<ol class=\"wp-block-list\">\n<li><a href=\"#what-happened\">What Happened and Who is Affected<\/a><\/li>\n\n\n\n<li><a href=\"#access-cpanel\">Accessing Your cPanel<\/a><\/li>\n\n\n\n<li><a href=\"#update\">Step-by-Step: Update cPanel Now<\/a><\/li>\n\n\n\n<li><a href=\"#mitigation\">If You Cannot Update Right Now<\/a><\/li>\n\n\n\n<li><a href=\"#detection\">Check if Your Server Was Already Compromised<\/a><\/li>\n\n\n\n<li><a href=\"#compromised\">If Your Server Was Compromised \u2014 Immediate Actions<\/a><\/li>\n\n\n\n<li><a href=\"#legacy\">Warning for Unsupported cPanel Versions<\/a><\/li>\n\n\n\n<li><a href=\"#reinstall\">Reinstalling cPanel (Last Resort)<\/a><\/li>\n\n\n\n<li><a href=\"#checklist\">Summary Checklist<\/a><\/li>\n\n\n\n<li><a href=\"#help\">Need Help? Contact Truehost Support<\/a><\/li>\n<\/ol>\n\n\n\n<h2 class=\"wp-block-heading\"><a id=\"what-happened\"><\/a>1. What Happened and Who is Affected<\/h2>\n\n\n\n<p>A serious <strong>authentication bypass security vulnerability<\/strong> has been discovered in cPanel software \u2014 including cPanel and DNSOnly \u2014 affecting <strong>all versions after 11.40<\/strong>. The cPanel security team confirmed the issue on April 28, 2026 and has released emergency patches.<\/p>\n\n\n\n<p>If this vulnerability is exploited on your server, an attacker could:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Bypass the login screen and gain admin access <strong>without a password<\/strong><\/li>\n\n\n\n<li>Access and modify all websites, databases, and email accounts on your server<\/li>\n\n\n\n<li>Install malware, ransomware, or backdoors<\/li>\n\n\n\n<li>Steal confidential customer data<\/li>\n\n\n\n<li>Use your server to send spam or launch attacks on other systems<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Which cPanel Versions Are Safe?<\/h3>\n\n\n\n<p>The following versions have been patched and are safe. Your server must be running one of these versions:<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>Safe Patched Version<\/th><th>Notes<\/th><\/tr><\/thead><tbody><tr><td><code>11.86.0.41<\/code><\/td><td>Patched<\/td><\/tr><tr><td><code>11.110.0.97<\/code><\/td><td>Patched<\/td><\/tr><tr><td><code>11.118.0.63<\/code><\/td><td>Patched<\/td><\/tr><tr><td><code>11.126.0.54<\/code><\/td><td>Patched<\/td><\/tr><tr><td><code>11.130.0.19<\/code><\/td><td>Patched<\/td><\/tr><tr><td><code>11.132.0.29<\/code><\/td><td>Patched<\/td><\/tr><tr><td><code>11.134.0.20<\/code><\/td><td>Patched<\/td><\/tr><tr><td><code>11.136.0.5<\/code><\/td><td>Patched<\/td><\/tr><tr><td><code>136.1.7<\/code><\/td><td>WP Squared \u2014 Patched<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p>\u26a0\ufe0f <strong>Not sure which version you are running?<\/strong> You can check it in Section 3 Step 2. If you are unsure or unable to check, raise a support ticket immediately and our team will check and update your server for you.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><a id=\"access-cpanel\"><\/a>2. Accessing Your cPanel<\/h2>\n\n\n\n<p>Before you can apply the security patch you need to access your server. There are two ways to do this \u2014 via the browser or via SSH. For the security update, <strong>SSH is required<\/strong>.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Accessing cPanel\/WHM (Browser)<\/h3>\n\n\n\n<p>Your cPanel\/WHM dashboard is accessible at:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><mark class=\"has-inline-color has-vivid-green-cyan-color\">https:\/\/YOUR_SERVER_IP:2083<\/mark> -for cpanel\n<mark class=\"has-inline-color has-vivid-green-cyan-color\">https:\/\/YOUR_SERVER_IP:2087<\/mark> - for WHM\n<\/code><\/pre>\n\n\n\n<p>Log in with the username and password from your Truehost welcome email.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Accessing Your Server via SSH (Required for Security Update)<\/h3>\n\n\n\n<p>The security patch must be applied via SSH on the command line. Here is how to connect:<\/p>\n\n\n\n<p><strong>On macOS or Linux<\/strong> \u2014 open Terminal and run:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><mark class=\"has-inline-color has-vivid-green-cyan-color\">ssh root@YOUR_VPS_IP_ADDRESS<\/mark><\/code><\/pre>\n\n\n\n<p><strong>On Windows<\/strong> \u2014 use PuTTY (<a href=\"https:\/\/putty.org\" target=\"_blank\" rel=\"noreferrer noopener\">putty.org<\/a>) or Windows Terminal. Enter your VPS IP as the host and log in as <code>root<\/code>.<\/p>\n\n\n\n<p>Enter your root password from your welcome email when prompted.<\/p>\n\n\n\n<p>\ud83d\udca1 <strong>Cannot access your server via SSH?<\/strong> Raise a support ticket at <strong>your client area <\/strong>\u2192 <strong>Support \u2192 Open Ticket<\/strong> and our team will apply the security update on your behalf.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><a id=\"update\"><\/a>3. Step-by-Step: Update cPanel Now<\/h2>\n\n\n\n<p>Once connected to your server via SSH, follow these steps in order. Do not skip any step.<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>Run the forced update command<\/strong><br>This fetches and installs the latest patched version of cPanel directly from the official repositories. The process may take several minutes \u2014 do not interrupt it. <code><mark style=\"background-color:#abb8c3\" class=\"has-inline-color\">\/scripts\/upcp --force<\/mark><\/code><\/li>\n\n\n\n<li><strong>Verify the installed version<\/strong><br>Once the update completes, confirm that your server is now running a patched version: <mark style=\"background-color:#abb8c3\" class=\"has-inline-color\"><code>\/usr\/local\/cpanel\/cpanel -V<\/code> <\/mark>The output should show one of the safe versions listed in Section 1. If it does not, raise a support ticket immediately.<\/li>\n\n\n\n<li><strong>Restart the cPanel service<\/strong><br>A clean restart ensures the new patched code is fully loaded and active: <code><mark style=\"background-color:#abb8c3\" class=\"has-inline-color\">\/scripts\/restartsrv_cpsrvd<\/mark><\/code><\/li>\n\n\n\n<li><strong>Re-enable automatic updates (if you had them disabled)<\/strong><br>If you previously disabled cPanel automatic updates or pinned your server to a specific version, the forced update above may not have worked as expected. Re-enable automatic updates to ensure you receive future security patches automatically. For instructions see: <a href=\"https:\/\/docs.cpanel.net\/knowledge-base\/general-systems-administration\/how-to-customize-cpanels-update-preferences-from-the-command-line\/\" target=\"_blank\" rel=\"noreferrer noopener\">How to customize cPanel Update Preferences from the Command Line<\/a>.<\/li>\n<\/ol>\n\n\n\n<p>\u2705 <strong>Update complete.<\/strong> Once these four steps are done your server is protected against the authentication bypass vulnerability. Continue to Section 5 to check whether your server was attacked before the patch was applied.<\/p>\n\n\n\n<p>\u2139\ufe0f <strong>Stuck on any step?<\/strong> Raise a support ticket at <strong>your client area <\/strong>\u2192 <strong>Support \u2192 Open Ticket<\/strong> and our team will complete the update for you.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><a id=\"mitigation\"><\/a>4. If You Cannot Update Right Now<\/h2>\n\n\n\n<p>If you are unable to run the update immediately \u2014 for example due to a legacy operating system or a dependency conflict \u2014 apply one of the following temporary mitigations to block the attack vector while you arrange the update. These are <strong>not permanent fixes<\/strong> \u2014 you must still update as soon as possible.<\/p>\n\n\n\n<p>\u26a0\ufe0f <strong>These mitigations are temporary only.<\/strong> They reduce your exposure but do not fix the underlying vulnerability. Apply the full update in Section 3 as soon as you can.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Option A \u2014 Block the Vulnerable Ports at the Firewall<\/h3>\n\n\n\n<p>Block inbound traffic on the ports used by cPanel. This prevents anyone from accessing the panel from outside the server until you can apply the patch:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><mark style=\"background-color:#abb8c3\" class=\"has-inline-color\">iptables -A INPUT -p tcp --dport 2083 -j DROP\niptables -A INPUT -p tcp --dport 2087 -j DROP\niptables -A INPUT -p tcp --dport 2095 -j DROP\niptables -A INPUT -p tcp --dport 2096 -j DROP<\/mark><\/code><\/pre>\n\n\n\n<p>Save the rules according to your firewall manager (iptables-save, UFW, or CSF).<\/p>\n\n\n\n<p>\u26a0\ufe0f <strong>Note:<\/strong> Blocking these ports will make your cPanel dashboard inaccessible from the browser. You will still be able to manage the server via SSH.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Option B \u2014 Stop the Vulnerable cPanel Services<\/h3>\n\n\n\n<p>Alternatively, stop the cpsrvd and cpdavd services entirely:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><mark style=\"background-color:#abb8c3\" class=\"has-inline-color\">whmapi1 configureservice service=cpsrvd enabled=0 monitored=0 &amp;&amp; \\\nwhmapi1 configureservice service=cpdavd enabled=0 monitored=0 &amp;&amp; \\\n\/scripts\/restartsrv_cpsrvd --stop &amp;&amp; \\\n\/scripts\/restartsrv_cpdavd --stop<\/mark><\/code><\/pre>\n\n\n\n<p>This completely stops the vulnerable services. Your cPanel interface will be unavailable until you reverse this by applying the update.<\/p>\n\n\n\n<p>\ud83d\udca1 <strong>Not sure which option to use?<\/strong> Raise a support ticket and our team will apply the mitigation and then the full update for you.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><a id=\"detection\"><\/a>5. Check if Your Server Was Already Compromised<\/h2>\n\n\n\n<p>Even after applying the patch, it is important to check whether your server was attacked before the patch was applied. The cPanel security team has provided an official detection script that scans your server for indicators of compromise (IOC). <strong>Run this even if you updated quickly<\/strong> \u2014 attacks can happen within minutes of a vulnerability being disclosed.<\/p>\n\n\n\n<p>\ud83d\udca1 <strong>Prefer to let us run this for you?<\/strong> Raise a support ticket at<a href=\"https:\/\/truehost.com\/support\/knowledge-base\/how-to-create-and-manage-tickets-from-truehost-client-area\/\"> here<\/a> and our team will run the detection script and report back to you with the results.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Step 1 \u2014 Create the Detection Script File<\/h3>\n\n\n\n<p>Connect to your server via SSH, then create the script file:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><mark style=\"background-color:#abb8c3\" class=\"has-inline-color\">nano ioc_checksessions_files.sh<\/mark><\/code><\/pre>\n\n\n\n<p>Copy and paste the full script below exactly as shown:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>#!\/bin\/bash\n# Scan for compromised cPanel\/WHM session files.\n#\n# Each check function inspects a single session file and, if the IOC\n# matches, calls report_finding with a severity. report_finding records\n# the finding, prints a one-line header, and dumps the session for triage.\n# A summary of all findings (grouped by severity) is printed at the end.\n\n\n# Default paths\nSESSIONS_DIR=\"\/var\/cpanel\/sessions\"\nACCESS_LOG=\"\/usr\/local\/cpanel\/logs\/access_log\"\n\n# Flags\nVERBOSE=0\nPURGE=0\nASSUME_YES=0\n\n# Parse flags\nwhile &#91; $# -gt 0 ]; do\n    case \"$1\" in\n        --verbose)\n            VERBOSE=1\n            ;;\n        --purge)\n            PURGE=1\n            ;;\n        --yes|-y)\n            ASSUME_YES=1\n            ;;\n        --sessions-dir)\n            SESSIONS_DIR=\"$2\"; shift\n            ;;\n        --access-log)\n            ACCESS_LOG=\"$2\"; shift\n            ;;\n        --help|-h)\n            echo \"Usage: $0 &#91;--verbose] &#91;--purge &#91;--yes]] &#91;--sessions-dir DIR] &#91;--access-log FILE]\"\n            exit 0\n            ;;\n        *)\n            echo \"Unknown argument: $1\" >&amp;2\n            exit 1\n            ;;\n    esac\n    shift\ndone\n\n# Findings accumulator. Each entry: \"SEVERITY|session_file|short_message\"\nFINDINGS=()\n# Ordered list of unique session files that produced findings.\nFINDING_SESSIONS=()\n# Parallel array: token value associated with each entry in FINDING_SESSIONS\n# (first non-empty token seen for that session).\nFINDING_TOKENS=()\n# Parallel array: highest severity reported for each session (by index)\nFINDING_SEVERITIES=()\nCOUNT_CRITICAL=0\nCOUNT_WARNING=0\nCOUNT_INFO=0\nCOUNT_ATTEMPT=0\n\n# ---------------------------------------------------------------------------\n# Helpers\n# ---------------------------------------------------------------------------\n\n# Extract the value of a key=value line from a session file (first match).\n# Use: get_field &lt;file> &lt;key>\nget_field() {\n    local file=\"$1\" key=\"$2\"\n    grep \"^${key}=\" \"$file\" | head -1 | cut -d= -f2-\n}\n\nhr() {\n    echo \"    ----------------------------------------------------------------\"\n}\n\n# Dump full contents of a session file plus related context (matching\n# pre-auth file, access_log hits for the injected token, file metadata).\n# Use: dump_session &lt;session_file> &#91;token_value]\ndump_session() {\n    local session_file=\"$1\"\n    local token_val=\"$2\"\n    local session_name preauth_file\n    session_name=$(basename \"$session_file\")\n    preauth_file=\"$SESSIONS_DIR\/preauth\/$session_name\"\n\n    hr\n    echo \"    SESSION DUMP: $session_file\"\n    hr\n    echo \"    File metadata:\"\n    ls -la \"$session_file\" 2>\/dev\/null | sed 's\/^\/      \/'\n    echo\n    echo \"    Full session contents:\"\n    sed 's\/^\/      \/' \"$session_file\"\n    echo\n\n    if &#91; -f \"$preauth_file\" ]; then\n        echo \"    Matching pre-auth file: $preauth_file\"\n        ls -la \"$preauth_file\" 2>\/dev\/null | sed 's\/^\/      \/'\n        echo \"    Pre-auth contents:\"\n        sed 's\/^\/      \/' \"$preauth_file\"\n        echo\n    fi\n\n    if &#91; -n \"$token_val\" ] &amp;&amp; &#91; -r \"$ACCESS_LOG\" ]; then\n        echo \"    Access log hits for token '$token_val':\"\n        grep -aF -- \"$token_val\" \"$ACCESS_LOG\" | sed 's\/^\/      \/' || echo \"      (none)\"\n        echo\n    fi\n    hr\n}\n\n# Record a finding and print a brief header line. The full session dump is\n# deferred to print_summary so that multiple findings for the same session\n# are grouped together and the session is only dumped once. When the same\n# session matches multiple IOCs at different severities, only the highest\n# (CRITICAL > WARNING > ATTEMPT > INFO) is kept.\n# Use: report_finding &lt;SEVERITY> &lt;session_file> &lt;token_value> &lt;message>\n# SEVERITY is one of: CRITICAL, WARNING, ATTEMPT, INFO\nreport_finding() {\n    local severity=\"$1\"\n    local session_file=\"$2\"\n    local token_val=\"$3\"\n    local message=\"$4\"\n\n    # Severity ranking: CRITICAL=3, WARNING=2, ATTEMPT=1, INFO=0\n    local sev_rank=0\n    case \"$severity\" in\n        CRITICAL) sev_rank=3 ;;\n        WARNING)  sev_rank=2 ;;\n        ATTEMPT)  sev_rank=1 ;;\n        INFO)     sev_rank=0 ;;\n    esac\n\n    local i found=0 prev_sev prev_rank\n    for i in \"${!FINDING_SESSIONS&#91;@]}\"; do\n        if &#91; \"${FINDING_SESSIONS&#91;$i]}\" = \"$session_file\" ]; then\n            found=1\n            prev_sev=\"${FINDING_SEVERITIES&#91;$i]}\"\n            case \"$prev_sev\" in\n                CRITICAL) prev_rank=3 ;;\n                WARNING)  prev_rank=2 ;;\n                ATTEMPT)  prev_rank=1 ;;\n                INFO)     prev_rank=0 ;;\n            esac\n            if &#91; \"$sev_rank\" -le \"$prev_rank\" ]; then\n                # Existing finding is at least as severe; ignore.\n                return\n            fi\n            # Upgrade in place: replace severity, token, FINDINGS entry,\n            # and roll back the previous severity counter so the new one\n            # can be incremented below without double-counting.\n            FINDING_SEVERITIES&#91;$i]=\"$severity\"\n            &#91; -n \"$token_val\" ] &amp;&amp; FINDING_TOKENS&#91;$i]=\"$token_val\"\n            local j\n            for j in \"${!FINDINGS&#91;@]}\"; do\n                local entry=\"${FINDINGS&#91;$j]}\"\n                local entry_sev=\"${entry%%|*}\"\n                local entry_file=\"${entry#*|}\"; entry_file=\"${entry_file%%|*}\"\n                if &#91; \"$entry_file\" = \"$session_file\" ] &amp;&amp; &#91; \"$entry_sev\" = \"$prev_sev\" ]; then\n                    FINDINGS&#91;$j]=\"${severity}|${session_file}|${message}\"\n                    break\n                fi\n            done\n            case \"$prev_sev\" in\n                CRITICAL) COUNT_CRITICAL=$((COUNT_CRITICAL - 1)) ;;\n                WARNING)  COUNT_WARNING=$((COUNT_WARNING - 1))   ;;\n                ATTEMPT)  COUNT_ATTEMPT=$((COUNT_ATTEMPT - 1))   ;;\n                INFO)     COUNT_INFO=$((COUNT_INFO - 1))         ;;\n            esac\n            break\n        fi\n    done\n\n    if &#91; \"$found\" -eq 0 ]; then\n        FINDING_SESSIONS+=(\"$session_file\")\n        FINDING_TOKENS+=(\"$token_val\")\n        FINDING_SEVERITIES+=(\"$severity\")\n        FINDINGS+=(\"${severity}|${session_file}|${message}\")\n    fi\n\n    case \"$severity\" in\n        CRITICAL) COUNT_CRITICAL=$((COUNT_CRITICAL + 1)) ;;\n        WARNING)  COUNT_WARNING=$((COUNT_WARNING + 1))   ;;\n        ATTEMPT)  COUNT_ATTEMPT=$((COUNT_ATTEMPT + 1))   ;;\n        INFO)     COUNT_INFO=$((COUNT_INFO + 1))         ;;\n    esac\n\n    echo \"&#91;${severity}] ${message}: ${session_file}\"\n}\n\n# ---------------------------------------------------------------------------\n# IOC checks\n# ---------------------------------------------------------------------------\n\n# IOC 0: token_denied counter alongside cp_security_token, in a session\n# whose origin is badpass or otherwise non-benign.\n#\n# - token_denied is incremented by do_token_denied() (cpsrvd.pl:3821)\n#   every time a request supplies the wrong cp_security_token. The\n#   session is killed on the third failure.\n# - cp_security_token itself is set by newsession() unconditionally\n#   while security tokens are enabled (Cpanel\/Server.pm:2290), so its\n#   presence is NOT by itself an IOC. The pair (token_denied,\n#   cp_security_token) tells us only that someone is actively trying\n#   tokens against this session.\n#\n# Auth markers (successful_*_auth_with_timestamp, hasroot=1,\n# tfa_verified=1, or an access_log hit on the security token) cannot\n# legitimately appear in a badpass session: the badpass call site\n# (Cpanel\/Server.pm:1244-1252) doesn't pass them, hasroot is not even\n# in _SESSION_PARTS (Cpanel\/Server.pm:2216-2247), and tfa_verified is\n# forced to 0 unless the caller passes a truthy value (line 2295).\n#\n# Severity tiers:\n#   CRITICAL - badpass origin AND auth markers present (post-exploit)\n#   INFO     - badpass origin, no auth markers, pass looks like a real\n#              encoded password (likely an unrelated failed login that\n#              happened to receive bad-token traffic)\n#   WARNING  - origin is neither badpass nor a known-benign method\n#              (handle_form_login, create_user_session,\n#              handle_auth_transfer); the suspicious origin itself is\n#              the IOC\n#\n# Legitimate badpass sessions never carry a pass= line (the badpass\n# call site at Cpanel\/Server.pm:1244-1252 does not pass `pass` to\n# newsession, and saveSession only writes pass= when length is\n# non-zero - Cpanel\/Session.pm:181). When we see one anyway we defer\n# classification to IOC 5 (check_failed_exploit_attempt), which flags\n# it as ATTEMPT.\ncheck_token_denied_with_injected_token() {\n    local session_file=\"$1\"\n\n    grep -q '^token_denied='      \"$session_file\" || return\n    grep -q '^cp_security_token=' \"$session_file\" || return\n\n    local token_val external_auth internal_auth hasroot tfa used\n    token_val=$(get_field      \"$session_file\" cp_security_token)\n    external_auth=$(get_field  \"$session_file\" successful_external_auth_with_timestamp)\n    internal_auth=$(get_field  \"$session_file\" successful_internal_auth_with_timestamp)\n    hasroot=$(get_field        \"$session_file\" hasroot)\n    tfa=$(get_field            \"$session_file\" tfa_verified)\n    used=\"\"\n    if &#91; -r \"$ACCESS_LOG\" ]; then\n        used=$(grep -aF -- \"$token_val\" \"$ACCESS_LOG\" | grep -m1 \" 200 \")\n    fi\n\n    local has_auth_markers=0\n    if &#91; -n \"$external_auth\" ] || &#91; -n \"$internal_auth\" ] \\\n       || &#91; \"$hasroot\" = \"1\" ] || &#91; \"$tfa\" = \"1\" ] || &#91; -n \"$used\" ]; then\n        has_auth_markers=1\n    fi\n\n    if grep -q '^origin_as_string=.*method=badpass' \"$session_file\"; then\n        if &#91; \"$has_auth_markers\" -eq 1 ]; then\n            report_finding CRITICAL \"$session_file\" \"$token_val\" \\\n                \"Exploitation artifact - token_denied with injected cp_security_token (badpass origin, token used)\"\n        else\n            # A pass= line on a badpass session is itself anomalous;\n            # defer to IOC 5 (ATTEMPT).\n            if grep -q '^pass=' \"$session_file\"; then\n                return\n            fi\n            report_finding INFO \"$session_file\" \"$token_val\" \\\n                \"Possible injected session (badpass origin, no usage observed)\"\n        fi\n    elif grep -q '^origin_as_string=.*method=handle_form_login' \"$session_file\" || \\\n         grep -q '^origin_as_string=.*method=create_user_session' \"$session_file\" || \\\n         grep -q '^origin_as_string=.*method=handle_auth_transfer' \"$session_file\"; then\n        # Known-benign origins where token_denied + cp_security_token\n        # genuinely happens during normal use.\n        return\n    else\n        report_finding WARNING \"$session_file\" \"$token_val\" \\\n            \"Suspicious session with token_denied + cp_security_token (non-badpass origin)\"\n    fi\n}\n\n# IOC 1: A session that still has its pre-auth marker file but already\n# contains an auth-success timestamp (external or internal).\n#\n# write_session creates $SESSIONS_DIR\/preauth\/&lt;session_name> when the\n# session is written with needs_auth=1, and removes that marker once\n# needs_auth is cleared on promotion (Cpanel\/Session.pm:225-235). A\n# legitimately authenticated session therefore never has both the\n# preauth marker and an auth-success timestamp at the same time.\n#\n# Both successful_external_auth_with_timestamp and\n# successful_internal_auth_with_timestamp are checked: the original\n# poc.py payload injects the external variant; the watchtowr payload\n# (poc\/poc_watchtowr.py:35) injects the internal variant.\ncheck_preauth_with_auth_attrs() {\n    local session_file=\"$1\"\n    local session_name preauth_file\n    session_name=$(basename \"$session_file\")\n    preauth_file=\"$SESSIONS_DIR\/preauth\/$session_name\"\n\n    &#91; -f \"$preauth_file\" ] || return\n\n    local marker\n    if grep -qE '^successful_external_auth_with_timestamp=' \"$session_file\"; then\n        marker=\"successful_external_auth_with_timestamp\"\n    elif grep -qE '^successful_internal_auth_with_timestamp=' \"$session_file\"; then\n        marker=\"successful_internal_auth_with_timestamp\"\n    else\n        return\n    fi\n\n    report_finding CRITICAL \"$session_file\" \\\n        \"$(get_field \"$session_file\" cp_security_token)\" \\\n        \"Injected session - ${marker} present in pre-auth session\"\n}\n\n# IOC 2: tfa_verified=1 outside of a legitimate origin method.\n#\n# tfa_verified=1 is set in only two places:\n#   - Cpanel\/Security\/Authn\/TwoFactorAuth\/Verify.pm:122, after a real\n#     TFA token validation succeeds.\n#   - Cpanel\/Server.pm:2295, when a caller passes tfa_verified=1 to\n#     newsession().\n# In both cases the legitimate origin method is one of handle_form_login,\n# create_user_session, or handle_auth_transfer. tfa_verified=1 with any\n# other origin (notably badpass) cannot occur in a benign flow.\ncheck_tfa_with_bad_origin() {\n    local session_file=\"$1\"\n\n    grep -qE '^tfa_verified=1$' \"$session_file\" || return\n    grep -q '^origin_as_string=.*method=handle_form_login'    \"$session_file\" &amp;&amp; return\n    grep -q '^origin_as_string=.*method=create_user_session'  \"$session_file\" &amp;&amp; return\n    grep -q '^origin_as_string=.*method=handle_auth_transfer' \"$session_file\" &amp;&amp; return\n\n    report_finding WARNING \"$session_file\" \\\n        \"$(get_field \"$session_file\" cp_security_token)\" \\\n        \"Session with tfa_verified=1 but suspicious origin\"\n}\n\n# IOC 3: Session file contains a line that is not in `key=value` form.\n#\n# Three structural invariants together guarantee that every legitimate\n# line matches ^&#91;A-Za-z_]&#91;A-Za-z0-9_]*=:\n#\n#   1. write_session serializes via Cpanel::Config::FlushConfig::flushConfig\n#      with '=' as the separator (Cpanel\/Session.pm:221), so the on-disk\n#      format is one key=value pair per line.\n#   2. Keys come from a fixed whitelist (_SESSION_PARTS at\n#      Cpanel\/Server.pm:2216-2247, applied at lines 2268-2270), so they\n#      always match the identifier shape above.\n#   3. Cpanel::Session::filter_sessiondata strips \\r\\n from every value\n#      (Cpanel\/Session.pm:315) and additionally strips \\r\\n=, from origin\n#      sub-values (line 312), so values can never re-introduce line\n#      breaks. The `pass` value is additionally encoded by saveSession\n#      (Cpanel\/Session.pm:181-189) into either lowercase hex (with-secret\n#      via Cpanel::Session::Encoder->encode_data) or the literal prefix\n#      `no-ob:` followed by lowercase hex (no-secret via\n#      Cpanel::Session::Encoder->hex_encode_only), so it cannot\n#      reintroduce structural characters either.\n#\n# Any non-blank line that fails the regex is the footprint of an\n# injection that bypassed these invariants - typically raw payload bytes\n# that didn't form valid key=value pairs. Note: an injection whose\n# smuggled lines DO match key=value (e.g. the watchtowr payload at\n# poc\/poc_watchtowr.py:35, which fabricates successful_internal_auth_\n# with_timestamp\/user\/tfa_verified\/hasroot lines) will not trip this\n# check; it is caught by IOC-0 and IOC-4 instead.\ncheck_malformed_session_line() {\n    local session_file=\"$1\"\n\n    # Look for any non-blank line that doesn't start with key=...\n    grep -nE -v '^&#91;A-Za-z_]&#91;A-Za-z0-9_]*=|^&#91;&#91;:space:]]*$' \"$session_file\" >\/dev\/null 2>&amp;1 || return\n\n    report_finding CRITICAL \"$session_file\" \\\n        \"$(get_field \"$session_file\" cp_security_token)\" \\\n        \"Malformed session line(s) detected (not key=value - newline injection footprint)\"\n}\n\n# IOC 4: badpass origin combined with markers that no legitimate cpsrvd\n# code path writes into a badpass session.\n#\n# The badpass call site (Cpanel\/Server.pm:1244-1252) is:\n#\n#   $randsession = $self->newsession(\n#       'needs_auth' => 1,\n#       %security_token_options,            # adds cp_security_token\n#       'origin' => { 'method' => 'badpass' },\n#   );\n#\n# %security_token_options is why badpass sessions legitimately carry\n# cp_security_token, but no auth-related options are ever supplied.\n# newsession() filters %OPTS through the _SESSION_PARTS whitelist\n# (Cpanel\/Server.pm:2216-2247, applied at lines 2268-2270), so any key\n# not in that whitelist cannot land in the session via newsession at\n# all. Per marker:\n#\n#   successful_external_auth_with_timestamp - whitelisted, but the\n#       badpass caller doesn't pass it\n#   successful_internal_auth_with_timestamp - same\n#   tfa_verified=1 - newsession unconditionally writes 0 unless the\n#       caller passed a truthy value (Cpanel\/Server.pm:2295), and the\n#       badpass caller doesn't\n#   hasroot=1 - NOT in _SESSION_PARTS, so newsession cannot write it\n#       for ANY session. A repo-wide grep finds no caller of\n#       Cpanel::Session::Modify->set('hasroot', ...) either: hasroot is\n#       never written to a session by legitimate code. Its presence in\n#       any session file is conclusive evidence of newline injection\n#       (the watchtowr payload at poc\/poc_watchtowr.py:35 smuggles\n#       hasroot=1 via \\r\\n in a user-controlled field).\ncheck_badpass_with_auth_markers() {\n    local session_file=\"$1\"\n\n    grep -q '^origin_as_string=.*method=badpass' \"$session_file\" || return\n\n    local markers=()\n    grep -q '^successful_external_auth_with_timestamp=' \"$session_file\" \\\n        &amp;&amp; markers+=(\"successful_external_auth_with_timestamp\")\n    grep -q '^successful_internal_auth_with_timestamp=' \"$session_file\" \\\n        &amp;&amp; markers+=(\"successful_internal_auth_with_timestamp\")\n    grep -qE '^hasroot=1$'      \"$session_file\" &amp;&amp; markers+=(\"hasroot=1\")\n    grep -qE '^tfa_verified=1$' \"$session_file\" &amp;&amp; markers+=(\"tfa_verified=1\")\n\n    &#91; \"${#markers&#91;@]}\" -gt 0 ] || return\n\n    local joined\n    joined=$(IFS=,; echo \"${markers&#91;*]}\")\n    report_finding CRITICAL \"$session_file\" \\\n        \"$(get_field \"$session_file\" cp_security_token)\" \\\n        \"badpass origin combined with authenticated markers ($joined) - impossible in benign flow\"\n}\n\n# IOC 5: Failed exploit attempt - a badpass session that carries a\n# pass= line, a token_denied counter, and no auth markers.\n#\n# A legitimate badpass session is created at Cpanel\/Server.pm:1244-1252:\n#\n#   $randsession = $self->newsession(\n#       'needs_auth' => 1,\n#       %security_token_options,\n#       'origin' => { 'method' => 'badpass' },\n#   );\n#\n# %security_token_options carries only cp_security_token,\n# requested_token_at_next_login, and previous_session_user\n# (Cpanel\/Server.pm:1205-1226) - never `pass`. saveSession only\n# writes a pass= line when length($session_ref->{pass}) is non-zero\n# (Cpanel\/Session.pm:181), so legitimate badpass sessions have no\n# pass= line at all.\n#\n# An exploit that tampers with a user-controlled field on a\n# badpass-bound request leaves a pass= line behind (saveSession\n# encodes it as `&lt;hex>` or `no-ob:&lt;hex>` per Cpanel\/Session.pm:181-189,\n# but the format is irrelevant - its presence is the indicator). Combined\n# with token_denied (someone was poking at cp_security_token) and the\n# absence of auth markers (the injection didn't promote - otherwise\n# IOC-0 or IOC-4 fires CRITICAL), this is the signature of a failed\n# exploit attempt.\ncheck_failed_exploit_attempt() {\n    local session_file=\"$1\"\n\n    grep -q '^origin_as_string=.*method=badpass' \"$session_file\" || return\n    grep -q '^token_denied=' \"$session_file\" || return\n\n    # If auth markers are present, IOC-4 (CRITICAL) handles it.\n    grep -q '^successful_internal_auth_with_timestamp=' \"$session_file\" &amp;&amp; return\n    grep -q '^successful_external_auth_with_timestamp=' \"$session_file\" &amp;&amp; return\n\n    # Legitimate badpass sessions never carry pass=.\n    grep -q '^pass=' \"$session_file\" || return\n\n    report_finding ATTEMPT \"$session_file\" \"$(get_field \"$session_file\" cp_security_token)\" \\\n        \"Failed exploit attempt (badpass origin, token_denied, no auth markers, anomalous pass= line)\"\n}\n\n# Inspect a *.lock file (Cpanel::SafeFile dotlock) and confirm it looks\n# like a real lock before silently skipping it.\n#\n# Cpanel::Session uses Cpanel::SafeFile to write the session file to\n# disk (serialization itself is handled in the session code). SafeFile\n# creates a sibling dotlock at &lt;session>.lock for the duration of every\n# write and, on crash\/abort, may leave it behind permanently. The lock contents\n# are written by Cpanel::SafeFileLock::write_lock_contents as \"$$\\n$0\\n\"\n# - first line is the PID, second line is the program name. These are\n# not key=value pairs, so without a guard they trip\n# check_malformed_session_line as a CRITICAL false positive.\n#\n# The CVE-2026-41940 exploit vector is the session file content, not the\n# lock file, so a lock file that doesn't look right is not by itself an\n# exploitation indicator. Emit a stderr notice for operator awareness and\n# leave the SCAN SUMMARY counters alone.\ncheck_lock_file() {\n    local lock_file=\"$1\"\n    local first_line\n    first_line=$(grep -m1 -v '^&#91;&#91;:space:]]*$' \"$lock_file\" 2>\/dev\/null)\n    if &#91;&#91; \"$first_line\" =~ ^&#91;0-9]+$ ]]; then\n        return\n    fi\n    echo \"&#91;NOTICE] Skipping unexpected .lock contents: $lock_file\" >&amp;2\n}\n\n# ---------------------------------------------------------------------------\n# Main\n# ---------------------------------------------------------------------------\n\nscan_sessions() {\n    local session_file\n    while IFS= read -r -d '' session_file; do\n        # SafeFile dotlocks come in two forms: &lt;session>.lock (the\n        # final lock) and &lt;session>.lock-&lt;hex-and-hyphens> (the temp\n        # name SafeFile writes before atomic-renaming into place; it\n        # can also be left behind on crash). Skip both.\n        #\n        # Vim creates a .swp swap file alongside any file it opens,\n        # so an operator inspecting a session in vim leaves one\n        # behind. The format is binary and not a session.\n        case \"$session_file\" in\n            *.lock | *.lock-*)\n                check_lock_file \"$session_file\"\n                continue\n                ;;\n            *.swp)\n                continue\n                ;;\n        esac\n        check_token_denied_with_injected_token \"$session_file\"\n        check_preauth_with_auth_attrs          \"$session_file\"\n        check_tfa_with_bad_origin              \"$session_file\"\n        check_malformed_session_line           \"$session_file\"\n        check_badpass_with_auth_markers        \"$session_file\"\n        check_failed_exploit_attempt           \"$session_file\"\n    done &lt; &lt;(find \"$SESSIONS_DIR\/raw\" -type f -print0 2>\/dev\/null)\n}\n\n\nprint_summary() {\n    local total=$((COUNT_CRITICAL + COUNT_WARNING + COUNT_INFO + COUNT_ATTEMPT))\n\n    echo\n    echo \"=================================================================\"\n    echo \"                       SCAN SUMMARY\"\n    echo \"=================================================================\"\n    echo \"  CRITICAL findings: $COUNT_CRITICAL\"\n    echo \"  WARNING  findings: $COUNT_WARNING\"\n    echo \"  ATTEMPT  findings: $COUNT_ATTEMPT\"\n    echo \"  INFO     findings: $COUNT_INFO\"\n    echo \"  Total            : $total\"\n    echo \"-----------------------------------------------------------------\"\n\n    if &#91; \"$total\" -eq 0 ]; then\n        echo \"&#91;+] No indicators of compromise found.\"\n        return\n    fi\n\n    # --purge has destructive blast radius (live session files for every\n    # logged-in user). Require either --yes for non-interactive use, or\n    # an explicit \"yes\" at an attached TTY.\n    if &#91; \"$PURGE\" -eq 1 ] &amp;&amp; &#91; \"$ASSUME_YES\" -ne 1 ]; then\n        if &#91; ! -t 0 ]; then\n            echo \"&#91;ERROR] --purge requires --yes when stdin is not a TTY (cron, pipes, etc)\" >&amp;2\n            echo \"        Re-run with --yes to confirm deletion.\" >&amp;2\n            exit 64\n        fi\n        echo\n        echo \"About to delete ${#FINDING_SESSIONS&#91;@]} session file(s) plus matching preauth markers.\"\n        local confirm=\"\"\n        read -r -p \"Type 'yes' to confirm: \" confirm\n        if &#91; \"$confirm\" != \"yes\" ]; then\n            echo \"&#91;+] Aborted; no files deleted.\"\n            PURGE=0\n        fi\n    fi\n\n\n    # For each unique session, print only the highest-severity finding, then dump\/purge as needed.\n    local i session token severity message found=0\n    for i in \"${!FINDING_SESSIONS&#91;@]}\"; do\n        session=\"${FINDING_SESSIONS&#91;$i]}\"\n        token=\"${FINDING_TOKENS&#91;$i]}\"\n        severity=\"${FINDING_SEVERITIES&#91;$i]}\"\n        found=0\n        # Find the first matching finding for this session and severity.\n        # Use `read` with three names so the last variable (entry_msg)\n        # absorbs any remaining `|` characters - the previous `${var##*|}`\n        # form took only the suffix after the LAST `|`, which would\n        # silently truncate any future message that contained one.\n        for entry in \"${FINDINGS&#91;@]}\"; do\n            local entry_sev entry_file entry_msg\n            IFS='|' read -r entry_sev entry_file entry_msg &lt;&lt;&lt; \"$entry\"\n            if &#91; \"$entry_file\" = \"$session\" ] &amp;&amp; &#91; \"$entry_sev\" = \"$severity\" ]; then\n                message=\"$entry_msg\"\n                found=1\n                break\n            fi\n        done\n        echo\n        echo \"=================================================================\"\n        echo \"  SESSION: $session\"\n        echo \"=================================================================\"\n        echo \"  Findings:\"\n        if &#91; \"$found\" -eq 1 ]; then\n            printf \"    &#91;%-8s] %s\\n\" \"$severity\" \"$message\"\n        else\n            printf \"    &#91;%-8s] %s\\n\" \"$severity\" \"(no message found)\"\n        fi\n        echo\n        if &#91; \"$VERBOSE\" -eq 1 ]; then\n            dump_session \"$session\" \"$token\"\n        fi\n        if &#91; \"$PURGE\" -eq 1 ]; then\n            echo \"    &#91;ACTION] Deleting session file: $session\"\n            rm -f -- \"$session\"\n            local preauth_marker=\"$SESSIONS_DIR\/preauth\/$(basename \"$session\")\"\n            if &#91; -e \"$preauth_marker\" ]; then\n                echo \"    &#91;ACTION] Deleting preauth marker: $preauth_marker\"\n                rm -f -- \"$preauth_marker\"\n            fi\n        fi\n    done\n\n    if &#91; \"$COUNT_CRITICAL\" -gt 0 ] || &#91; \"$COUNT_WARNING\" -gt 0 ]; then\n        echo\n        echo \"&#91;!] INDICATORS OF COMPROMISE DETECTED - IMMEDIATE ACTION REQUIRED\"\n        echo \"    1. Purge all affected sessions\"\n        echo \"    2. Force password reset for root and all WHM users\"\n        echo \"    3. Audit \/var\/log\/wtmp and WHM access logs for unauthorized access\"\n        echo \"    4. Check for persistence mechanisms (cron, SSH keys, backdoors)\"\n    fi\n}\n\nif &#91; ! -d \"$SESSIONS_DIR\/raw\" ]; then\n    echo \"&#91;ERROR] Sessions directory not found: $SESSIONS_DIR\/raw\" >&amp;2\n    echo \"        Pass --sessions-dir DIR to point at a different location\" >&amp;2\n    echo \"        (the default is \/var\/cpanel\/sessions).\" >&amp;2\n    exit 64\nfi\n\necho \"&#91;*] Scanning session files for injection indicators...\"\nscan_sessions\nprint_summary\n\n# Exit codes (for cron \/ monitoring):\n#   2 - at least one CRITICAL or WARNING finding (compromise indicators)\n#   1 - only ATTEMPT or INFO findings (probing, no confirmed compromise)\n#   0 - clean scan\nif &#91; \"$COUNT_CRITICAL\" -gt 0 ] || &#91; \"$COUNT_WARNING\" -gt 0 ]; then\n    exit 2\nelif &#91; \"$COUNT_ATTEMPT\" -gt 0 ] || &#91; \"$COUNT_INFO\" -gt 0 ]; then\n    exit 1\nfi\nexit 0<\/code><\/pre>\n\n\n\n<p>Save the file with <code><mark class=\"has-inline-color has-vivid-red-color\">Ctrl+O<\/mark><\/code>, press <strong>Enter<\/strong>, then exit with <code><mark class=\"has-inline-color has-vivid-red-color\">Ctrl+X<\/mark><\/code>.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Step 2 \u2014 Make the Script Executable<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code><mark class=\"has-inline-color has-vivid-green-cyan-color\">chmod +x ioc_checksessions_files.sh<\/mark><\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Step 3 \u2014 Run the Script<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code><mark class=\"has-inline-color has-vivid-green-cyan-color\">\/bin\/bash .\/ioc_checksessions_files.sh<\/mark><\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Step 4 \u2014 Interpret the Results<\/h3>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>Output<\/th><th>What it means<\/th><th>Action<\/th><\/tr><\/thead><tbody><tr><td><code>[+] No indicators of compromise found.<\/code><\/td><td>Your server shows no signs of being attacked<\/td><td>No immediate action needed \u2014 continue monitoring<\/td><\/tr><tr><td><code>Found possible injected session file<\/code><\/td><td>A suspicious session was found but may not have been used<\/td><td>Purge sessions and reset all passwords as a precaution<\/td><\/tr><tr><td><code>[!] CRITICAL<\/code> or <code>[!] WARNING<\/code><\/td><td>Your server was actively attacked and likely compromised<\/td><td>See Section 6 \u2014 take immediate action and contact support<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\"><a id=\"compromised\"><\/a>6. If Your Server Was Compromised \u2014 Immediate Actions<\/h2>\n\n\n\n<p>\ud83d\udea8 <strong>If the detection script shows CRITICAL or WARNING results, act immediately.<\/strong> Every minute of delay increases the risk of further damage. Raise a support ticket with Truehost right now and our team will assist you urgently.<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>Purge all active cPanel sessions immediately<\/strong><br>This disconnects any active attacker sessions from your server. <code><mark style=\"background-color:#abb8c3\" class=\"has-inline-color\">rm -rf \/var\/cpanel\/sessions\/raw\/*<\/mark><\/code><\/li>\n\n\n\n<li><strong>Force a password reset for root and all cPanel users<\/strong><br>Change the root password immediately using the <code>passwd<\/code> command via SSH.<\/li>\n\n\n\n<li><strong>Audit the access logs for unauthorised activity<\/strong><br>Check for any suspicious login activity before and after the vulnerability window: <code><mark style=\"background-color:#abb8c3\" class=\"has-inline-color\">cat \/var\/log\/wtmp | last | head -50 cat \/usr\/local\/cpanel\/logs\/access_log | grep \" 200 \" | tail -100<\/mark><\/code><\/li>\n\n\n\n<li><strong>Check for persistence mechanisms<\/strong><br>Attackers often leave backdoors behind. Check for unexpected cron jobs, new SSH keys, and unfamiliar scripts: <code><mark style=\"background-color:#abb8c3\" class=\"has-inline-color\">crontab -l cat \/root\/.ssh\/authorized_keys find \/tmp \/var\/tmp -type f -name \"*.sh\" 2&gt;\/dev\/null<\/mark><\/code><\/li>\n\n\n\n<li><strong>Raise a support ticket with Truehost immediately<\/strong><br>Our team can assist with forensic investigation, server hardening, and recovery. Include your VPS IP and the output of the detection script in your ticket.<\/li>\n<\/ol>\n\n\n\n<h3 class=\"wp-block-heading\">\ud83d\udea8 Server Compromised? Contact Us Now<\/h3>\n\n\n\n<p>If your server shows signs of compromise, do not wait. Our team is available to assist with urgent recovery.<\/p>\n\n\n\n<p>Go to <strong>your client area \u2192 Support \u2192 Open Ticket<\/strong> and mark your ticket as <strong>URGENT \u2014 Server Compromised<\/strong>. Include your VPS IP address and the output of the detection script or use this <a href=\"https:\/\/truehost.com\/support\/knowledge-base\/how-to-create-and-manage-tickets-from-truehost-client-area\/\">guide<\/a> <\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><a id=\"legacy\"><\/a>7. Warning for Unsupported cPanel Versions<\/h2>\n\n\n\n<p>If your server is running an end-of-life or unsupported version of cPanel that is <strong>not listed<\/strong> in the safe versions table in Section 1, it almost certainly contains the same authentication vulnerability \u2014 but <strong>no patch will be provided<\/strong> for these old versions.<\/p>\n\n\n\n<p>If you are on an unsupported version you must:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Plan a migration to a supported cPanel release track as soon as possible<\/li>\n\n\n\n<li>Apply <strong>both<\/strong> mitigation options from Section 4 as an immediate precaution (firewall block AND service stop)<\/li>\n\n\n\n<li>Enable multi-factor authentication (MFA) for cPanel access<\/li>\n\n\n\n<li>Restrict cPanel access to specific trusted IP addresses only<\/li>\n<\/ul>\n\n\n\n<p>\ud83d\udea8 <strong>Running an unsupported cPanel version is a critical security risk.<\/strong> Raise a support ticket immediately and our team will advise you on the fastest path to a supported version.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><a id=\"reinstall\"><\/a>8. Reinstalling cPanel (Last Resort)<\/h2>\n\n\n\n<p>If your server has been severely compromised and cannot be recovered, or if you are running an unsupported version and cannot upgrade, a full reinstall may be the safest option. This gives you a completely clean server with a fresh cPanel installation.<\/p>\n\n\n\n<p>\u26a0\ufe0f <strong>Warning:<\/strong> A reinstall permanently wipes all data on your server \u2014 all websites, databases, emails, and configurations. Back up everything important before proceeding. Only consider this as a last resort after consulting with our support team.<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Log in to your Truehost Cloud account and go to <strong>Services<\/strong>. Click <strong>Manage<\/strong> next to your cPanel VPS product.<\/li>\n\n\n\n<li>Find the <strong>Reinstall<\/strong> button on the management page and click it.<\/li>\n\n\n\n<li>Confirm the action when prompted. The reinstall process runs automatically.<\/li>\n\n\n\n<li>You will receive a new welcome email with fresh credentials when the reinstall is complete.<\/li>\n<\/ol>\n\n\n\n<p>\u2139\ufe0f <strong>Not sure if a reinstall is the right option?<\/strong> Raise a support ticket first \u2014 our team will assess your situation and recommend the best course of action before you take any irreversible steps.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><a id=\"checklist\"><\/a>9. Summary Checklist<\/h2>\n\n\n\n<p>Use this checklist to confirm you have completed all required actions:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Connected to my server via SSH<\/li>\n\n\n\n<li>Ran <mark style=\"background-color:#abb8c3\" class=\"has-inline-color\"><code>\/scripts\/upcp --force<\/code> <\/mark>to apply the security patch<\/li>\n\n\n\n<li>Verified the patched version with <code><mark style=\"background-color:#abb8c3\" class=\"has-inline-color\">\/usr\/local\/cpanel\/cpanel -V<\/mark><\/code><\/li>\n\n\n\n<li>Restarted cPanel service with <code><mark style=\"background-color:#abb8c3\" class=\"has-inline-color\">\/scripts\/restartsrv_cpsrvd<\/mark><\/code><\/li>\n\n\n\n<li>Re-enabled automatic cPanel updates (if previously disabled)<\/li>\n\n\n\n<li>Ran the detection script <code><mark style=\"background-color:#abb8c3\" class=\"has-inline-color\">ioc_checksessions_files.sh<\/mark><\/code><\/li>\n\n\n\n<li>Confirmed: no indicators of compromise found (or raised a ticket if found)<\/li>\n\n\n\n<li>Changed root and all cPanel account passwords as a precaution<\/li>\n\n\n\n<li>Enabled two-factor authentication (2FA) on cPanel<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\"><a id=\"help\"><\/a>10. Need Help? We Are Here for You<\/h2>\n\n\n\n<p>We understand that applying security patches on a live server can be stressful \u2014 especially if you are not fully comfortable with SSH and command-line tools. <strong>You do not have to do this alone.<\/strong><\/p>\n\n\n\n<p>Our support team can help you with:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Applying the cPanel security patch on your server for you<\/li>\n\n\n\n<li>Running the compromise detection script and reporting results<\/li>\n\n\n\n<li>Assisting with server recovery if your server was compromised<\/li>\n\n\n\n<li>Advising on the best path forward for unsupported cPanel versions<\/li>\n\n\n\n<li>Any other step in this guide you are unsure about<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">\ud83d\udcac Contact Truehost Support<\/h3>\n\n\n\n<p>Log in to your Truehost Cloud account and go to <strong>Support \u2192 Open Ticket<\/strong>.<\/p>\n\n\n\n<p>When writing to us, please include:<\/p>\n\n\n\n<p>\u2022 Your VPS hostname or IP address<br>\u2022 Which step you are stuck on<br>\u2022 The output of<mark class=\"has-inline-color has-vivid-green-cyan-color\"> <\/mark><code><mark style=\"background-color:#abb8c3\" class=\"has-inline-color has-black-color\">\/usr\/local\/cpanel\/cpanel -V<\/mark><\/code><mark class=\"has-inline-color has-vivid-green-cyan-color\"> <\/mark>if you can get it<br>\u2022 The output of the detection script if you have run it<\/p>\n\n\n\n<p><strong>Do not delay.<\/strong> Even if you are unsure, reach out \u2014 we would rather help you than have you wait and risk your server being compromised. Use this <a href=\"https:\/\/truehost.com\/support\/knowledge-base\/how-to-create-and-manage-tickets-from-truehost-client-area\/\">guide<\/a> to open a supporyt ticket.<\/p>\n\n\n\n<p>Truehost Cloud &nbsp;\u00b7&nbsp; truehost.cloud &nbsp;\u00b7&nbsp; April 2026 &nbsp;\u00b7&nbsp; cPanel Security Advisory<\/p>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Truehost Cloud &nbsp;\u00b7&nbsp; cPanel VPS Security Advisory Critical cPanel Security Patch \u2014 Required Actions for Your VPS A serious security vulnerability has been identified in cPanel. This guide walks you through exactly what to do to protect your server. Published: April 30, 2026 &nbsp;\u00b7&nbsp; Affected: cPanel all versions after 11.40 &nbsp;\u00b7&nbsp; Truehost Cloud \ud83d\udea8 Urgent [&hellip;]<\/p>\n","protected":false},"author":32,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_eb_attr":"","_exactmetrics_skip_tracking":false,"_exactmetrics_sitenote_active":false,"_exactmetrics_sitenote_note":"","_exactmetrics_sitenote_category":0,"footnotes":""},"categories":[1],"tags":[],"class_list":["post-19070","post","type-post","status-publish","format-standard","hentry","category-guides"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.7 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>cPanel Security Patch -<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/truehost.com\/support\/cpanel-security-patch-truehost-cloud-client-guide\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"cPanel Security Patch -\" \/>\n<meta property=\"og:description\" content=\"Truehost Cloud &nbsp;\u00b7&nbsp; cPanel VPS Security Advisory Critical cPanel Security Patch \u2014 Required Actions for Your VPS A serious security vulnerability has been identified in cPanel. This guide walks you through exactly what to do to protect your server. Published: April 30, 2026 &nbsp;\u00b7&nbsp; Affected: cPanel all versions after 11.40 &nbsp;\u00b7&nbsp; Truehost Cloud \ud83d\udea8 Urgent [&hellip;]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/truehost.com\/support\/cpanel-security-patch-truehost-cloud-client-guide\/\" \/>\n<meta property=\"article:published_time\" content=\"2026-04-30T09:35:50+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2026-05-06T10:38:09+00:00\" \/>\n<meta name=\"author\" content=\"Jillian A.\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Jillian A.\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"9 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/truehost.com\\\/support\\\/cpanel-security-patch-truehost-cloud-client-guide\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/truehost.com\\\/support\\\/cpanel-security-patch-truehost-cloud-client-guide\\\/\"},\"author\":{\"name\":\"Jillian A.\",\"@id\":\"https:\\\/\\\/www.truehost.com\\\/support\\\/#\\\/schema\\\/person\\\/2b1e998cb219f95acc7fb5d81efd5a7a\"},\"headline\":\"cPanel Security Patch\",\"datePublished\":\"2026-04-30T09:35:50+00:00\",\"dateModified\":\"2026-05-06T10:38:09+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/truehost.com\\\/support\\\/cpanel-security-patch-truehost-cloud-client-guide\\\/\"},\"wordCount\":1884,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/www.truehost.com\\\/support\\\/#organization\"},\"articleSection\":[\"Guides\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/truehost.com\\\/support\\\/cpanel-security-patch-truehost-cloud-client-guide\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/truehost.com\\\/support\\\/cpanel-security-patch-truehost-cloud-client-guide\\\/\",\"url\":\"https:\\\/\\\/truehost.com\\\/support\\\/cpanel-security-patch-truehost-cloud-client-guide\\\/\",\"name\":\"cPanel Security Patch -\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.truehost.com\\\/support\\\/#website\"},\"datePublished\":\"2026-04-30T09:35:50+00:00\",\"dateModified\":\"2026-05-06T10:38:09+00:00\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/truehost.com\\\/support\\\/cpanel-security-patch-truehost-cloud-client-guide\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/truehost.com\\\/support\\\/cpanel-security-patch-truehost-cloud-client-guide\\\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/truehost.com\\\/support\\\/cpanel-security-patch-truehost-cloud-client-guide\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/www.truehost.com\\\/support\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"cPanel Security Patch\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.truehost.com\\\/support\\\/#website\",\"url\":\"https:\\\/\\\/www.truehost.com\\\/support\\\/\",\"name\":\"\",\"description\":\"Help In a Click\",\"publisher\":{\"@id\":\"https:\\\/\\\/www.truehost.com\\\/support\\\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.truehost.com\\\/support\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/www.truehost.com\\\/support\\\/#organization\",\"name\":\"Truehost Kenya\",\"url\":\"https:\\\/\\\/www.truehost.com\\\/support\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.truehost.com\\\/support\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/www.truehost.com\\\/support\\\/wp-content\\\/uploads\\\/2026\\\/04\\\/cropped-image_2026-04-16_174808866.png\",\"contentUrl\":\"https:\\\/\\\/www.truehost.com\\\/support\\\/wp-content\\\/uploads\\\/2026\\\/04\\\/cropped-image_2026-04-16_174808866.png\",\"width\":240,\"height\":48,\"caption\":\"Truehost Kenya\"},\"image\":{\"@id\":\"https:\\\/\\\/www.truehost.com\\\/support\\\/#\\\/schema\\\/logo\\\/image\\\/\"}},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/www.truehost.com\\\/support\\\/#\\\/schema\\\/person\\\/2b1e998cb219f95acc7fb5d81efd5a7a\",\"name\":\"Jillian A.\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/b12d8634ee959e1b4b4ef35b8ea8e93625989e6b1c45a6ff9de8635f4734efb2?s=96&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/b12d8634ee959e1b4b4ef35b8ea8e93625989e6b1c45a6ff9de8635f4734efb2?s=96&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/b12d8634ee959e1b4b4ef35b8ea8e93625989e6b1c45a6ff9de8635f4734efb2?s=96&r=g\",\"caption\":\"Jillian A.\"},\"url\":\"https:\\\/\\\/www.truehost.com\\\/support\\\/author\\\/jillian\\\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"cPanel Security Patch -","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/truehost.com\/support\/cpanel-security-patch-truehost-cloud-client-guide\/","og_locale":"en_US","og_type":"article","og_title":"cPanel Security Patch -","og_description":"Truehost Cloud &nbsp;\u00b7&nbsp; cPanel VPS Security Advisory Critical cPanel Security Patch \u2014 Required Actions for Your VPS A serious security vulnerability has been identified in cPanel. This guide walks you through exactly what to do to protect your server. Published: April 30, 2026 &nbsp;\u00b7&nbsp; Affected: cPanel all versions after 11.40 &nbsp;\u00b7&nbsp; Truehost Cloud \ud83d\udea8 Urgent [&hellip;]","og_url":"https:\/\/truehost.com\/support\/cpanel-security-patch-truehost-cloud-client-guide\/","article_published_time":"2026-04-30T09:35:50+00:00","article_modified_time":"2026-05-06T10:38:09+00:00","author":"Jillian A.","twitter_card":"summary_large_image","twitter_misc":{"Written by":"Jillian A.","Est. reading time":"9 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/truehost.com\/support\/cpanel-security-patch-truehost-cloud-client-guide\/#article","isPartOf":{"@id":"https:\/\/truehost.com\/support\/cpanel-security-patch-truehost-cloud-client-guide\/"},"author":{"name":"Jillian A.","@id":"https:\/\/www.truehost.com\/support\/#\/schema\/person\/2b1e998cb219f95acc7fb5d81efd5a7a"},"headline":"cPanel Security Patch","datePublished":"2026-04-30T09:35:50+00:00","dateModified":"2026-05-06T10:38:09+00:00","mainEntityOfPage":{"@id":"https:\/\/truehost.com\/support\/cpanel-security-patch-truehost-cloud-client-guide\/"},"wordCount":1884,"commentCount":0,"publisher":{"@id":"https:\/\/www.truehost.com\/support\/#organization"},"articleSection":["Guides"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/truehost.com\/support\/cpanel-security-patch-truehost-cloud-client-guide\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/truehost.com\/support\/cpanel-security-patch-truehost-cloud-client-guide\/","url":"https:\/\/truehost.com\/support\/cpanel-security-patch-truehost-cloud-client-guide\/","name":"cPanel Security Patch -","isPartOf":{"@id":"https:\/\/www.truehost.com\/support\/#website"},"datePublished":"2026-04-30T09:35:50+00:00","dateModified":"2026-05-06T10:38:09+00:00","breadcrumb":{"@id":"https:\/\/truehost.com\/support\/cpanel-security-patch-truehost-cloud-client-guide\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/truehost.com\/support\/cpanel-security-patch-truehost-cloud-client-guide\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/truehost.com\/support\/cpanel-security-patch-truehost-cloud-client-guide\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.truehost.com\/support\/"},{"@type":"ListItem","position":2,"name":"cPanel Security Patch"}]},{"@type":"WebSite","@id":"https:\/\/www.truehost.com\/support\/#website","url":"https:\/\/www.truehost.com\/support\/","name":"","description":"Help In a Click","publisher":{"@id":"https:\/\/www.truehost.com\/support\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.truehost.com\/support\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/www.truehost.com\/support\/#organization","name":"Truehost Kenya","url":"https:\/\/www.truehost.com\/support\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.truehost.com\/support\/#\/schema\/logo\/image\/","url":"https:\/\/www.truehost.com\/support\/wp-content\/uploads\/2026\/04\/cropped-image_2026-04-16_174808866.png","contentUrl":"https:\/\/www.truehost.com\/support\/wp-content\/uploads\/2026\/04\/cropped-image_2026-04-16_174808866.png","width":240,"height":48,"caption":"Truehost Kenya"},"image":{"@id":"https:\/\/www.truehost.com\/support\/#\/schema\/logo\/image\/"}},{"@type":"Person","@id":"https:\/\/www.truehost.com\/support\/#\/schema\/person\/2b1e998cb219f95acc7fb5d81efd5a7a","name":"Jillian A.","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/b12d8634ee959e1b4b4ef35b8ea8e93625989e6b1c45a6ff9de8635f4734efb2?s=96&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/b12d8634ee959e1b4b4ef35b8ea8e93625989e6b1c45a6ff9de8635f4734efb2?s=96&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/b12d8634ee959e1b4b4ef35b8ea8e93625989e6b1c45a6ff9de8635f4734efb2?s=96&r=g","caption":"Jillian A."},"url":"https:\/\/www.truehost.com\/support\/author\/jillian\/"}]}},"_links":{"self":[{"href":"https:\/\/www.truehost.com\/support\/wp-json\/wp\/v2\/posts\/19070","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.truehost.com\/support\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.truehost.com\/support\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.truehost.com\/support\/wp-json\/wp\/v2\/users\/32"}],"replies":[{"embeddable":true,"href":"https:\/\/www.truehost.com\/support\/wp-json\/wp\/v2\/comments?post=19070"}],"version-history":[{"count":29,"href":"https:\/\/www.truehost.com\/support\/wp-json\/wp\/v2\/posts\/19070\/revisions"}],"predecessor-version":[{"id":19129,"href":"https:\/\/www.truehost.com\/support\/wp-json\/wp\/v2\/posts\/19070\/revisions\/19129"}],"wp:attachment":[{"href":"https:\/\/www.truehost.com\/support\/wp-json\/wp\/v2\/media?parent=19070"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.truehost.com\/support\/wp-json\/wp\/v2\/categories?post=19070"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.truehost.com\/support\/wp-json\/wp\/v2\/tags?post=19070"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}