Skip to content

Harden Optimization Detective XPath data against HTML-mangling plugins - #2694

Draft
sarthak-19 wants to merge 1 commit into
WordPress:trunkfrom
sarthak-19:fix/optimization-detective-xpath-id-mapping
Draft

sarthak-19 wants to merge 1 commit into
WordPress:trunkfrom
sarthak-19:fix/optimization-detective-xpath-id-mapping

Conversation

@sarthak-19

@sarthak-19 sarthak-19 commented Oct 2, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Fixes #1947.

Some plugins implement HTML "minification" using naive regular expressions that strip JS/CSS comments (e.g. preg_replace('@/\*(.*?)\*/@s', ...)). Because Optimization Detective writes raw XPath strings like /HTML/BODY/*[1][self::DIV] directly into data-od-xpath attributes, such plugins can mistake the /* in an XPath for the start of a JS/CSS comment and corrupt the page by swallowing everything up to the next */-like sequence.

Per the direction from the issue thread, this takes the larger approach rather than a simple base64_encode()/atob() of the attribute value:

  • Each tracked element now gets a small auto-incremented integer in a new data-od-id attribute instead of the raw XPath text.
  • The id → xpath mapping is shipped once in a SCRIPT tag as gzip-compressed, base64-encoded JSON (application/gzip+json;base64), falling back to plain JSON when gzencode() is unavailable server-side.
  • detect.js decompresses/parses this mapping at initialization and resolves data-od-id back to the original XPath.

This removes XPath text from the HTML entirely, which:

  • Fixes the reported corruption bug.
  • Shrinks the HTML payload.
  • Avoids search engines potentially trying to follow XPath-looking strings as crawlable URLs.

Extension API change

embed-optimizer/detect.js previously read data-od-xpath directly off the DOM via element.dataset.odXpath. Since the attribute no longer carries the XPath, a new getElementXPath(element) function is now exposed to extensions via the initialize()/finalize() args (added to InitializeArgs/FinalizeArgs in types.ts), and Embed Optimizer uses it instead.

image-prioritizer needed no changes — its tag visitors call $processor->get_xpath() directly during the PHP-side tag walk, independent of the HTML attribute.

AI TOOL

  • Used claudecode to generate HTML test changes and to generate descriptions / comments

Replace the data-od-xpath attribute, which embeds raw XPath text directly
in HTML, with an auto-incremented data-od-id attribute. The id-to-xpath
mapping is shipped once as a gzip-compressed, base64-encoded JSON SCRIPT
tag (falling back to plain JSON when gzip is unavailable) and decoded by
detect.js at initialization.

This prevents third-party "HTML minifier" plugins that use naive regular
expressions to strip JS/CSS comments from mistaking an XPath's /* for the
start of a comment and corrupting the page, while also shrinking the HTML
payload and avoiding search engines treating XPath strings as crawlable
URLs.

Embed Optimizer's detect.js, which previously read data-od-xpath directly
off the DOM, now resolves XPaths through a new getElementXPath() function
exposed to extensions via the initialize()/finalize() args.

Fixes WordPress#1947
@github-actions github-actions Bot added [Plugin] Optimization Detective Issues for the Optimization Detective plugin [Plugin] Embed Optimizer Issues for the Embed Optimizer plugin (formerly Auto Sizes) [Plugin] Image Prioritizer Issues for the Image Prioritizer plugin (dependent on Optimization Detective) labels Oct 2, 2026
@codecov

codecov Bot commented Oct 2, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 72.72727% with 6 lines in your changes missing coverage. Please review.
✅ Project coverage is 70.49%. Comparing base (1647b94) to head (3f3d87c).
⚠️ Report is 13 commits behind head on trunk.

Files with missing lines Patch % Lines
plugins/optimization-detective/detection.php 66.66% 6 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##            trunk    #2694      +/-   ##
==========================================
- Coverage   70.50%   70.49%   -0.01%     
==========================================
  Files          91       91              
  Lines        7869     7888      +19     
==========================================
+ Hits         5548     5561      +13     
- Misses       2321     2327       +6     
Flag Coverage Δ
multisite 70.49% <72.72%> (-0.01%) ⬇️
single 35.25% <0.00%> (-0.09%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

[Plugin] Embed Optimizer Issues for the Embed Optimizer plugin (formerly Auto Sizes) [Plugin] Image Prioritizer Issues for the Image Prioritizer plugin (dependent on Optimization Detective) [Plugin] Optimization Detective Issues for the Optimization Detective plugin

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Optimization Detective's XPath expressions in HTML can be erroneously interpreted as JS/CSS comments

1 participant