From Public Nonce to Persistent Script Execution
Themify Builder registers tb_generate_on_fly through wp_ajax_nopriv_, so save_builder_css() in classes/class-themify-builder-stylesheet.php runs for logged-out visitors. The only gate is check_ajax_referer('tf_nonce'), and that nonce is printed into front-end HTML whenever a builder page's generated stylesheet is missing — a CSRF token, not an authentication barrier. sanitize_on_the_fly_css() whitelists breakpoint CSS but copies the attacker's fonts and cf_fonts maps through untouched. write_stylesheet() persists them in the themify_builder_google_fonts option, and loadGoogleFonts() later interpolates them into a double-quoted <link href> attribute guarded only by a first-character word check. The result is stored XSS that executes in every visitor's browser on the targeted published post — including administrators, which is what drives the changed CVSS scope.
BitFire FREE Stops the Delivery and the Payload
The attack starts as an automated, unauthenticated POST to /wp-admin/admin-ajax.php?action=tb_generate_on_fly — precisely the traffic BitFire FREE Bot Protection is built to stop. Restricted bots cannot POST data or call sensitive AJAX endpoints, and a client posing as a browser must pass JavaScript verification first, so the scripted delivery fails before WordPress loads the vulnerable handler. Allowlisted integrations bypass bot rules only — the WAF still inspects what they send. That second layer is decisive: the BitFire FREE WAF evaluates request content, and its cross-site scripting detection scans form fields and POST bodies, including the css[fonts] payload, blocking the malicious content before Themify Builder stores anything. Both controls ship in BitFire FREE for eligible non-commercial sites (commercial sites need the appropriate license), need no CVE-specific signature, and stop this exploit today.
Fixed in 7.8.2: Sanitized at Storage, Escaped at Output
Themify Builder 7.8.2 closes the chain at both ends. sanitize_on_the_fly_css() and write_stylesheet() now route every family and weight through themify_sanitize_builder_font_map(), which strips tags and control characters and rejects quotes, markup, and pipes outright — and the write-time re-check also neutralizes values already stored by 7.8.1. On the render side, loadGoogleFonts() replaces the one-character preg_match guard with the themify_is_safe_google_font_request() allowlist and wraps the link URL in esc_url(). Update immediately: running 7.8.1 leaves the injection path open on every published builder page. This is the defensive pattern BitFire enforces at the request layer even before you patch.
If Your Site Was Affected, Investigate for Persistence
Patching removes the known path; it does not undo a compromise that already happened. Injected script from CVE-2026-95864 executes in your visitors' browsers — including logged-in administrators — so treat any window on 7.8.1 as suspect: patch now, rotate administrator credentials and WordPress authentication salts, and hunt for persistence. BitFire Threat Hunter performs a thorough post-compromise investigation that surfaces backdoor WordPress administrator accounts, hidden database triggers, long-running PHP processes, and droppers capable of restoring malware or reinfecting the site. Absence of an obvious malicious file is not evidence you are clean — investigate, remove every persistence mechanism Threat Hunter finds, and re-verify.
Deploy BitFire, Patch, and Verify You Are Clean
Themify Builder trusted client input twice — at storage and at render — and version 7.8.1 paid for it with persistent script execution on public pages. BitFire breaks attacks in this class without waiting for a vendor patch: FREE Bot Protection stops the automated AJAX delivery, and the FREE WAF blocks the XSS payload in the request body before vulnerable code runs. If your site ran 7.8.1, update now, then investigate with BitFire Threat Hunter. Deploy BitFire FREE today and keep injected scripts off your pages.