Back to Intelligence

CVE-2026-78159: Unauthenticated RCE in The Events Calendar WordPress Plugin (CVSS 9.8) — Detection and Remediation Guide

SA
Security Arsenal Team
September 12, 2026
13 min read

The NVD has published CVE-2026-78159, a CVSS 9.8 (CRITICAL) unauthenticated remote code execution vulnerability in The Events Calendar plugin for WordPress — one of the most widely deployed event-management plugins in the WordPress ecosystem, with hundreds of thousands of active installations across corporate sites, nonprofits, universities, local governments, and healthcare organizations. The flaw affects all versions up to and including 6.17.3 and is exploitable over the network with no authentication, no privileges, and no user interaction beyond a prerequisite that exists on a large share of real-world deployments.

The vulnerability lives in the parse_array function within Element_Classes, where insufficient validation of the widget 'classes' map allows a plain-array malicious payload to bypass the is_safe_widget_instance() object-type check and flow into a callable-invocation sink. The practical result: an unauthenticated attacker can invoke arbitrary PHP callables on the server — which in a WordPress/PHP context is a short step to full remote code execution, webshell deployment, and complete compromise of the web host.

There is one important exploitation precondition: the targeted site must have comments enabled on tribe_events posts, and at least one comment must exist to reach the vulnerable code path. This precondition reduces the blast radius somewhat — but The Events Calendar is frequently deployed with community interaction enabled, and many site owners never audited the comment status of their event custom post type. Do not assume you are safe. Verify.

If you run The Events Calendar anywhere in your WordPress fleet, treat this as a drop-everything patch event. This post covers the technical mechanics, concrete detection content for your SOC, and exact remediation steps.

Technical Analysis

Affected Products and Versions

ItemDetail
CVECVE-2026-78159
CVSS v3.19.8 (CRITICAL) — Network attack vector
Affected softwareThe Events Calendar plugin for WordPress
Affected versionsAll versions up to and including 6.17.3
Vulnerable componentElement_Classes::parse_array() — widget 'classes' map handling
Authentication requiredNone (unauthenticated)
Exploitation preconditionComments enabled on tribe_events posts AND at least one existing comment
ImpactUnauthenticated PHP callable invocation → remote code execution → full web server compromise

How the Vulnerability Works — Defender's View

This is a type-confusion / insufficient-validation flaw leading to a callable-invocation sink, a pattern we've seen repeatedly in WordPress plugin vulnerabilities. The attack chain:

  1. Entry point — comment rendering on tribe_events: The plugin processes widget configuration data when rendering event pages that include comments. The vulnerable path is only reachable when comments are enabled on the event custom post type and at least one comment exists, because the comment-rendering flow is what exercises the widget class-parsing logic.

  2. The validation failure: Element_Classes::parse_array() is supposed to receive a safe widget instance. It calls is_safe_widget_instance() as a guardrail — but that guardrail performs an object check. The critical mistake: the validation does not adequately constrain the 'classes' map within the input structure.

  3. The bypass: By supplying the malicious payload as a plain PHP array rather than an object, the attacker walks the input around the is_safe_widget_instance() object check entirely. The unsanitized array contents — including attacker-controlled strings representing function names or [class, method] callable pairs — survive validation.

  4. The sink: The attacker-controlled data reaches a callable-invocation sink inside parse_array() — PHP constructs such as call_user_func() / call_user_func_array() or dynamic {$callable}(...) invocation. At this point the attacker controls what gets invoked. Depending on what's callable in the environment (and with WordPress's enormous function surface, plenty is), this is leveraged into arbitrary code execution: writing a webshell into wp-content/uploads/, spawning system commands via system()/shell_exec()/passthru(), or loading additional payloads.

  5. Post-exploitation: Expect the standard WordPress-compromise playbook — webshell droppers in upload directories, rogue administrator account creation, malicious plugin/theme installation, injected SEO spam or credit-card skimmers for e-commerce-adjacent sites, and use of the host as phishing infrastructure or a pivot point.

