
| Plugin Name | Funnel Builder by FunnelKit |
|---|---|
| Type of Vulnerability | Cross-Site Scripting (XSS) |
| CVE Number | CVE-2025-12878 |
| Urgency | Low |
| CVE Publish Date | 2026-02-01 |
| Source URL | CVE-2025-12878 |
Urgent: Stored XSS in Funnel Builder (FunnelKit) <= 3.13.1.2 — What WordPress Owners Need to Know and How WP‑Firewall Protects You
Author: WP‑Firewall Security Team
Date: 2026-02-02
Executive summary
A stored cross‑site scripting (XSS) vulnerability affecting Funnel Builder (FunnelKit) versions <= 3.13.1.2 was publicly disclosed on 2 February 2026 (CVE‑2025‑12878). The vulnerability allows an authenticated user with Contributor privileges to store JavaScript inside the plugin’s wfop_phone shortcode parameter which then executes in visitors’ browsers when the affected shortcode is rendered. The vendor released a patch in version 3.13.1.3.
This post explains, in practical terms:
- what the vulnerability is and why it matters;
- who is at risk and realistic attack scenarios;
- how to confirm whether your site is affected using WordPress/WP‑CLI/SQL searches;
- immediate mitigations and long‑term security hardening;
- how WP‑Firewall protects your site both now (virtual patching/WAF) and going forward.
This guidance is written from the WP‑Firewall security team perspective and assumes you want pragmatic steps you can apply today (staging first, always).
What happened — quick facts
- Affected plugin: Funnel Builder by FunnelKit (WordPress plugin).
- Vulnerable versions: <= 3.13.1.2
- Fixed in: 3.13.1.3
- Vulnerability type: Stored Cross‑Site Scripting (XSS)
- CVE: CVE‑2025‑12878
- Required privilege to exploit: Contributor
- CVSS: 6.5 (medium)
- Exploitation requires user interaction (visiting a page that renders the payload), but the payload is stored server‑side (so it persists and can affect many users).
Why stored XSS is dangerous (reminder)
Stored XSS occurs when an attacker can inject JavaScript (or HTML with script handlers) that is stored on the server (in posts, meta, plugin settings, etc.) and is later served to other users without proper sanitization or escaping. Consequences include:
- Session theft and account takeover (stealing cookies, session tokens);
- Privilege escalation if administrators view or edit the affected content;
- Delivering second‑stage payloads (malware, cryptomining scripts, phishing forms);
- Defacement or content injection that undermines trust and SEO;
- Persistent backdoors via malicious administrator settings injected by initial XSS.
Although Contributor is a relatively low privilege, stored XSS elevates the risk: an attacker with a Contributor account can create content containing the payload that will later run in the browser of any user — including administrators — who views the affected frontend or admin pages that render the shortcode.
Technical overview (what’s going on)
The vulnerability stems from insufficient input sanitization/escaping for data passed through the wfop_phone shortcode parameter. A Contributor user (who normally cannot publish, but can add content that may be saved in plugin forms, drafts, or other plugin-managed entities) can include HTML/JS payloads inside that parameter. When the plugin later renders the shortcode on a page, those payloads are output unescaped, allowing the browser to execute them.
Example (sanitized for safety):
- Malicious payload as stored input (displayed escaped):
<script>/* malicious JS */</script> - When the shortcode is rendered without escaping, the script runs in the visitor’s browser context.
Because this is stored (not reflected), the injected code persists until removed, and can affect many visitors or even site administrators who open the content in their browsers.
Realistic attack scenarios
- Attacker registers (or compromises) a Contributor account — many sites allow registration or have weak onboarding controls.
- The attacker creates content or updates a Funnel/element/form setting where
wfop_phoneis persisted with a script payload. - The site later publishes the funnel/form or an admin previews it, causing the payload to execute in the context of logged‑in users (including admins) or guests.
- The attacker’s script performs actions like:
- Steal cookies/session tokens (leading to account takeover).
- Create a new admin user via any available JS‑accessible endpoints.
- Inject a backdoor or redirect visitors to phishing/malware.
- Modify plugin/theme settings, embed an SEO spam page, etc.
Even if the site requires admin publishing, a Contributor can sometimes create content that an admin will preview — and previews can execute scripts in the admin browser.
How to check if your site is affected
First — always test in staging or offline copy of your site. Do not run unsafe payloads on production.
- Confirm plugin version
- Go to WordPress Admin → Plugins and check Funnel Builder / FunnelKit version.
- If you cannot access admin, inspect
wp-content/plugins/funnel-builderplugin headers in plugin files; checkreadme.txtorfunnel-builder.php.
- If you have SSH access, use WP‑CLI:
- List installed version:
wp plugin get funnel-builder --field=version
- Update plugin (see later section) if it’s vulnerable.
- List installed version:
- Search your database for
wfop_phoneoccurrences
Using phpMyAdmin, Adminer, or MySQL client, run (adjust table prefix if notwp_):SELECT ID, post_title, post_status FROM wp_posts WHERE post_content LIKE '%wfop_phone%';
Search postmeta:
SELECT post_id, meta_key, meta_value FROM wp_postmeta WHERE meta_value LIKE '%wfop_phone%';
Search options and other tables:
SELECT option_name, option_value FROM wp_options WHERE option_value LIKE '%wfop_phone%';
- Use WP‑CLI to search posts and options:
- Posts:
wp post list --post_type='any' --format=ids | xargs -I % wp post get % --field=post_content --raw | grep -n "wfop_phone"
- Search option values (careful with large databases):
wp db query "SELECT option_name FROM wp_options WHERE option_value LIKE '%wfop_phone%';"
- Posts:
- Scan with a security scanner (WP‑Firewall, malware scanners, or custom scripts) — look for occurrences of
<scriptorjavascript:inside any content or plugin data. - Audit users with Contributor role: look for recent signups, suspicious usernames, or sudden activity.
Immediate mitigations (what to do now — prioritized)
If your site runs a vulnerable FunnelKit version or you find suspicious wfop_phone occurrences, follow this prioritized list. Always work in staging before making production changes if possible.
- Update the plugin (best fix)
- Update Funnel Builder to 3.13.1.3 or later immediately via WordPress admin or WP‑CLI:
wp plugin update funnel-builder
- If auto‑update is not available, download the patched plugin from the official plugin repository and install.
- Update Funnel Builder to 3.13.1.3 or later immediately via WordPress admin or WP‑CLI:
- Temporarily disable the plugin
- If you cannot update immediately, temporarily deactivate Funnel Builder (admin → plugins) to prevent rendering the shortcode and stop script execution.
- Remove or neutralize affected shortcodes
- Replace occurrences of
[wfop_phone ...]usage in posts/pages with a safe placeholder until patched. - Run database updates to strip suspicious attributes:
UPDATE wp_posts SET post_content = REPLACE(post_content, '[wfop_phone', '[wfop_phone_removed') WHERE post_content LIKE '%wfop_phone%';
- Backup your DB before running any mass updates.
- Replace occurrences of
- Sanitize stored content
- Search for
<scriptand other event handlers in post content and plugin meta and remove them:SELECT ID, post_title FROM wp_posts WHERE post_content LIKE '%<script%';
- Search for
- Limit Contributor privileges (temporary)
- Change member roles; restrict the ability to create or edit forms/funnels for Contributors until the site is patched.
- Consider temporarily disabling front‑end registration or requiring admin approval for new users.
- Scan for indicators of compromise
- Look for new admin accounts, modified plugin/theme files, unknown scheduled tasks (cron), or files added to uploads.
- Check server logs for unusual POST requests or entries around the time a malicious payload may have been stored.
- Rotate secrets
- After confirming clean state, rotate salts, API keys, and any credentials that could have been leaked.
- Restore from backup if you find persistent backdoors
- If cleanup is incomplete or you detect deeper compromise, restore from a clean backup and apply all security patches.
WP‑Firewall protections — how we help
As a WordPress firewall and security provider, WP‑Firewall has multiple layers to protect sites from this class of vulnerability, even before plugin updates are applied:
- Virtual patching (WAF rule)
- We deploy virtual patches (WAF rules) that intercept requests attempting to store known exploit patterns in
wfop_phoneor other FunnelKit inputs. - Example WAF signature pattern we use (conceptual; actual rule uses hardened regex and context checks):
- Block HTTP POSTs/PUTs containing
wfop_phoneparameter values that include:<scriptor encoded variants (%3Cscript%3E)onerror=,onload=,javascript:,document.cookie, oreval(
- Conceptual regex to detect script tags or event handlers in parameter values:
(?i)(<\s*script\b|%3C\s*script|javascript:|on\w+\s*=|document\.cookie|eval\()
- We tune rules to avoid false positives (e.g., phone numbers containing
onsubstrings) by checking context and parameter names.
- We deploy virtual patches (WAF rules) that intercept requests attempting to store known exploit patterns in
- Response filtering
- WP‑Firewall can optionally sanitize outgoing HTML responses to remove inline
<script>tags inserted via shortcodes before they reach clients. This is a second line of defense and should be used carefully to avoid breaking benign functionality.
- WP‑Firewall can optionally sanitize outgoing HTML responses to remove inline
- Rate limiting and registration controls
- Block or throttle automated registrations and suspicious contributor account creation flows to reduce attacker account opportunities.
- File & integrity scanning
- We scan for newly added files, modified plugin/theme files, and suspicious changes that often accompany post‑exploitation activities.
- Activity monitoring & alerts
- Alerts for suspicious admin previews, content changes containing script-like payloads, and contributor account activity are available to administrators.
- Post‑incident support
- If you detect a compromise, WP‑Firewall support can help remove malicious code, restore safe states, and recommend hardening steps.
Note: virtual patching is a temporary emergency mitigation and should never be a permanent substitute for applying vendor patches. Always update to the fixed plugin version when available.
Recommended WAF rules (technical, for security teams)
Below are suggested detection rules you can implement in a WAF. These are illustrative — test rules in staging and avoid overly broad patterns to reduce false positives.
- Block POST requests where a parameter name contains
wfop_phoneand value includes<scriptor encoded script tag:
Condition: HTTP Method is POST/PUT
Parameter: body (form data) or JSON payload
Pattern:(?i)(wfop_phone).*?(%3C\s*script|<\s*script|javascript:|on\w+\s*=|document\.cookie|eval\(|window\.location)
- Block requests with
wfop_phoneparameter value containing suspicious JS event attributes:
Pattern:(?i)wfop_phone=.*(onerror|onload|onclick|onsubmit|onfocus)=
- Sanitize rendered content (response inspection)
Inspect output HTML for<scriptembedded underwfop_phone-related markup; remove or escape before responding. - Monitor and alert
If any request matches rule, log full request with timestamp, IP, user agent, and captured parameter values (store logs securely) and send admins an alert.
Important: WAF rules are powerful but require tuning for your site. Test extensively as phone fields sometimes legitimately contain characters that could trip naive rules (e.g., plus signs, parentheses, or localized number formats).
Incident response checklist (step‑by‑step)
If you find evidence of exploitation, use this structured checklist:
- Contain
- Deactivate the vulnerable plugin or apply the vendor patch.
- Activate WP‑Firewall protection rules and increase logging/alerts.
- Temporarily disable public user registration if abused.
- Investigate
- Identify when the malicious content was stored (timestamp).
- Identify the Contributor account(s) that stored the payload.
- Search for other instances of
wfop_phoneand other suspicious shortcodes. - Review server and access logs for attacker IPs and request patterns.
- Eradicate
- Remove malicious content from the DB (posts, postmeta, options).
- Remove any malicious files or unauthorized admin users.
- Clean up scheduled tasks (wp_cron hooks) created by the attacker.
- Recover
- Rotate all credentials that may have been exposed.
- Reapply security patches and confirm plugin is updated to 3.13.1.3 or later.
- Restore from a clean backup if integrity cannot be guaranteed.
- Lessons learned
- Review why the Contributor account existed and whether stricter onboarding or content moderation could reduce risk.
- Implement post‑incident hardening: 2FA, least privilege for roles, review auto‑publish workflows.
- Notify
- If sensitive user data or accounts were compromised, follow applicable breach notification policies and inform affected users.
Preventive hardening recommendations
- Principle of least privilege
- Review roles and capabilities. Contributors should only have what they need. Limit access to plugin admin pages.
- Require moderation and admin review
- Ensure contributor submissions are reviewed by editors/admins before being published. Avoid auto‑rendering editor drafts to admins without sanitization.
- Use input validation & sanitization
- Plugins that accept user content must sanitize inputs using standard WP functions:
- Use
wp_kses()for HTML whitelisting. - Escape output with
esc_html(),esc_attr(), orwp_kses_post()as appropriate.
- Use
- Plugins that accept user content must sanitize inputs using standard WP functions:
- Keep WordPress core, themes, and plugins updated
- Apply security patches promptly and maintain a staging process for testing.
- Enforce strong authentication
- Use 2FA for admin/editor accounts and enable strong password policies.
- Limit direct file edits and disable PHP exec where possible
- Prevent file editors in the dashboard to make it harder for attackers to persist server‑side backdoors.
- Ongoing monitoring
- File integrity monitoring, scheduled malware scans, and runtime WAF protection reduce dwell time for attackers.
Example queries and scripts (for site admins)
- Find posts containing the shortcode:
SELECT ID, post_title, post_status FROM wp_posts WHERE post_content LIKE '%[wfop_phone%';
- Find postmeta with suspicious script content:
SELECT post_id, meta_key FROM wp_postmeta WHERE meta_value REGEXP '<script|%3Cscript|on[a-z]+\\s*=';
- WP‑CLI search for suspicious strings:
wp search-replace '<script' '<!-- removed script -->' --all-tables --dry-run
Use
--dry-runfirst, then remove it to perform the replacement after verifying results.
Best practices for plugin publishers and site builders
If you build funnels, forms, or allow contributions from lower‑privileged users, follow these obligations:
- Always escape output. Never rely on user’s role to make unescaped output safe.
- Use server‑side sanitization, not just client‑side.
- Validate phone numbers strictly (only digits, plus sign, spaces, hyphens).
- Avoid injecting raw user content into inline HTML attributes without proper encoding.
- Implement a secure preview mechanism that neutralizes scripts during admin preview.
A practical example: safe phone field handling in code
If you are a developer updating plugin or theme code, ensure phone fields are sanitized/escaped. Example (conceptual PHP):
// When saving phone input:
$phone_input = isset($_POST['wfop_phone']) ? sanitize_text_field($_POST['wfop_phone']) : '';
// On output (shortcode rendering):
echo esc_attr( $phone_input ); // or wrap in appropriate markup using esc_html if rendering in text area
Never echo raw values directly into HTML attributes or content.
Sign up for WP‑Firewall Basic — protect your site today
Title: Start protecting your WordPress site for free with WP‑Firewall Basic
If you want a quick, frictionless way to add a protective layer while you patch or investigate, WP‑Firewall’s Basic (Free) plan delivers essential protection for WordPress sites. The Basic plan includes a managed firewall, WAF rules, unlimited bandwidth, a malware scanner, and mitigation for OWASP Top 10 risks — helping stop known exploit patterns like the FunnelKit wfop_phone XSS before they reach visitors’ browsers. For site owners who need more automation and deeper remediation, our paid plans add automatic malware removal, IP black/whitelisting, auto vulnerability virtual patching, and advanced remediation services. Sign up for WP‑Firewall’s free plan and add an emergency defensive layer to your site here: https://my.wp-firewall.com/buy/wp-firewall-free-plan/
Long‑term monitoring and assurance
After patching and cleaning up, keep monitoring:
- Weekly malware scans and file integrity checks.
- Alerts for new plugin installs or changes.
- Periodic searches for shortcodes and suspicious patterns.
- Regularly review user accounts, especially contributors.
Consider a staged rollout for automatic plugin updates and a process to quickly apply emergency patches site‑wide.
Final thoughts from the WP‑Firewall team
Stored XSS vulnerabilities in widely used plugins present a significant risk because they can turn low‑privileged accounts into powerful attack vectors. The FunnelKit wfop_phone issue is a clear example: a single unsanitized field can have outsized consequences.
The safe, correct response is layered:
- Patch at the source — update FunnelKit to 3.13.1.3 or later.
- Contain and clean — disable or sanitize affected content, review accounts.
- Protect in front — use a WAF/virtual patching layer (like WP‑Firewall) to block exploit attempts and monitor suspicious activity.
- Harden processes — limit roles, require moderation, and keep a rapid update pipeline in place.
We’re available to help WP administrators quickly implement emergency WAF rules, scan for suspicious content, and restore clean operation. If you’re not already running WP‑Firewall, our Basic (Free) plan gives you immediate firewall and malware scanning protection while you apply vendor patches. Get started: https://my.wp-firewall.com/buy/wp-firewall-free-plan/
Stay vigilant — these kinds of vulnerabilities are fairly common, and layered defenses plus fast patching dramatically reduce risk.
— WP‑Firewall Security Team
