As a WordPress security practitioner working with site owners every day, I want to give you a clear, practical guide to this vulnerability, explain real-world risks and detection options, and walk through immediate mitigations you can apply — whether you run a single blog or manage hundreds of client sites.
This vulnerability is a stored cross-site scripting (XSS) issue originating in the vc_custom_heading shortcode in WPBakery Page Builder. A user with the ability to add or edit content (the public disclosure indicates the required minimum privilege is a Contributor) can insert payloads that are stored in the database and later rendered on public pages. When that malicious content is viewed, the attacker’s script executes in visitors’ and potentially administrators’ browsers.
Below I’ll cover:
What exactly is wrong and why it matters
Who is at risk and realistic exploitation scenarios
How to find whether your site is vulnerable or already injected
Immediate and layered mitigations: update, virtual patching/WAF rules, content sanitization and hardening
Incident response if you discover an infection
How WP-Firewall protects you and a simple, secure path to get started
This is written from the perspective of a professional WordPress security team — pragmatic, focused on defender actions, and with remediation options you can apply right away.
Executive summary (short)
The vulnerability allows stored XSS via the vc_custom_heading shortcode in WPBakery Page Builder (<= 8.6.1). The plugin renders user-supplied heading content without adequate sanitization or escaping.
Fixed in WPBakery Page Builder 8.7. Upgrading the plugin to 8.7+ is the primary long-term fix.
Immediate mitigations include applying a WAF/virtual patch, removing or sanitizing dangerous shortcode content, auditing contributor-created content, and hardening user privileges.
If you suspect compromise, follow incident response steps: isolate, preserve evidence, scan and clean, rotate credentials.
Technical background — root cause explained
Shortcodes in WordPress are a mechanism that allows plugins and themes to declare a textual token that expands to HTML during content rendering (for example, [vc_custom_heading ...]). The WPBakery Page Builder plugin exposes many shortcodes to store visual components.
This issue is a classic stored XSS:
A user with the ability to create or edit content (Contributor or higher) inserts a crafted payload into a shortcode attribute or content field managed by the vc_custom_heading shortcode.
The plugin stores that content in the database (as part of the post content or post meta).
On page render, the plugin outputs the stored value into the HTML without adequate escaping or with a permissive filtering policy that allows script-capable attributes (for example, inline event handlers or unfiltered HTML).
When another user or visitor loads the page, the malicious script executes in their browser context.
Because the payload is stored, this is a persistent vector — it continues to affect visitors until cleaned.
Important context:
Required privilege: Contributor (per the disclosure) — that means non-admin user accounts obtained by registration, compromise or unvetted contributors can be abused.
Attack surface: primarily front-end visitors; however, an XSS that targets admin users (e.g., site editors or administrators who view the injected content in the admin area) can be escalated to remote code execution or site takeover via CSRF/JS-powered API calls.
Realistic exploitation scenarios
Malicious registered user (or attacker who registers) creates a page or post using WPBakery elements and places a payload in the heading field. The site publishes the content. Every visitor including admins who view that page can execute attacker-supplied JavaScript.
Compromised contributor account is used to inject payloads into frequently visited pages (home page, resource pages) to maximize spread and persistence.
An attacker crafts a payload that performs background requests to wp-admin/admin-ajax.php or REST API endpoints with the currently authenticated admin cookie — this can be used to create a new admin user, change settings, or upload a backdoor (depending on available endpoints and CSRF protections).
Advertising or redirect payloads that affect SEO and reputation, or credential phishing pages to harvest user credentials.
Drive-by malware: the injected JavaScript can include third-party payloads that attempt to deliver cryptomining scripts or redirect users to malicious sites.
Why this is more than an annoyance: stored XSS can lead to full admin takeover if the victim is an authenticated admin who visits a poisoned page. It’s also a privacy and trust problem for your users.
Who is at risk?
Any site running WPBakery Page Builder version <= 8.6.1.
Sites that allow users with Contributor or higher roles to publish or save content (e.g., membership/community sites, multi-author blogs, some e-commerce setups with vendor roles).
Sites that have not patched to 8.7+ and that do not have protective firewall rules or content sanitization.
If you host dozens or hundreds of WordPress sites or provide managed WordPress services for clients, treat this as a priority to assess and remediate even if your site has few contributors.
How to check your site — discovery & detection
The first step is to confirm whether WPBakery Page Builder is present and the plugin version.
Check plugin version
– WordPress admin: Plugins → Installed Plugins → find WPBakery Page Builder.
– If you cannot access admin or for a remote check, look for code references or readme files. The safest path is via the WordPress admin or via file inspection on the server.
Identify posts using the vulnerable shortcode
You want to find posts that contain the vc_custom_heading shortcode or suspicious HTML attributes.
SQL (run carefully, preferably on a staging copy):
– Find posts that reference the shortcode: SELECT ID, post_title FROM wp_posts WHERE post_content LIKE '%vc_custom_heading%';
– Find posts that include suspicious attributes or script-like content: SELECT ID, post_title FROM wp_posts WHERE post_content REGEXP '<(script|img|iframe|svg|object|embed)[[:space:]]|onerror=|onload=|javascript:';
WP-CLI (faster for multiple sites):
– wp post list --post_type=post,page --format=ids --field=ID --post_status=any --< use grep on content >
– Or export and grep: wp db export - && grep -R "vc_custom_heading" -n
Searching for stored payloads in user-supplied meta or page builder meta
– Page builders sometimes store configuration in post meta; search wp_postmeta.value for suspicious content: SELECT post_id, meta_key FROM wp_postmeta WHERE meta_value LIKE '%<script%' OR meta_value LIKE '%onerror=%' OR meta_value LIKE '%vc_custom_heading%';
Log and traffic indicators
– Unusual outbound requests from client browsers reported in analytics (referrer anomalies).
– New administrator accounts created without expected workflow or emails.
– An increase in errors or suspicious admin actions.
Scan using a reputable malware scanner or an endpoint that can detect suspicious inline JavaScript in posts and post meta. If you use a web application firewall with virtual patching, it may have already flagged or blocked attempted exploit traffic.
Note: Always operate on a backup or staging copy when performing bulk finds and replaces. Don’t modify production content blindly.
Immediate steps you must take (triage)
If you are running an affected version, prioritize actions in this order:
Update WPBakery Page Builder to 8.7 or later immediately.
– This is the single most important corrective step where possible.
– If the site cannot be updated instantly due to compatibility concerns, proceed with the mitigations below until you can patch.
Apply virtual patching (WAF rule) to block exploitation attempts.
– Block requests that attempt to submit shortcodes or suspect attributes via POSTs to post creation endpoints, admin-ajax endpoints and REST endpoints.
– Block requests containing patterns such as vc_custom_heading combined with event handlers (onerror, تحميل), <script> tags, or javascript: URIs.
Audit content produced by Contributor and Author accounts.
– Search posts/pages and post meta for vc_custom_heading and suspicious attributes.
– Remove or sanitize detected payloads or temporarily unpublish affected content.
Harden user privileges:
– Temporarily restrict or disable the ability for Contributors to publish or use page builder tools until you confirm site cleanliness.
– Use a stricter publish workflow: require editors or admins to review content from non-trusted users.
Rotate secrets and sessions where appropriate:
– Reset passwords for administrative users if you suspect any administrative account was exposed or if an admin visited a poisoned page.
– Invalidate active sessions where possible (force logout users — change salts or use tools to terminate sessions).
Take a full backup (files + database), then scan with malware scanner and perform manual inspection.
If you find active malicious scripts or backdoors, follow an incident response strategy (below).
Example WAF rules and virtual patching guidance
If you operate a web application firewall (WAF) or have ModSecurity/NGINX/Cloud WAF controls, you can deploy targeted rules that block exploit attempts while you patch. Below are defensive examples meant for site administrators and security teams.
Note: Rules should be tested in blocking and monitoring modes on staging before full production enforcement to avoid false positives.
ModSecurity example (conceptual — adapt to your ruleset syntax):
# Block attempts to submit vc_custom_heading with inline script or event attributes
SecRule REQUEST_BODY|ARGS|ARGS_NAMES "vc_custom_heading" "phase:2,deny,log,status:403,id:100001,msg:'Block attempt to exploit vc_custom_heading stored XSS',chain"
SecRule REQUEST_BODY|ARGS "(