CVE-2026-109989
Executive Summary
CVE-2026-109989 is a stored cross-site scripting (XSS) vulnerability in the Themify Popup plugin for WordPress, affecting all versions up to and including 1.4.7. The flaw arises because the popup_width_unit parameter is stored without adequate input sanitization and rendered without output escaping, allowing an authenticated user with Author-level privileges or higher to inject persistent JavaScript into site pages. Successful exploitation compromises any user who views the affected page, including administrators, enabling session theft and privileged actions performed in the context of the victim's browser. The vulnerability is currently unpatched and no public proof-of-concept is available.
This record — and 170,000+ others — are available via the ValtersIT API. One endpoint replaces five: NVD + GitHub CVE + CISA KEV + EPSS + Nuclei + Exploit-DB, unified.
No signup required
Technical Analysis
The vulnerability is a textbook instance of CWE-79 (Improper Neutralization of Input During Web Page Generation, commonly "stored XSS"). The attack surface is the WordPress administrative layer: the Themify Popup plugin exposes a configuration mechanism through which popup presentation attributes are set, and the popup_width_unit field is one such attribute. Because the plugin neither sanitizes the value on input nor escapes it on output, a value containing HTML/script markup is persisted in the WordPress database (within plugin settings or post/page content associated with a popup) and subsequently emitted into the HTML response without encoding.
Stored XSS differs materially from reflected XSS in terms of persistence and blast radius. Once the malicious value is saved, it survives page reloads, logouts, and browser restarts, and it fires on every rendering of the injected page for every visitor until the offending setting is purged from the database. The injection context is whatever the popup markup renders into — either as an attribute value (e.g., a CSS width-related unit field) or as inline markup depending on theme and template rendering. Attackers can defeat naive filtering by using event-handler attributes, malformed tags, or encoding tricks against the front-end renderer, but because the exact rendering context is not detailed in the available vulnerability description, the precise payload grammar cannot be stated with certainty. No specific function names, filter hooks, or source file paths are documented in the provided intelligence; implementation-level analysis is therefore limited to the vulnerability class.
The CVSS v3.1 vector (AV:N/AC:L/PR:L/UI:N/S:C/C:L/I:L/A:N) is instructive. Network attack vector and low attack complexity reflect remote, unauthenticated-delivery exploitation of an already-stored payload. Privileges Required: Low captures that the initial injector must be authenticated — specifically at Author level or above, which on standard WordPress installations means the ability to create and publish content. User Interaction: None is consistent with the persistent nature of the payload: no crafted URL is required to trigger execution. Scope: Changed is the key discriminator, indicating that successful exploitation breaches the security boundary between the vulnerable component and the broader application or hosting context — a script executing in the site's origin can act on behalf of administrators against WordPress administration endpoints. Confidentiality and Integrity impacts are Low, reflecting that scripts execute in the victim's browser with the privileges of that session rather than granting direct server-side control. Availability impact is None. The resulting base score is 6.4 (Medium).
Exploitation Scenarios
No public PoC is available; the attack chain below is inferred from the stored XSS vulnerability class and the documented parameter name.
Reconnaissance / target identification. The attacker enumerates WordPress sites running the Themify Popup plugin. Detection is straightforward because plugin assets are typically loaded from a predictable path under
/wp-content/, and the plugin's presence may be inferred from page markup or directory listings. The attacker then needs an authenticated foothold — a registered account with Author privileges or above. On many WordPress deployments, registration is open or contributor accounts are obtainable through social engineering or credential stuffing, and Author-level access is frequently granted to content contributors.Triggering the flaw class. While editing a popup configuration or associated content, the attacker supplies a crafted value for the
popup_width_unitparameter. Because the plugin does not sanitize the input before storage, the value is committed to the database and persists.Payload delivery. When any user — including an administrator previewing or browsing the site — loads a page on which the popup renders, the plugin emits the stored value into the HTML response without output escaping. The browser parses the injected content as markup/script and executes attacker-supplied JavaScript in the origin of the WordPress site. This is the canonical stored-XSS execution path; because User Interaction is None in the vector, no click or crafted link is required once the payload is planted.
Post-exploitation impact. In an attacker-controlled script context, the actor can exfiltrate session cookies or authentication tokens where they are not exclusively flagged HttpOnly, perform authenticated actions in the victim's session (e.g., modifying content, creating administrative users, or installing further plugins where the victim is an administrator), redirect visitors to phishing or malware-hosting pages, or use the compromised site as a watering-hole vector against its clientele. Because the injection is persistent, remediation requires purging the stored value, not merely cleaning a transitory request.
Impact Assessment
Business impact centers on integrity and trust of a public web property. The medium-severity base score of 6.4 understates the practical operational risk for WordPress sites that display popups to logged-in editors and administrators: an attacker with Author access can ladder a stored XSS into administrative takeover of the CMS, in which case the real-world effect approaches total site compromise. Because Scope is Changed, the vulnerable plugin's weakness can be leveraged beyond its own boundary into the surrounding WordPress application and any same-origin functionality. Blast radius is bounded only by popup visibility: the payload fires for every visitor who loads an affected page or triggers the popup, potentially across an entire content estate. Availability impact is none per the vector, but reputation and SEO damage (blacklisting, defacement, malicious redirects) can be substantial. The absence of a vendor patch and the lack of an EPSS score (not yet computed by FIRST.org) mean defenders should treat exploitation likelihood as non-trivial rather than negligible for exposed installations.
Detection Guidance
Sigma Rule
title: Themify Popup Stored XSS via popup_width_unit
id: 8e1a6b2c-4f3d-4c1e-9a7b-tmfy2026xss
status: experimental
description: Detects WordPress requests writing script-like content into the popup_width_unit parameter of the Themify Popup plugin.
references:
- https://nvd.nist.gov/vuln/detail/CVE-2026-109989
author: Valters IT Threat Intelligence
date: 2026/01/01
tags:
- attack.t1059.007
- attack.t1190
logsource:
category: webserver
detection:
selection_method:
cs-method:
- POST
- GET
selection_param:
- '|in|': 'popup_width_unit'
selection_payload:
c-uri|contains:
- 'popup_width_unit='
c-uri|re:
- '(?i)popup_width_unit=.*(<\s*script|%3cscript|onerror\s*=|onload\s*=|javascript:|%3c%2fscript)'
condition: selection_method and selection_param and selection_payload
fields:
- c-ip
- c-uri
- cs-method
- sc-status
falsepositives:
- Legitimate administrators editing popup settings with debug tooling
level: high
YARA Rule
rule WordPress_Themify_Popup_XSS_popup_width_unit
{
meta:
description = "Detects stored XSS payloads associated with CVE-2026-109989 in Themify Popup plugin configuration dumps or web artifacts"
author = "Valters IT Threat Intelligence"
date = "2026-01-01"
reference = "https://nvd.nist.gov/vuln/detail/CVE-2026-109989"
cve = "CVE-2026-109989"
strings:
$param = "popup_width_unit" ascii wide nocase
$script_tag = "<script" ascii wide nocase
$onerror = "onerror=" ascii wide nocase
$onload = "onload=" ascii wide nocase
$onfocus = "onfocus=" ascii wide nocase
$js_uri = "javascript:" ascii wide nocase
$svg = "<svg" ascii wide nocase
$iframe = "<iframe" ascii wide nocase
condition:
filesize < 2MB and
$param and
1 of ($script_tag, $onerror, $onload, $onfocus, $js_uri, $svg, $iframe)
}
Suricata IDS Rule
alert http any any -> any any (msg:"CVE-2026-109989 Themify Popup Stored XSS popup_width_unit injection attempt"; flow:to_server,established; http.method; content:"POST"; http.uri; content:"popup_width_unit"; nocase; http.uri; pcre:"/(<script|%3cscript|onerror=|onload=|javascript:)/i"; classtype:web-application-attack; reference:cve,2026-109989; sid:202600109989; rev:1;)
Elastic Detection
sequence by source.ip with maxspan=1m
[ network where http.method == "POST" and
wildcard(url.path, "*") ]
[ network where http.request.body.content : "*popup_width_unit*" and
(http.request.body.content : "*<script*" or
http.request.body.content : "*onerror=*" or
http.request.body.content : "*javascript:*") and
process.name == "php" ]
Splunk SPL Query
index=web sourcetype=access_combined OR sourcetype=apache OR sourcetype=nginx
(uri="*popup_width_unit*")
(form_data="*<script*" OR form_data="*onerror*" OR form_data="*onload*" OR form_data="*javascript:*" OR uri="*script*" OR uri="*%3Cscript*")
| eval m = mvfilter(match(_raw, "(?i)popup_width_unit"))
| stats count min(_time) as first_seen max(_time) as last_seen values(status) as statuses values(uri) as uris by src_ip host
| where count > 0
| sort - count
Wazuh OSSEC Rule
<group name="web,wordpress,xss,">
<rule id="2026001" level="10">
<if_sid>31100,31101,31103</if_sid>
<match>popup_width_unit</match>
<match type="pcre2">(?i)(%3cscript|<script|onerror=|onload=|javascript:)</match>
<description>CVE-2026-109989 - Possible Themify Popup stored XSS attempt via popup_width_unit parameter</description>
<mitre>
<id>T1059.007</id>
<id>T1190</id>
</mitre>
<group>web_attack,</group>
</rule>
</group>
Mitigation & Patch Guidance
Patch confidence is 0/4: no coherent patch evidence exists from tracked sources, and all versions up to and including 1.4.7 remain exposed. The single most effective control is removing the attack precondition — the presence of a plugin vulnerable to stored XSS — until a vendor fix appears.
Immediate mitigations. Disable and deactivate the Themify Popup plugin unless business-critical; if popups are essential, restrict access to the plugin's configuration and content editing to fully trusted accounts. Re-tier user privileges so that no account beyond necessary trusted editors holds Author-level rights; WordPress Authors can publish and are precisely the actor class this vulnerability arms. Enable HttpOnly and Secure flags on WordPress session cookies to blunt cookie exfiltration, deploy a Content-Security-Policy that blocks inline script execution and restricts script-src to first-party hosts, and maintain an uptime/integrity monitoring tool to detect unexpected DOM injections on rendered pages.
Patch / upgrade steps. No fixed version is published; monitor the vendor's plugin changelog and WordPress.org plugin repository for a release exceeding 1.4.7 and upgrade immediately upon availability. In the interim, audit existing popup and content settings for values containing markup or script syntax in
popup_width_unitand remove any suspicious entries directly. Where the plugin has been removed, purge its database remnants.Long-term hardening. Adopt a WordPress vulnerability management workflow: subscribe to plugin vulnerability feeds and CVE advisories, enforce least privilege for all CMS roles, restrict author-level registration, deploy a web application firewall with virtual patching for XSS patterns, and include content-rendering checks in periodic security reviews. Maintain an inventory of installed plugins and their versions to speed response when advisories land.
References
- NVD — CVE-2026-109989: https://nvd.nist.gov/vuln/detail/CVE-2026-109989
- MITRE CWE-79 — Improper Neutralization of Input During Web Page Generation (Cross-site Scripting): https://cwe.mitre.org/data/definitions/79.html
- MITRE ATT&CK T1059.007 — JavaScript/JScript: https://attack.mitre.org/techniques/T1059/007/
- WordPress Plugin Security / Hardening Guidance: https://developer.wordpress.org/plugins/wordpress-org/plugin-security/
- OWASP Cross Site Scripting Prevention Cheat Sheet: https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html
No known threat actor campaigns or in-the-wild exploitation are documented for this CVE at the time of writing. The vulnerability is not listed in CISA KEV, no public PoC or Nuclei template exists, and no EPSS score has been assigned by FIRST.org.
What is this? Security researchers use these exact search queries on Shodan.io (a search engine for internet-connected devices) to find vulnerable systems globally. You can copy these dorks to see if your organization's IP space is exposed.