This is a loaded nail gun left on the counter, but only in shops that installed the optional trigger
CVE-2026-6960 is an arbitrary file upload bug in BookingPress Pro for WordPress. Per NVD and Wordfence, all versions up to and including 5.6 are affected, and 5.7 is the stated fixed version. The vulnerable path is the booking form submission handler bookingpress_validate_submitted_booking_form_func, where uploads tied to the Signature custom field are not properly type-validated; on an exposed site, that can let an unauthenticated attacker land a server-side file and turn it into remote code execution.
The vendor's 9.8/CRITICAL score is technically understandable because the impact is full site compromise and the attacker needs no credentials. But in real environments this is not a blanket internet-wide WordPress fire: exploitation only works when a site is running the Pro plugin, is still on <= 5.6, has a public booking form, and has the optional Signature field configured on that form. That hidden prerequisite materially shrinks the reachable population, so this lands as HIGH, not CRITICAL.
4 steps from start to impact.
Find a reachable BookingPress Pro booking flow
curl, browser DevTools, or Burp Suite to inspect front-end form behavior and backend AJAX requests. The goal is not just 'WordPress present' but 'BookingPress Pro booking form exposed to the internet.'- Public-facing WordPress site
- BookingPress Pro installed and actively used
- Booking form reachable without authentication
- Many enterprises do not run BookingPress at all
- This is a commercial Pro plugin, so install base is smaller than generic free plugins
- Some sites hide or restrict booking flows behind business logic, geo rules, or customer workflows
Confirm the optional Signature field exists
- Site operator enabled the Signature custom field in BookingPress Pro
- That field is attached to the reachable booking form path
- Signature is an optional premium feature, not a universal default
- Many deployments will never use handwritten-signature capture
- Even where the feature exists in the product, it may not be placed on the exposed form
Upload a disguised server-side payload
curl, or a simple PoC script, the attacker submits a crafted multipart request to the BookingPress AJAX flow described in public analysis, typically via wp-admin/admin-ajax.php with the bookingpress_validate_submitted_booking_form action. Because file type validation is missing on this path, a webshell or PHP polyglot can be uploaded under the guise of a signature/image artifact.- Vulnerable version <= 5.6
- Signature upload path reachable from the internet
- Web server and WordPress stack accept the upload request
- Reverse proxies or WAFs can block suspicious multipart requests to the BookingPress AJAX action
- Some stacks disallow executable handling in upload paths
- File permission or hardening differences can make the upload land but not execute
Execute the uploaded file for site takeover
- Uploaded file stored in a reachable location
- Server executes the file type instead of treating it as inert content
- Well-configured servers often disable PHP execution in
wp-content/uploads - EDR/FIM on the underlying host can catch new webshell artifacts
- Containerized or immutable hosting can reduce post-exploitation dwell time
wp-content/uploads, outbound command execution from php-fpm/Apache, and web requests to newly created script files.The supporting signals.
| In-the-wild status | As disclosed on 2026-05-21, I found no CISA KEV listing and no authoritative public report of active exploitation in the sources reviewed. That does not mean safe; it means the urgency is being driven more by impact than by observed campaign activity. |
|---|---|
| Proof-of-concept availability | A public Atomic Edge analysis published 2026-05-21 includes an inferred request path, WAF rule, and sample PoC logic targeting wp-admin/admin-ajax.php with action=bookingpress_validate_submitted_booking_form. |
| EPSS | Prompt-supplied EPSS = 0.00197 (~0.197% 30-day exploitation probability). I could confirm FIRST's EPSS methodology source, but not the live percentile for this CVE from browsed sources. |
| KEV status | Not listed in CISA's Known Exploited Vulnerabilities catalog in the sources reviewed. |
| CVSS vector reality check | CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H says pre-auth internet exploitable with total impact, which is true only if the deployment exposes the Signature-field workflow. The vendor description itself adds that hidden prerequisite. |
| Affected versions | BookingPress Pro <= 5.6 per Wordfence and NVD. |
| Fixed version | 5.7 per Wordfence. This is a commercial WordPress plugin path, so there is no distro backport story to lean on; you need the vendor update. |
| Exposure population | The vendor markets '100,000+ Users' for BookingPress overall, but the actually exploitable subset is much smaller: this CVE is Pro-only and requires the optional Signature field on a reachable public booking form. |
| Feature timeline that matters | The vendor changelog shows the Digital Signature field was added in version 4.4 on 2025-08-28. That matters because exploitability depends on a later-added premium feature, not the entire historical product base. |
| Researcher / disclosure | Wordfence credits researcher h0xilo and marks the issue publicly published on 2026-05-21. |
noisgate verdict.
The decisive factor is the configuration prerequisite: the bug is only reachable on sites that exposed the optional Signature custom field on a public BookingPress Pro form. That sharply reduces the real-world target pool, but when that prerequisite is met the attacker still gets a clean pre-auth path to full WordPress compromise.
Why this verdict
- Downgrade for hidden prerequisite: vendor/NVD both state exploitation only works if a Signature custom field is added to the booking form; that is a meaningful exposure filter, not a footnote.
- Still pre-auth and internet-reachable: no credentials, no prior foothold, and no user interaction are required once the vulnerable form exists, so this stays well above MEDIUM.
- Threat telemetry is weak so far: prompt-supplied EPSS 0.00197 is low, there is no KEV listing, and I found no authoritative active-exploitation reporting in the reviewed sources.
- Blast radius is full site takeover: arbitrary file upload on a PHP-backed WordPress host can become code execution, credential theft, content tampering, webshell persistence, and downstream abuse of shared hosting or adjacent secrets.
- Some modern controls can break the chain: WAF rules on the BookingPress AJAX action and 'no PHP execution in uploads' hardening materially raise friction in ways the raw CVSS base score ignores.
Why not higher?
This is not a universal pre-auth WordPress RCE across every BookingPress install. The exploit path depends on an optional premium feature being present on a reachable public form, and some hardened stacks will store uploads in places that do not execute PHP. Those two friction points are enough to keep it out of CRITICAL.
Why not lower?
Once the prerequisite is met, the rest of the chain is ugly: no auth, low complexity, and likely one-request compromise. A successful hit gives the attacker a direct path to server-side code execution on an internet-facing CMS, which is far too consequential for MEDIUM or LOW.
What to do — in priority order.
- Remove or disable Signature fields — If you cannot patch immediately, remove the Signature custom field from public booking forms or disable the affected booking workflow entirely. This directly breaks the documented prerequisite for exploitation and should be deployed within 30 days for a HIGH verdict.
- Block the BookingPress upload action at the edge — Add a reverse-proxy or WAF rule to scrutinize or block multipart uploads hitting
wp-admin/admin-ajax.phpwhen the action isbookingpress_validate_submitted_booking_form, especially for suspicious filenames, MIME mismatches, or PHP extensions. Treat this as the main temporary shield and deploy it within 30 days. - Disable script execution in upload paths — Enforce web-server policy so
wp-content/uploadsand any BookingPress-specific upload subdirectories cannot execute PHP or other server-side scripts. This does not fix the upload bug, but it can turn full RCE into a failed post-upload step; implement within 30 days. - Hunt for webshell artifacts — Review
wp-content/uploadsfor newly created.php, double-extension files, anomalous image/polyglot payloads, and suspicious timestamps near the disclosure window. Pair file review with HTTP logs for direct requests into upload directories; start immediately and complete the first sweep within 30 days. - Constrain egress from the web tier — If an attacker does land a shell, outbound restrictions from the PHP/Apache worker reduce follow-on staging, callback traffic, and data theft. This is blast-radius reduction, not prevention, and should be in place within 30 days.
- MFA on WordPress admin does nothing here because the attack path is unauthenticated and never touches the login flow.
- Generic perimeter vulnerability scanning is not enough because version detection alone cannot prove whether the Signature-field prerequisite is actually enabled.
- Relying on plugin auto-update assumptions is shaky here; BookingPress Pro uses a vendor-managed update path and may lag in environments without disciplined WordPress maintenance.
Crowdsourced verification payload.
Run this on the target WordPress host or an admin jump box with filesystem access to the site directory. Invoke it as sudo bash verify-bookingpress-cve-2026-6960.sh /var/www/html; read access to WordPress files is required, and WP-CLI is optional but helps with a best-effort check for the Signature-field prerequisite.
#!/usr/bin/env bash
# verify-bookingpress-cve-2026-6960.sh
# Purpose: Best-effort verification for CVE-2026-6960 on a WordPress host.
# Output: VULNERABLE / PATCHED / UNKNOWN
# Exit codes: 0=PATCHED, 1=VULNERABLE, 2=UNKNOWN, 3=usage/runtime error
set -u
WP_ROOT="${1:-}"
if [ -z "$WP_ROOT" ]; then
echo "UNKNOWN - usage: $0 /path/to/wordpress"
exit 3
fi
PLUGIN_DIR="$WP_ROOT/wp-content/plugins/bookingpress-appointment-booking-pro"
if [ ! -d "$PLUGIN_DIR" ]; then
echo "UNKNOWN - BookingPress Pro plugin directory not found: $PLUGIN_DIR"
exit 2
fi
find_version() {
local v=""
local candidates=(
"$PLUGIN_DIR/bookingpress-appointment-booking-pro.php"
"$PLUGIN_DIR/bookingpress-pro.php"
"$PLUGIN_DIR/bookingpress.php"
)
for f in "${candidates[@]}"; do
if [ -f "$f" ]; then
v=$(grep -Ei '^[[:space:]]*Version:[[:space:]]*' "$f" | head -n1 | sed -E 's/^[^:]+:[[:space:]]*//; s/[[:space:]]+$//')
[ -n "$v" ] && { echo "$v"; return 0; }
fi
done
if [ -f "$PLUGIN_DIR/readme.txt" ]; then
v=$(grep -Ei '^(Stable tag|Version):[[:space:]]*' "$PLUGIN_DIR/readme.txt" | head -n1 | sed -E 's/^[^:]+:[[:space:]]*//; s/[[:space:]]+$//')
[ -n "$v" ] && { echo "$v"; return 0; }
fi
return 1
}
verlte() {
[ "$1" = "$2" ] && return 0
[ "$(printf '%s\n%s\n' "$1" "$2" | sort -V | head -n1)" = "$1" ]
}
verlt() {
[ "$1" = "$2" ] && return 1
verlte "$1" "$2"
}
VERSION="$(find_version || true)"
if [ -z "$VERSION" ]; then
echo "UNKNOWN - could not determine installed BookingPress Pro version"
exit 2
fi
# Fast path: fixed version or newer.
if ! verlt "$VERSION" "5.7"; then
echo "PATCHED - BookingPress Pro version $VERSION"
exit 0
fi
# At this point version is <= 5.6, but exploitability depends on Signature field usage.
# Best-effort check using WP-CLI if available.
SIG_FOUND=0
WPCLI_FOUND=0
if command -v wp >/dev/null 2>&1; then
WPCLI_FOUND=1
# Search BookingPress-related options for the string 'signature'.
# This is heuristic because vendor option names may vary by version.
QUERY_RESULT=$(wp --path="$WP_ROOT" db query \
"SELECT option_name FROM $(wp --path='$WP_ROOT' db prefix 2>/dev/null)options WHERE option_name LIKE '%bookingpress%' AND option_value LIKE '%signature%';" \
--skip-column-names 2>/dev/null || true)
if [ -n "$QUERY_RESULT" ]; then
SIG_FOUND=1
fi
fi
if [ "$SIG_FOUND" -eq 1 ]; then
echo "VULNERABLE - BookingPress Pro version $VERSION and Signature-related BookingPress config found"
exit 1
fi
if [ "$WPCLI_FOUND" -eq 1 ]; then
echo "UNKNOWN - BookingPress Pro version $VERSION is in the vulnerable range, but Signature-field usage was not confirmed by heuristic WP-CLI inspection"
exit 2
else
echo "UNKNOWN - BookingPress Pro version $VERSION is in the vulnerable range; install WP-CLI or manually review BookingPress custom fields for Signature usage"
exit 2
fi
If you remember one thing.
Sources
What defenders are saying.
Crowdsourced verification outputs.
Results submitted by users who ran the verification payload against their environment.