Why the Precondition Matters — and Why You Can't Rely on It

The requirement for comments on tribe_events posts with at least one existing comment is a genuine attack-surface reducer. But consider:

  • Comments are on by default for posts in WordPress, and many event-driven sites (community calendars, churches, venues, universities, municipalities) deliberately enable discussion on events.
  • The comment requirement is trivially satisfiable on any site where visitors have ever engaged with an event listing.
  • Site administrators routinely do not know the comment status of their custom post types until they check.

CVSS 9.8 reflects the reality that across the deployed base, the precondition is met often enough — and the impact is catastrophic enough — that this must be treated as a network-exploitable unauthenticated RCE. Given the pattern of WordPress plugin vulnerabilities, expect PoC publication and mass scanning within days to weeks of disclosure. Historically, critical unauthenticated WordPress plugin RCEs are weaponized by automated botnets almost immediately after technical details circulate.

Exploitation Status

At the time of writing, the vulnerability is newly published to NVD. No public confirmation of in-the-wild exploitation or CISA KEV listing exists yet — but the unauthenticated, network-exploitable nature of the flaw, combined with the plugin's install base, makes rapid weaponization highly probable. Operate as if exploitation is imminent. Monitor the NVD entry and CISA KEV for status changes.

Detection & Response

Web-layer PHP RCE is best detected at two layers: (1) the HTTP request layer (suspicious payloads targeting event/comment endpoints) and (2) the host layer (the web server process doing things a web server should never do — spawning shells, writing executable files to upload directories). The host-layer detections are the higher-fidelity signals and should be prioritized.

Sigma Rules

YAML
---
title: Web Server Process Spawning Shell or System Utility - Possible WordPress Plugin RCE
id: 3f8a1c92-7d4e-4b6a-9f31-2c5e8a7b1d40
status: experimental
description: Detects web server or PHP-FPM worker processes spawning command shells or system utilities, consistent with post-exploitation after unauthenticated PHP code execution such as CVE-2026-78159 (The Events Calendar parse_array callable injection).
references:
  - https://nvd.nist.gov/vuln/detail/CVE-2026-78159
  - https://attack.mitre.org/techniques/T1059/
author: Security Arsenal
date: 2026/04/06
tags:
  - attack.execution
  - attack.t1059.004
logsource:
  category: process_creation
  product: linux
detection:
  selection_parent:
    ParentImage|endswith:
      - '/apache2'
      - '/httpd'
      - '/nginx'
      - '/php-fpm'
      - '/php-fpm7.4'
      - '/php-fpm8.0'
      - '/php-fpm8.1'
      - '/php-fpm8.2'
      - '/php-fpm8.3'
      - '/litespeed'
  selection_child:
    Image|endswith:
      - '/sh'
      - '/bash'
      - '/dash'
      - '/zsh'
      - '/curl'
      - '/wget'
      - '/nc'
      - '/ncat'
      - '/netcat'
      - '/python'
      - '/python3'
      - '/perl'
      - '/base64'
      - '/id'
      - '/whoami'
  condition: selection_parent and selection_child
falsepositives:
  - Legitimate WordPress plugins invoking system binaries (rare - image optimizers, backup tools); investigate parent PHP script context
level: high
---
title: Executable or PHP File Written to WordPress Uploads Directory
id: 9c2e5b17-4a8d-4f63-b820-6d1a3e9c5f72
status: experimental
description: Detects creation of PHP or script files inside WordPress uploads directories, a hallmark of webshell deployment following plugin RCE exploitation such as CVE-2026-78159.
references:
  - https://nvd.nist.gov/vuln/detail/CVE-2026-78159
  - https://attack.mitre.org/techniques/T1505/003/
author: Security Arsenal
date: 2026/04/06
tags:
  - attack.persistence
  - attack.t1505.003
logsource:
  category: file_event
  product: linux
detection:
  selection_path:
    TargetFilename|contains:
      - '/wp-content/uploads/'
  selection_ext:
    TargetFilename|endswith:
      - '.php'
      - '.phtml'
      - '.php3'
      - '.php4'
      - '.php5'
      - '.php7'
      - '.phar'
      - '.sh'
  condition: selection_path and selection_ext
falsepositives:
  - Rare legitimate plugin behavior writing PHP into uploads; verify with file content review and plugin inventory
level: critical
---
title: Suspicious Payload Patterns in WordPress Comment and Event Endpoint Requests
id: 5b7d3e04-1f92-4c58-a673-8e2f4b6d9a13
status: experimental
description: Detects HTTP requests to WordPress comment-processing and tribe_events endpoints containing PHP callable-injection indicators such as call_user_func references, serialized structures, or system command strings, consistent with exploitation attempts against The Events Calendar parse_array flaw (CVE-2026-78159).
references:
  - https://nvd.nist.gov/vuln/detail/CVE-2026-78159
  - https://attack.mitre.org/techniques/T1190/
author: Security Arsenal
date: 2026/04/06
tags:
  - attack.initial_access
  - attack.t1190
logsource:
  category: webserver
detection:
  selection_uri:
    cs-uri|contains:
      - '/wp-comments-post.php'
      - '/wp-json/wp/v2/comments'
      - 'tribe_events'
      - '/events/'
  selection_payload:
    cs-uri|contains:
      - 'call_user_func'
      - 'is_safe_widget_instance'
      - 'system('
      - 'shell_exec'
      - 'passthru'
      - 'base64_decode'
      - 'php://input'
      - 'a:2:{i:0'
  condition: selection_uri and selection_payload
falsepositives:
  - Security researchers and vulnerability scanners; tune against authorized scanning source IPs
level: high

KQL — Microsoft Sentinel / Defender

The query below hunts across Syslog/CEF-ingested web and audit logs for the two highest-fidelity signals: web-tier processes executing shells, and requests carrying callable-injection payloads against WordPress comment/event endpoints. Deploy it as a scheduled analytic rule with a 4-hour lookback during the exposure window.

KQL — Microsoft Sentinel / Defender
let Lookback = 4h;
let SuspiciousChildren = dynamic(["/bin/sh","/bin/bash","/bin/dash","curl","wget","nc","ncat","python","python3","perl","base64","whoami"]);
let WebParents = dynamic(["apache2","httpd","nginx","php-fpm","litespeed"]);
union isfuzzy=true
    (Syslog
    | where TimeGenerated >= Lookback
    | where ProcessName in~ (WebParents) or SyslogMessage has_any ("php-fpm","apache2","nginx")
    | where SyslogMessage has_any (SuspiciousChildren)
    | project TimeGenerated, Computer, ProcessName, SyslogMessage, Source="Syslog"),
    (CommonSecurityLog
    | where TimeGenerated >= Lookback
    | where RequestURL has_any ("wp-comments-post.php","/wp-json/wp/v2/comments","tribe_events")
    | where RequestURL has_any ("call_user_func","system(","shell_exec","passthru","base64_decode","php://input")
         or AdditionalExtensions has_any ("call_user_func","shell_exec","base64_decode")
    | project TimeGenerated, SourceIP, DestinationHostName, RequestURL, RequestMethod, Source="CEF"),
    (DeviceProcessEvents
    | where TimeGenerated >= Lookback
    | where InitiatingProcessFileName has_any ("apache2","httpd","nginx","php-fpm","w3wp.exe")
    | where FileName in~ ("sh","bash","dash","curl","wget","nc","ncat","python","python3","perl","cmd.exe","powershell.exe")
    | project TimeGenerated, DeviceName, InitiatingProcessFileName, FileName, ProcessCommandLine, AccountName, Source="MDE")
| sort by TimeGenerated desc

Velociraptor VQL

Use this hunt artifact across your Linux web hosts to identify webshell artifacts in uploads directories and anomalous web-server child processes — the two most reliable post-exploitation indicators for this class of flaw.

VQL — Velociraptor
-- Hunt for PHP webshells in WordPress uploads and suspicious web-server child processes
-- Context: CVE-2026-78159 The Events Calendar unauthenticated RCE post-exploitation

-- Part 1: PHP/script files recently written under wp-content/uploads
SELECT FullPath, Size, Mtime, Ctime,
       read_file(filename=FullPath, length=512) AS FileHead
FROM glob(globs=[
    '/var/www/**/wp-content/uploads/**/*.php',
    '/var/www/**/wp-content/uploads/**/*.phtml',
    '/var/www/**/wp-content/uploads/**/*.phar',
    '/srv/www/**/wp-content/uploads/**/*.php',
    '/home/**/public_html/wp-content/uploads/**/*.php'
])
WHERE Mtime > now() - 604800

-- Part 2: web/PHP processes with suspicious command lines or children
SELECT Pid, Ppid, Name, Exe, CommandLine, Username, CreateTime
FROM pslist()
WHERE (Name =~ 'apache2|httpd|nginx|php-fpm|litespeed'
       AND CommandLine =~ 'curl |wget |/bin/sh|/bin/bash|base64 -d|nc -|python -c|perl -e')
   OR CommandLine =~ 'wp-content/uploads.*\.php'

Verification & Hardening Script

Run this Bash script on each WordPress host (or via your configuration-management/orchestration tooling across the fleet). It inventories The Events Calendar installations, reports versions, checks the tribe_events comment precondition, and applies compensating controls. It uses wp-cli where available — the standard for scripted WordPress administration.

Bash / Shell
#!/bin/bash
# CVE-2026-78159 - The Events Calendar RCE: inventory, verify, and harden
# Run as a user with filesystem access to WordPress roots; wp-cli operations need the WP owner context.

set -uo pipefail

WP_ROOTS=("/var/www" "/srv/www" "/home")
VULN_MAX="6.17.3"
REPORT="/tmp/cve-2026-78159-report-$(date +%Y%m%d-%H%M%S).txt"

echo "=== CVE-2026-78159 Exposure Assessment ===" | tee "$REPORT"

# Locate all The Events Calendar plugin installs
find "${WP_ROOTS[@]}" -type f -path "*/wp-content/plugins/the-events-calendar/the-events-calendar.php" 2>/dev/null | while read -r PLUGIN; do
  WP_DIR=$(echo "$PLUGIN" | sed 's#/wp-content/plugins/the-events-calendar/the-events-calendar.php##')
  VERSION=$(grep -m1 -oP "Version:\s*\K[0-9.]+" "$PLUGIN" 2>/dev/null || echo "unknown")
  echo "[FOUND] $WP_DIR | The Events Calendar version: $VERSION" | tee -a "$REPORT"

  # Version comparison: flag anything <= 6.17.3
  if [ "$VERSION" != "unknown" ] && [ "$(printf '%s\n%s\n' "$VERSION" "$VULN_MAX" | sort -V | head -n1)" = "$VERSION" ] && [ "$VERSION" != "$VULN_MAX" -o "$VERSION" = "$VULN_MAX" ]; then
    if [ "$(printf '%s\n%s\n' "$VERSION" "$VULN_MAX" | sort -V | tail -n1)" = "$VULN_MAX" ]; then
      echo "  [VULNERABLE] Version $VERSION is at or below $VULN_MAX - UPDATE IMMEDIATELY" | tee -a "$REPORT"

      # Attempt update via wp-cli if available
      if command -v wp >/dev/null 2>&1; then
        echo "  [ACTION] Attempting wp-cli plugin update..." | tee -a "$REPORT"
        (cd "$WP_DIR" && wp plugin update the-events-calendar --allow-root 2>&1) | tee -a "$REPORT"
      fi

      # Compensating control: disable comments on tribe_events post type
      if command -v wp >/dev/null 2>&1; then
        echo "  [ACTION] Closing comments on all tribe_events posts..." | tee -a "$REPORT"
        (cd "$WP_DIR" && wp post list --post_type=tribe_events --format=ids --allow-root 2>/dev/null | \
          xargs -r -n50 wp post update --comment_status=closed --allow-root 2>&1) | tee -a "$REPORT"
      fi
    fi
  else
    echo "  [OK] Version $VERSION appears patched (verify against vendor advisory)" | tee -a "$REPORT"
  fi

done

# Hunt for webshell indicators: PHP files in uploads modified in the last 14 days
echo "" | tee -a "$REPORT"
echo "=== Webshell Sweep: PHP files under uploads (last 14 days) ===" | tee -a "$REPORT"
find "${WP_ROOTS[@]}" -type f \( -name "*.php" -o -name "*.phtml" -o -name "*.phar" \) \
  -path "*/wp-content/uploads/*" -mtime -14 2>/dev/null | tee -a "$REPORT"

echo "" | tee -a "$REPORT"
echo "Report saved to $REPORT. Manually review any webshell hits before removal."

Remediation

1. Patch immediately. Update The Events Calendar to a version greater than 6.17.3 via the WordPress admin dashboard (Plugins → Installed Plugins → Update) or via wp plugin update the-events-calendar. Confirm the installed version after update and re-check the plugin's changelog for the security fix referencing the parse_array/is_safe_widget_instance() validation. Monitor the NVD entry for CVE-2026-78159 and the vendor's release notes for the exact fixed version number and any follow-on releases.

2. Remove the exploitation precondition — even after patching. Until you are certain every site is on a patched version, disable comments on tribe_events posts: in WordPress admin (Events → edit each event → Discussion → uncheck "Allow comments"), or at scale via wp-cli (wp post list --post_type=tribe_events --format=ids | xargs wp post update --comment_status=closed). Also review Settings → Discussion and disable comments site-wide if your business use case doesn't require them. This is good hygiene independent of this CVE — comment surfaces are perennial injection vectors.

3. If you cannot patch immediately, take the plugin offline or isolate the site. Deactivate The Events Calendar until the update can be applied, or place the site behind WAF rules blocking requests containing callable-injection patterns (call_user_func, serialized array structures in comment bodies, php://input) targeting /wp-comments-post.php, the REST comments endpoint, and event permalinks. Note: WAF rules are a speed bump, not a fix — determined attackers will probe for filter bypasses. Patch remains the only durable remediation.

4. Assume compromise on exposed sites and hunt. For any site that was running a vulnerable version with comments enabled on events at the time of disclosure: sweep wp-content/uploads/ for PHP files, audit the wp_users table for rogue administrator accounts, review wp-content/plugins/ and wp-content/themes/ for unrecognized additions, check cron/scheduled tasks (wp cron event list), and examine web access logs for POST requests to comment endpoints containing unusual payloads in the days surrounding disclosure. If indicators are found, treat it as a full IR engagement — rebuild from known-good backups and rotate all credentials (database, admin, API keys, salts/keys in wp-config.php).

5. Harden the platform going forward. Deploy the Sigma rules above and ensure PHP-FPM/web-server process telemetry is flowing to your SIEM. Block PHP execution in the uploads directory at the web-server level (e.g., an Nginx location rule or Apache .htaccess denying .php execution under uploads/) — this breaks the most common webshell-landing pattern for plugin RCEs. Enforce automatic updates for WordPress plugins with a staging validation step, and maintain a current inventory of every plugin on every site so the next CVSS 9.8 doesn't require a scavenger hunt to assess exposure.

Related Resources

Security Arsenal Penetration Testing Services AlertMonitor Platform Book a SOC Assessment vulnerability-management Intel Hub

Is your security operations ready?

Get a free SOC assessment or see how AlertMonitor cuts through alert noise with automated triage.